Professional iOS Network Programming

As the iPhone and iPad grow in popularity, there is a growing demand for applications that are focused on data. Developers need to know how to get data onto these devices, deal with and create data, and communicate with external services—this book satisfies that need.

Professional iOS Network Programming

Jack Cox, Nathan Jones, John Szumski


320 Pages

1202 Reads

60 Downloads

English

PDF Format

5.08 MB

iOS App Development

Download PDF format

  • Jack Cox, Nathan Jones, John Szumski   
  • 320 Pages   
  • 20 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    CONTENTSactionGoTo:5,PartactionGoTo:5, I:actionGoTo:5, UnderstandiactionGoTo:5,ngactionGoTo:5, iOSactionGoTo:5, andactionGoTo:5, EnterpriseactionGoTo:5, NetworkingactionGoTo:6,ChapteractionGoTo:6, 1:actionGoTo:6, IntroducingactionGoTo:6, iOSactionGoTo:6, NetworkingactionGoTo:6, CapabilitieactionGoTo:6,sactionGoTo:6,UnderstandingactionGoTo:6, theactionGoTo:6, NetworkingactionGoTo:6, FrameworksactionGoTo:7,iOSactionGoTo:7, NetworkingactionGoTo:7, APIsactionGoTo:10,RunactionGoTo:10, read more..

  • Page - 3

    actionGoTo:91,UnderstandingactionGoTo:91, ErroractionGoTo:91, SourcesactionGoTo:100,RulesactionGoTo:100, ofactionGoTo:100, ThumbactionGoTo:100, foractionGoTo:100, HandlingactionGoTo:100, ErrorsactionGoTo:102,GracefullyactionGoTo:102, HandlingactionGoTo:102, NetworkactionGoTo:102, ErrorsactionGoTo:113,SummaryactionGoTo:114,PartactionGoTo:114, III:actionGoTo:114, AdvancedactionGoTo:114, NetworkingactionGoTo:114, TechniquesactionGoTo:115,ChapteractionGoTo:115, 6:actionGoTo:115, read more..

  • Page - 4

    actionGoTo:198,ChapteractionGoTo:198, 10:actionGoTo:198, UsingactionGoTo:198, PushactionGoTo:198, NotificationsactionGoTo:199,SchedulingactionGoTo:199, LocalactionGoTo:199, NotificationsactionGoTo:207,RegisteringactionGoTo:207, andactionGoTo:207, RespondingactionGoTo:207, toactionGoTo:207, RemoteactionGoTo:207, NotificationsactionGoTo:229,UnderstandingactionGoTo:229, NotificationactionGoTo:229, BestactionGoTo:229, PracticesactionGoTo:231,SummaryactionGoTo:232,PartactionGoTo:232, read more..

  • Page - 5

    PART IUnderstanding iOS and Enterprise NetworkingCHAPTER 1: Introducing iOS Networking CapabilitiesCHAPTER 2: Designing Your Service Architecture read more..

  • Page - 6

    Chapter 1Introducing iOS Networking CapabilitiesWHAT’S IN THIS CHAPTER?Understanding the iOS networking frameworksKey networking APIs available to developersUsing your application’s run Loop effectivelyGreat iOS applications require a simple and intuitive user interface. Likewise, great applications thatcommunicate with a web service of any kind require a well-architected networking layer. Anapplication’s architecture must be designed with the flexibility to adapt to changing requirements read more..

  • Page - 7

    Each iOS application sits on top of a networking framework stack composed of four levels. At thetop is the Cocoa level, which includes the Objective-C APIs for URL loading, Bonjour, and GameKit. Below Cocoa sits Core Foundation, a set of C APIs that includes CFNetwork, the foundation ofmost application-level networking code. CFNetwork provides a simple networking interface that sitson top of CFStream and CFSocket. Those two classes are lightweight wrappers around BSD sockets,which form the read more..

  • Page - 8

    NSURLConnection is a Cocoa level API that provides a simple method to load URL requests, whichcan interact with a web service, fetch an image or video, or simply retrieve a formatted HTMLdocument. It is built on top of NSStream and was designed with optimized support for the four mostcommon URI schemes: file, HTTP, HTTPS, and FTP. Although NSURLConnection restricts theprotocols over which you can communicate, it abstracts much of the lower-level work required toread and write from buffers, read more..

  • Page - 9

    NSStream is a Cocoa level API built on top of CFNetwork that serves as the foundation forNSURLConnection and is intended for lower-level networking tasks. Much like NSURLConnection,NSStream provides a mechanism to communicate with remote servers or local files. However, youcan use NSStream to communicate over protocols such as telnet or SMTP that are not supported byNSURLConnection.The additional control that NSStream provides does come at a cost. NSStream does not have built-in support for read more..

  • Page - 10

    As you implement the various network APIs, you must understand how they integrate with yourapplication. The next section discusses the concept of run loops, which monitor for network events(among other things) from the operating system and relay those events to your application.RUN LOOPSRun loops, represented by the class NSRunLoop, are a fundamental component of threads that enablethe operating system to wake sleeping threads to manage incoming events. A run loop is a loopconfigured to schedule read more..

  • Page - 11

    Run Loop ModesEach pass through the run loop is run in a specific mode specified by you. Run loop modes are aconvention used by the operating system to filter the sources that are monitored and allowed todeliver events, such as calling a delegate method. Modes include the input sources and timers thatshould be monitored as well as any observers that should be notified of run loop events.There are two predefined run loop modes in iOS. NSDefaultRunLoopMode(kCFRunLoopDefaultMode in Core Foundation) read more..

  • Page - 12

    Chapter 2Designing Your Service ArchitectureWHAT’S IN THIS CHAPTER?Implementing a remote façadeDiscovering endpoints with service locatorsSupporting older apps with service versioningWROX.COM CODE DOWNLOADS FOR THIS CHAPTERYou can find the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): code downloads for this chapter read more..

  • Page - 13

    accessible method that returns the results of the operation. As long as the façade’s external APIcontract remains constant, the underlying systems can be changed, upgraded, or removed entirelywithout impacting any clients using the façade.A remote façade takes this pattern and employs it in the web service tier for an application. Itdefines an unchanging service contract that an app can use to create, read, update, or delete datastored externally to the app. The API is commonly used to read more..

  • Page - 14

    Imagine, for example, a bank merges with a competitor and wants to move its existing accounts tothe competitor’s account storage system. If the service API is written with abstract banking functions,it can work with any back-end database that provides the same data, even if it is stored in a newformat. The remote façade can switch to the new source, transform any data that doesn’t alreadymatch the API contract, and then return it to a mobile banking app without the user knowing read more..

  • Page - 15

    merging banks example, this tweak might be a new password security requirement adopted from thenew institution. If the app merely takes the user’s candidate password and asks the façade if it isvalid, that logic can be changed at any time. A similar pattern to verify e-mail addresses can easilyadapt to the upcoming switch to custom top-level domain (TLD) names; however, if the list of validTLDs were hardcoded in the app, it would potentially reject valid e-mail addresses until an appupdate read more..

  • Page - 16

    actionGoTo:15,LISTINGactionGoTo:15, 2-1: Generating Common Output from Two Stock Quote Sources(stockQuote_v1.php)<?php $useYahooResults = true;$ticker = "AAPL"; if ($useYahooResults) { $rawData = rtrim(file_get_contents("http://finance.yahoo.com/d/quotes.csv?s=". $ticker."&f=snl1p2o"),"\r\n"); $data = explode(",",$rawData); $symbol = trim($data[0],'"'); $name = trim($data[1],'"'); $currentPrice = read more..

  • Page - 17

    <Earns>41.042</Earns> <P-E>13.31</P-E> <Name>Apple Inc.</Name> </Stock></StockQuotes>When the variable $useYahooResults is true, the CSV string is loaded and when it is false, theXML is loaded. Regardless of the input source, the façade returns its data in a common JSON formatlike so:{"symbol":"AAPL","name":"Apple Inc.","currentPrice":"-2.92%"}Any data source used read more..

  • Page - 18

    Example Façade ClientsThe Façade Tester application demonstrates how to use the output formats and displays the results ina table view. actionGoTo:18,ListingactionGoTo:18, 2-3 shows how to load the façade weather service in a background thread usingGrand Central Dispatch. actionGoTo:19,ListingactionGoTo:19, 2-4 shows the equivalent code to parse the stock quote service. TheJSON results are parsed using iOS 5’s NSJSONSerialization and then assigned to local variablesused by the table view. read more..

  • Page - 19

    actionGoTo:18,LISTINGactionGoTo:18, 2-4: Loading and Parsing the Stock Quote Service(FTStockViewController.m)NSString *v1_symbol;NSString *v1_name;NSNumber *v1_currentPrice; - (void)loadVersion1Stock { dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ FTAppDelegate *appDelegate = (FTAppDelegate*) [[UIApplication sharedApplication] delegate]; if (appDelegate.urlForStockVersion1 != nil) { NSError *error = nil; read more..

  • Page - 20

    your existing services without cutting off users of older versions. One option is to include logic thatchecks for a minimum supported application version and displays an upgrade message until the userconsents. However, these nagging messages on previously working versions may upset some users,who may then quickly overwhelm your support lines and App Store reviews with negative comments.Because of this potential downside, proper service versioning is really the best solution.API versioning is not read more..

  • Page - 21

    Both the example web services have two versions that mimic a service contract that expands asbusiness requirements change. Some output field types have been modified and other fields have beenadded. These examples use the passive versioning system that merely changes the URL to specify anew version. Recall that weather_v1.php, the version 1.0 of the weather service, had the followingoutput read more..

  • Page - 22

    actionGoTo:21,LISTINGactionGoTo:21, 2-5: Fetching API Endpoints from the Application Delegate(FTWeatherViewController.m)- (void)loadVersion1Weather { dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ FTAppDelegate *appDelegate = (FTAppDelegate*) [[UIApplication sharedApplication] delegate]; if (appDelegate.urlForWeatherVersion1 != nil) { NSError *error = nil; NSData *data = [NSData read more..

  • Page - 23

    released applications to new services whenever those services become available. These newservices don’t necessarily need to change the API contract with any clients; for example, if endpointsare moved to a different server or subdomain, behind a load balancer, or to an SSL-secured HTTPSendpoint. You can even create new service locator files for each development environment to easilyswitch between development, QA, or production resources with a single change.At its core, a service locator is read more..

  • Page - 24

    parsed before any other networked action can happen. The locator file should also be updated whenan application returns to the foreground to ensure its endpoint data is fresh. Apps can remain in abackground state for an extended period of time, and it may have previously loaded a service locatorfile that is now stale. In certain cases the stale endpoints may have been decommissioned andconsistently timeout, providing a poor user experience. Typically an application displays a splashscreen while read more..

  • Page - 25

    inDictionary:locatorDictionary]; self.urlForWeatherVersion2 = [self findURLForServiceNamed:@"weather" version:2 inDictionary:locatorDictionary]; } else { NSLog(@"Unable to parse service locator because of error: %@", error); // inform the user on the UI thread read more..

  • Page - 26

    service locator, you have many options to tweak business logic and API settings for apps already inthe wild. It becomes easier to support minor tweaks in production code and major new features inupcoming versions without breaking the previous application versions. The upfront developmentcosts of the service infrastructure may seem unnecessary, but it can pay for itself many times over asthe application grows and evolves. read more..

  • Page - 27

    PART IIHTTP Requests: The Workhorse of iOSNetworkingCHAPTER 3: Making RequestsCHAPTER 4: Generating and Digesting PayloadsCHAPTER 5: Handling Errors read more..

  • Page - 28

    Chapter 3Making RequestsWHAT’S IN THIS CHAPTER?Understanding the structure of HTTP requestsIssuing HTTP requests from iOS applicationsUsing advanced manipulation of HTTP requestsWROX.COM CODE DOWNLOADS FOR THIS CHAPTERYou can find the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): code downloads for this chapter read more..

  • Page - 29

    which made finding, consuming, and relating historical research to your own research difficult. Youcan read the original proposal for the WorldWideWeb project at actionURI(http://www.w3.org/Proposal.html):http://www.w3.org/Proposal.html.NOTE An interesting side note in the invention of HTTP and HTML is that the firstWorld Wide Web server and browser were written on a NeXTStep computer. In 1997,Apple acquired NeXT Computer and used NeXTStep as the basis for OS X. Apple’s OS Xbecame the read more..

  • Page - 30

    request per TCP connection. HTTP 1.1 permits the client to reuse the connection.actionGoTo:29,FIGUREactionGoTo:29, 3-1NOTE The definitive specification for HTTP is IETF RFC 2616. This RFC wasadopted as a standard in 1999. You can find this RFC atactionURI(http://www.ietf.org/rfc/rfc2616.txt):http://www.ietf.org/rfc/rfc2616.txt.The most significant difference between HTTP and HTTPS is during the connection establishmentphase of the conversation. After the TCP connection is made but before HTTP read more..

  • Page - 31

    communicate to the server. If you’ve been around the web for a while, you may remember usingftp as a protocol in addition to http. The dominance of http has led to the near extinction ofpre-HTTP protocol usage. Another commonly used protocol in iOS apps is the file protocol.file requests are used to retrieve resources in the local filesystem within the apps sandbox. Ifyou create an NSURL object using a string without a protocol, it defaults to the file protocol.Credentials — Some HTTP read more..

  • Page - 32

    stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];The resulting value of encoded is actionURI(http://myhost.com?query=This%20is%20a%20question):http://myhost.com?query=This%20is%20a%20question. Each ofthe spaces was replaced by a %20 sequence. This encoding differs from URL encoding in that it doesnot encode the ampersand (&) characters, thereby leaving the URL parameter separation intact. URLencoding would encode the ampersands, question marks, and other punctuation. If your read more..

  • Page - 33

    the request uses the GET method, the URI unambiguously specifies the content to retrieve on the targethost. The URI may also contain query parameters, which must not contain a space or carriage returncharacter. In the prior code snippet the URI contains several query parameters, each separated by anampersand (&) character. Notice that the URI does not contain the protocol, host, or port that a userusually provides in the address field of a browser. The client uses the protocol portion of the read more..

  • Page - 34

    Date: Tue, 27 Mar 2012 12:59:18 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=UTF-8 Content-Encoding: gzip Transfer-Encoding: chunked Server: gws <!doctype html><html itemscope="itemscope"itemtype="http://schema.org/WebPage"><head><meta itemprop="image" content="/images/google_favicon_128.png"/><title>ios - Google read more..

  • Page - 35

    loaded and returned to the calling method. This technique is the simplest to implement but has themost limitations.Queued asynchronous — The initiating code creates a request and places it on a queue to beperformed on a background thread. This method is slightly more difficult to implement andremoves a significant limitation of the pure synchronous technique.Asynchronous — The initiating code starts a request that runs on the initiating thread but callsdelegate methods as the requests read more..

  • Page - 36

    If the URL contains a query string, the query accessor method contains the value of all the queryparameters. The contents of the URL string must be percent encoded, per RFC 3986, prior to using itto create an NSURL object. For example, if the following snippet is executed, the value of the queryparameter is q=iOS+Networking.NSURL *url = [NSURL URLWithString:@"http://google.com?q=iOS+Networking"];NSURL objects are immutable, meaning you cannot construct an empty NSURL object and read more..

  • Page - 37

    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0]; if (request == nil) { NSLog(@"Invalid Request"); return; }The NSURLRequest object has several accessor methods to retrieve the properties of the request,none of which you can modify using the immutable NSURLRequest class. If you need to modifyproperties beyond the URL, caching policy, and timeout value, you need to use theNSMutableURLRequest read more..

  • Page - 38

    Returning to the aforementioned primary methods used to perform HTTP requests and receiveresponses, an NSURLConnection class functions via these three different modes of operation:synchronous, asynchronous, and queued asynchronous. Synchronous mode is the easiest to use but hassignificant limitations that will make it inappropriate for more advanced interactions. Asynchronousmode provides greater flexibility but at the cost of complexity in your code. The third mode ofoperation, queued read more..

  • Page - 39

    HTTP status code — The integer status code from the status line of the response. TheNSHTTPURLResponse class has a class method that returns a localized string description for anysupplied status code.The following sections provide annotated examples of how to use each of the three request methodsof the URL loading system. Along with each example, best practices are provided for the use of eachtechnique.Synchronous RequestsSynchronous requests are the simplest type of requests to perform in iOS, read more..

  • Page - 40

    Synchronous requests present the simplest means to retrieve data at a URL, and there are manyhelper methods sprinkled throughout the iOS APIs that use synchronous requests under the covers. Forexample, the method on NSString stringWithContentsOfURL: creates an instance of NSStringand retrieves those contents from an arbitrary server based on the contents of the URL. If the URLuses the FILE (for example, file://foo.txt) protocol, then the contents are retrieved from the localfilesystem. If the read more..

  • Page - 41

    actionGoTo:40,LISTINGactionGoTo:40, 3-1: doSyncRequest Method of VideoDownloader/FeedLoader.m- (NSArray *) doSyncRequest:(NSString *)urlString { // make the NSURL object from the string NSURL *url = [NSURL URLWithString:urlString]; // Create the request object with a 30 second timeout and a // cache policy to always retrieve the // feed regardless of cachability. NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData read more..

  • Page - 42

    the request did not fail because of a networking error or invalid URL. It could still have failedsemantically, for example if the server responded that it encountered an internal server error. Thecontents of the NSError object referenced by that pointer contain a detailed description of the error,and those values are covered in detail in Chapter 5.The code in actionGoTo:41,ListingactionGoTo:41, actionGoTo:41,3-1actionGoTo:41, checks for the existence of an NSError object and the status code of read more..

  • Page - 43

    iOS provides a facility called operation queues in the aptly named NSOperationQueue. Thesequeues enable your program to describe an operation to perform and then submit the operation forqueued execution in first-in-first-out order. The queuing framework provides for priority ordering andordering based on operational dependencies, but the URL loading system does not use these facilities.Before your code can make a queued asynchronous request, it must first create a queue on which therequests will read more..

  • Page - 44

    actionGoTo:43,LISTINGactionGoTo:43, 3-2: doQueuedRequest Method of VideoDownloader/FeedLoader.m- (void) doQueuedRequest:(NSString *)urlString delegate:(id)delegate { // make the NSURL object NSURL *url = [NSURL URLWithString:urlString]; // create the request object with a no cache policy and a 30 second timeout. NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:30.0]; // If the queue doesn't read more..

  • Page - 45

    Only use them when you know that the data returned will never exceed the memory available tothe app. The entire body of the response is returned in-memory to your code. If the response islarge, it may cause out-of-memory conditions in your app. Remember that your code mayduplicate the memory footprint of the returned data when it parses it into a usable format.Use a single NSOperationQueue for all your operations and control the maximum number ofcurrent operations based on the capacity of your read more..

  • Page - 46

    The protocol handler validates that the delegate implements a method before attempting to call themethod. If one is not implemented, then the protocol handler assumes a default value and proceedswith the connection. The best way to explain the operation of the delegate methods is to walk throughthe example app.actionGoTo:47,ListingactionGoTo:47, actionGoTo:47,3-3actionGoTo:47, contains the code used to initiate the URL load request using the asynchronoustechnique. This method starts similarly read more..

  • Page - 47

    class. The code can specify a different run loop or operation queue to use to deliver the callbacks.This example does not make these types of modifications.actionGoTo:46,LISTINGactionGoTo:46, 3-3: The start Method of VideoDownloader/AsyncDownloader.m- (void) start { NSLog(@"Starting to download %@", srcURL); // create the URL NSURL *url = [NSURL URLWithString:srcURL]; // Create the request NSURLRequest *request = [NSURLRequest requestWithURL:url]; // create the read more..

  • Page - 48

    example, the code performs a debugging function of logging the headers of the redirect request andthen following the redirection.connection:didReceiveResponse: Delegate MethodThe second implemented method is the connection:didReceiveResponse: method, as shown inactionGoTo:48,ListingactionGoTo:48, actionGoTo:48,3-5. This method is called when the protocol handler has completed building a responseobject from the headers of the response.actionGoTo:48,LISTINGactionGoTo:48, 3-5: Response Received read more..

  • Page - 49

    The didReceiveResponse method is called when the protocol handler has received enough data tocomplete the URL response object. If an error occurs before enough data was received to completethe response object, then this method will not be called. In the example code, the delegate methodvalidates the HTTP status of the provided response object. If the status is not a 200 status, the loadingof the request is canceled, and the view that provides download progress is reset. If the status is 200,the read more..

  • Page - 50

    method may be called at any time during the handling of the request.actionGoTo:49,LISTINGactionGoTo:49, 3-7: The didFailWithError Method ofVideoDownloader/AsyncDownloader.m- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"Load failed with error %@", [error localizedDescription]); NSFileManager *fm = [NSFileManager defaultManager]; // If you have a temp file already, close it and delete it if (self.tempFile != nil) { read more..

  • Page - 51

    in which all the received data has been accumulated, moves the file to a location based on the URL ofthe originating request, and notifies the view controller via the NSNotificationCenter that thedownload has completed.There are several other methods that a connection delegate may implement to increase the availableinformation and possible control of the connection. The remaining parts of this section describe thosemethods.connection:needNewBodyStream: Delegate MethodThis method is optional and read more..

  • Page - 52

    retention of the response, which includes persistent storage, in-memory storage only, or storage notallowed. The cached response object also contains a userInfo dictionary that can be used by yourapplication to store metadata with the cached request. If your delegate implementation returns nil,the response is not cached.Authentication Delegate MethodsThere are five delegate methods associated with client authentication of URL requests. The use ofthese methods is fully described in Chapter read more..

  • Page - 53

    ADVANCED HTTP MANIPULATIONHTTP headers play an important role supplying metadata that modifies the server’s response orprovides additional information to the HTTP client. Because of this, iOS developers frequently needto manipulate request headers or examine response headers. For example, some servers require theaddition of a custom authentication header that provides information about the user’s identity. Thestandard URL loading system does not add these headers automatically, but it read more..

  • Page - 54

    requestWithURL:url];[request setHTTPMethod:@"POST"];[request setHTTPBody:jsonData];The code first creates a simple NSDictionary with a few name-value pairs about a fictionalanimal. It then uses the built-in JSON library to create an NSData object that represents the dictionary.The NSData object is then supplied to an NSMutableURLRequest object as the request body. TheJSON produced by this code is shown in the following snippet. Chapter 4 describes the process tobuild and parse read more..

  • Page - 55

    specified URL path. When combined with the DNS domain, the path property can restrict thedelivery of a cookie to a limited and precise set of URLs on a server.Expiration Date — The date and time at which the cookie should no longer be supplied inrequests and at which the cookie should be removed from the client’s storage.Session Only — Indicates whether the cookie should be returned only for the duration of thecurrent browser session or until the expiration date, whichever comes first. In read more..

  • Page - 56

    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever];Your code can also stop the automatic handling of cookies on a request-by-request basis by callingthe setHTTPShouldHandleCookies: with a value of NO on an NSMutableURLRequest beforesubmitting it. This prevents the URL loading system from processing the returned requests.Retrieving Cookies from a ResponseIt’s a common task to retrieve the cookies from a response and look for a specific cookie by read more..

  • Page - 57

    Deleting CookiesOccasionally, you may need to delete a cookie from the persistent cookie storage so that it is nolonger added to outgoing requests. Because cookies are added to the request after your code starts theconnection via the asynchronous start or the sendSynchronousRequest method, you cannotprevent a cookie that already exists in the cookie storage from being added to the request. Instead,your code must first remove the cookie from the apps NSHTTPCookieStorage object prior to read more..

  • Page - 58

    the list of cookies is returned, the method looks through the list for a cookie with a matching name,and if found, that cookie is deleted.The deleteCookie:url: method takes two arguments, the name of the cookie to delete and a URLto which that cookie would be returned if a request were made to it. The rules for determining whichcookies to return to a domain allow for global cookies for a domain and cookies for a specific host.actionGoTo:58,TableactionGoTo:58, 3-2actionGoTo:58, illustrates the read more..

  • Page - 59

    [req setAllHTTPHeaderFields:newHeaders]; // send the request[NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];The first segment of the code creates a dictionary containing the properties of the new cookie usinga helpful set of NSHTTP constants for the property names. Using that dictionary, called properties inthe snippet, a new NSHTTPCookie is instantiated. An NSMutableURLRequest object is then createdusing the default properties.The next segment read more..

  • Page - 60

    The following sections describe how to manipulate HTTP request and response headers, and why itmay be important to closely manage the headers sent from your app.Adding Request HeadersWhen your code needs to change request headers, it must create an NSMutableURLRequest objectrather than an unalterable NSURLRequest object. The NSMutableURLRequest class provides twoways to add headers to a request: one header at a time or by replacing all headers.The setAllHTTPHeaderFields: method provides a way to read more..

  • Page - 61

    [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error]; NSDictionary *headers = [response allHeaderFields];NSLog(@"Headers = %@", headers);NSString *contentType = [headers objectForKey:@"Content-Type"];This is safe to do if the request URL will always use either the HTTP or HTTPS protocol scheme.The allHeaderFields method returns a dictionary of all the response headers, including Set-Cookie headers. The last line of the snippet read more..

  • Page - 62

    Base64 encoding.Another header that may be necessary to modify is the User-Agent header, which was created toidentify the browser type to the HTTP server. In many enterprise networks, the user agent value isused to direct traffic to specific servers based on the browser type. Some HTTP servers modify thecontent of the response based on the user agent value. By default, the user agent from your app willcontain the app product name and version, the network framework and version, and the OS name read more..

  • Page - 63

    Chapter 4Generating and Digesting PayloadsWHAT’S IN THIS CHAPTER?Using web service protocols and styles and understanding their impacts on mobile applicationsUnderstanding common payload formatsDigesting XML, HTML, and JSON payloadsGenerating JSON and xml payloadsWROX.COM DOWNLOADS FOR THIS CHAPTERYou can find the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): code downloads for this chapter read more..

  • Page - 64

    WEB SERVICE PROTOCOLS AND STYLESA protocol is a set of formats, procedures, and rules to follow when exchanging structuredinformation with another system. Among other things, protocols define the data format to be usedduring the transmission. This enables receiving systems to properly interpret the structuredinformation and react accordingly. This section compares and contrasts SOAP, a popular protocolwithin enterprise applications, with REST, an architectural design style that is well suited read more..

  • Page - 65

    The content and structure of the message body depends on the receiving system. A body can consistof multiple child elements, each of which can be namespace qualified. Each child element includesthe operation that should be performed by the receiver as well as any necessary parameter values.The following code snippet provides a sample SOAP body.<soap:Body> <m:GetWeather xmlns:m="http://www.<domain>.com/weather"> <m:ZipCode>95014</m:ZipCode> read more..

  • Page - 66

    DATA TYPEATTRIBUTE NAMEIntegerxsd:intBooleanxsd:booleanStringxsd:stringFloatxsd:floatDoublexsd:doubleArray or Dictionary xsd:structGenerating SOAP client-side code from Web Service Description Language (WSDL) and XMLSchema Definition (XSD) documents can be complex. This complexity is exacerbated by the need todevelop for multiple platforms and device families. Another pitfall of SOAP is that changes can bedifficult in the mobile environment. When two internally operated servers communicate, read more..

  • Page - 67

    return a resource representation as JSON formatted data, whereas others may return an image.Choosing an ApproachSOAP-based services are still actively deployed in many enterprises, especially those that run someof the more popular packaged software solutions such as enterprise resource planning (ERP)software. SOAP and REST try to solve the same problem in different ways. Although neither protocolis a perfect fit for every situation, REST style service architecture is the best design for read more..

  • Page - 68

    PAYLOADSPayloads are the essential data exchanged during the service request-response transaction. Forexample, in a POST request, the payload is the request body. Payloads do not include the overheaddata such as request headers or the HTTP method being requested; POST in the example. If yourapplication is sending or receiving information from a web service you need to have a firmunderstanding of the payload format for requests and responses.This section provides an overview of common payload read more..

  • Page - 69

    <person> <firstName>Nathan</firstName> <lastName>Jones</lastName> <emailAddress primary='true'>email@domain.com</emailAddress> <noContact medium='email' /></person>The preceding code outlines a person element that contains several child elements: firstName,lastName, emailAddress, and noContact. The emailAddress element contains an attributeindicating that the element’s content is this person’s primary e-mail address. The read more..

  • Page - 70

    much space. However, after stripping away all whitespace and newlines, the previous examplebecomes the following more compact payload that can be just as easily interpreted by a machine.{"person":{"firstName":"Nathan","lastName":"Jones","email":{"emailAddress":"email@domain.com","primary":true},"noContact":"email"}}HTMLHTML is a markup language standard for structuring data on a web page read more..

  • Page - 71

    that displays on the screen. The field names are defined using the id attribute, and the value is thecontent between the start-tags and end-tags. Note the use of HTML5 custom attributes to indicateprimary e-mail and the no-contact medium.Digesting Response PayloadsWeb services return structured data in a number of formats, most commonly XML and JSON. It’s alsofeasible that an application must retrieve HTML-structured data. Applications that implement theseweb services or retrieve HTML read more..

  • Page - 72

    documents, and some are quick but consume larger portions of memory. Anticipated XML documentsize also plays into the decision of which parser to choose; some parsers do well with smalldocuments, whereas others are intended to support large XML documents. Another factor to considerfor native parsers is that they are delivered and supported by Apple. This means that they will bethoroughly tested with each future release of the iOS operating system to ensure backwardcompatibility. Each of these read more..

  • Page - 73

    actionGoTo:72,LISTINGactionGoTo:72, 4-2: Top Stories RSS Parser Interface Definition(/Application/topstories/topstories/TopStoriesParser.h)#import "Post.h" @protocol TopStoriesDelegate <NSObject>@required-(void)topStoriesParsedWithResult:(NSMutableArray*)posts;@end @interface TopStoriesParser : NSObject <NSXMLParserDelegate> @property(nonatomic,strong) NSData *feedData;@property(nonatomic,strong) NSMutableArray *posts; @property(assign) read more..

  • Page - 74

    [_delegate topStoriesParsedWithResult:_posts]; }} - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { // if you were expecting an attribute, it would be // handled here in the attributeDict by using // objectForKey: using the attribute name // started a new post, create a fresh object if ([elementName read more..

  • Page - 75

    point, the parser has a complete list of Post objects, so the parser informs its delegate.The parser:didStartElement:namespaceURI:qualifiedName:attributes: method is calledwhen a new element is started. This is where attributes are handled; remember, they are part of thestart-tag. parser:foundCharacters: is called as content is read from the element andparser:didEndElement:namespaceURI:qualifiedName: is called when the element is closed.When elements are closed, it is safe to process and store read more..

  • Page - 76

    actionGoTo:75,LISTINGactionGoTo:75, 4-4: Fetch Top Stories Operation Implementation(/Application/topstories/topstories/FetchTopStoriesOperation.m)#import "FetchTopStoriesOperation.h"#import "FetchPostContentOperation.h"#import "TopStoriesParser.h" //#define kURL @"file:/<path to folder>/cnn_topstories.rss"#define kURL @"http://rss.cnn.com/rss/cnn_topstories.rss"#define kTimeout 30.0 @implementation FetchTopStoriesOperation - (void)main { read more..

  • Page - 77

    At this point the application has fetched and parsed the RSS feed and has initiated the story contentdownload process. With that, it’s time to parse the story content.HTMLAs discussed during the introduction, HTML documents share a similar structure with XML.However, XML document structures typically come with some sort of service contract between thesender and receiver. HTML documents typically do not have a contract associated with them; they canchange frequently and drastically with little read more..

  • Page - 78

    2. Add the libxml2.dylib to the project.3. Add $(SDKROOT)/usr/include/libxml2 to the Header Search Paths field in the targets’Build Settings.4. Disable ARC for the HTMLNode and HTMLParser files. Within the target Build Phases, add thecompiler flag -fno-objc-arc to HTMLNode.m and HTMLParser.m. As of this writing, thiswrapper has not been converted for ARC support.actionGoTo:78,ListingactionGoTo:78, 4-5 details how the application generates and processes the story content request. When read more..

  • Page - 79

    initWithData:content error:&error]; if (error) { return; } // get html doc head and meta tags HTMLNode *head = [parser head]; NSArray *metaTags = [head findChildTags:@"meta"]; // retrieve article meta data and add to the post for (HTMLNode *meta in metaTags) { NSString *name = [meta getAttributeNamed:@"name"]; // keywords if ([name isEqualToString:@"keywords"]) { read more..

  • Page - 80

    story content view may resemble. The application shown in this figure has now fetched all CNN-related content.actionGoTo:79,FIGUREactionGoTo:79, 4-3The next feature is to add light Twitter search integration to search for story keywords retrievedfrom the meta tags.JSONAs of iOS 5 Apple provides native JSON parsing support via the NSJSONSerialization class.Parsing JSON data prior to iOS 5’s native support required the use of a third-party library such asJSON framework read more..

  • Page - 81

    NSJSONReadingMutableContainers: Instructs the parser to generate NSMutableArray andNSMutableDictionary objects. Mutable objects mean that you can modify them using methods,such as addObject: for NSMutableArray and setObject:forKey: forNSMutableDictionary. This could be used in situations with a primary and secondary result setin which you need to add a value from the secondary result to the primary result before furtherprocessing.NSJSONReadingMutableLeaves: Instructs the parser to generate read more..

  • Page - 82

    [self postNotification:kTweetsStartNotification]; [self startNetworkActivityIndicator]; _post.tweetsLoading = YES; // create the twitter query NSMutableString *query = [[NSMutableString alloc] init]; for (int i=0; i<[_post.keywords count]; i++) { // prepend comma for all but first keyword if (i != 0) { [query appendString:@","]; } [query appendString:[_post.keywords objectAtIndex:i]]; } // create the read more..

  • Page - 83

    @endWhen the TweetsTableViewController has been hooked up (see the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): downloads forthis chapter) and the operation finishes, you should see a related tweet view similar to actionGoTo:83,FigureactionGoTo:83, 4-4.actionGoTo:83,FIGUREactionGoTo:83, 4-4Generating Request PayloadsIntegrating sophisticated web services into your applications often requires you to transmit payloadsin a structured format. These formats are most typically JSON read more..

  • Page - 84

    compact JSON possible.NSJSONSerialization also provides isValidJSONObject: to validate whether the Foundationobject you attempt to convert is convertible. For objects to be converted to JSON, they must conformto the following rules:Top-level object that is an NSArray or NSDictionary.All objects must be NSString, NSNumber, NSArray, NSDictionary, or NSNull.All NSDictionary keys must be NSStrings.NSNumbers must not be NaN or infinity.Because the newsreader application stores articles in the form of read more..

  • Page - 85

    [req setHTTPMethod:@"POST"]; [req setValue:@"application/json" forHTTPHeaderField:@"Accept"]; // convert array of POST objects to array of dictionary // objects so NSJSONSerialization can handle it NSMutableArray *articles = [[NSMutableArray alloc] init]; for (Post *post in posts) { // dictionaryRepresentation is a custom method // that creates an NSDictionary of a few key fields [articles read more..

  • Page - 86

    }The application creates an array of NSDictionary objects (representing each Post) and thencreates an NSDictionary with one key-value pair of articles. This is done so that the top-level ofthe resulting JSON is a collection.Attempting to convert invalid types to JSON causes your applications to crash. Therefore, it is abest practice to call isValidJSONObject: prior to calling dataWithJSONObject:options:error:to handle potential errors gracefully.actionGoTo:86,AfteractionGoTo:86, read more..

  • Page - 87

    is presented in this section.Building on the steps outlined in the XML parsing section earlier in this chapter, one additional stepis required to use libxml to create XML documents; <libxml/xmlwriter.h> must be imported intoeach class creating XML. Within the newsreader sample application, XML generation for articles hasbeen consolidated to the postXMLDataFromDictionary: method in Utils, as shown in actionGoTo:87,ListingactionGoTo:87, 4-10.actionGoTo:87,LISTINGactionGoTo:87, 4-10: Article read more..

  • Page - 88

    document. When that is added you can begin calling xmlTextWriterStartElement(),xmlTextWriterWriteString(), and xmlTextWriterEndElement() as needed to create your XMLstructure. xmlTextWriterEndElement() does not require the element name to close; it keeps trackof that for you.Two important function sets of libxml not required by this example are the ability to add commentsand element attributes to the XML document. Similar to elements, comments can be added by callingthe read more..

  • Page - 89

    actionGoTo:88,LISTINGactionGoTo:88, 4-11: XML Request Creation and Transmission(/Application/topstories/topstories/ShareArticlesOperationXML.m)#import "ShareArticlesOperationXML.h" @implementation ShareArticlesOperationXML @synthesize posts, shareType; - (void)main { [self startNetworkActivityIndicator]; // create the and issue request ... // convert array of POST objects to array of dictionary // objects so the XML writer can handle it NSMutableArray read more..

  • Page - 90

    SUMMARYThere are several factors to consider when designing how your application communicates with webservices. When implemented properly, the best architecture to deliver data to the mobile channel isREST. The optimal data interchange format for iOS applications is JSON. Although XML is alsonatively supported, JSON payloads are easier to work with, map more appropriately to Foundationtypes, and are more cellular network-friendly.In the next chapter, you gain an understanding of where errors read more..

  • Page - 91

    Chapter 5Handling ErrorsWHAT’S IN THIS CHAPTER?Sources of networking errors in iOS applicationsDetecting reachability of the networkRules of thumb for handling errorsA design pattern for handling network errorsWROX.COM CODE DOWNLOADS FOR THIS CHAPTERThe actionURI(http://wrox.com):wrox.com code downloads for this chapter are found read more..

  • Page - 92

    of device networking and internetworking led to the development of layered networks. Layerednetworks divide this complex environment into more manageable chunks. Although this helps theprogrammer, networking errors like those mentioned previously can occur as data moves betweenlayers.actionGoTo:92, FigureactionGoTo:92, 5-1actionGoTo:92, illustrates the layering in the Internet Protocol stack.actionGoTo:92,FIGUREactionGoTo:92, 5-1Every layer performs some sort of error checking, which could be read more..

  • Page - 93

    The steps in the sequence become much more complicated if the request is a secure HTTPS requestor if the HTTP server redirects the client. For many of these steps, there are numerous substeps, suchas the sequence of SYN and SYN-ACK packets involved in establishing a TCP connection. Thefollowing sections describe each error category in greater detail.Operating System ErrorsOperating system (OS) errors are errors caused by a data packet not reaching its intended target. Thatdata packet may be part read more..

  • Page - 94

    // some code that makes a call and may fail if (errorOccurred) //some kind of error { NSMutableDictionary *errorDict = [NSMutableDictionary dictionary]; [errorDict setValue:@"Failed to fetch my stuff" forKey:NSLocalizedDescriptionKey]; *error = [NSError errorWithDomain:@"myDomain" code:kSomeErrorCode userInfo:errorDict]; return read more..

  • Page - 95

    // Something low level broke}Notice that the NSError object is declared as a pointer to nil. The NSURLConnection objectinstantiates only the NSError object if an error occurs. The URL loading system owns the NSErrorobject; you should retain the object if your code will need it later. If the NSError pointer still pointsto nil after the synchronous request completes, then no low-level OS error occurred. At this pointyour code knows that no OS level has occurred, but an error may have occurred read more..

  • Page - 96

    To use the Reachability API, download the example program from the iOS developer library atactionURI(http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html):http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html, and addReachability.h and Reachability.m to your app’s XCode project. In addition, you need to addthe SystemConfiguration framework to your XCode project. Adding the SystemConfigurationframework to your XCode project read more..

  • Page - 97

    It is also useful to know if the reachability status of the device changes so that you can modifyapplication behavior proactively. The following code snippet initiates monitoring of network status:#import "Reachability.h"...[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChanged:) name:kReachabilityChangedNotification read more..

  • Page - 98

    A 404 status is a common example of an HTTP error. It indicates that the resource specified in theURL cannot be found. The HTTP header shown in the following code snippet is an example of theraw output from an HTTP server when it cannot find the requested resource.HTTP/1.1 404 Not FoundDate: Sat, 04 Feb 2012 18:32:25 GMTServer: Apache/2.2.14 (Ubuntu)Vary: Accept-EncodingContent-Encoding: gzipContent-Length: 248Keep-Alive: timeout=15, max=100Connection: Keep-AliveContent-Type: text/html; read more..

  • Page - 99

    // Check the returnif ((!error) && ([response statusCode] == 200)) { // looks like things worked} else { // things broke, again.}If the URL of the request could be something other than HTTP, the application should validate thatthe response object is actually an NSHTTPURLResponse. The preferred method to validate the type ofthe object is using the isKindOfClass: method on the returned object, as shown in the followingcode:if ([response isKindOfClass:[NSHTTPURLResponse class]]) { read more..

  • Page - 100

    to quickly determine if an error occurred by checking for the existence of the "error" object in theresponse JSON payload:{"error":{ "code":900005, "messages":"Insufficient Funds to Complete Transfer" }, "data":{ "fromAccount":1, "toAccount":5, "amount":500.00 }}Any UI code to report errors can easily be reused because the error information is always in theerror attribute of read more..

  • Page - 101

    web applications: ambiguous error reporting. There are three possible outcomes of any networkrequest from a mobile device to a server:The device has absolute positive confirmation that the operation succeeded. For example, boththe NSError and HTTP status values indicate success, and the returned payload containssyntactically and semantically correct information.The device has absolute negative confirmation that the operation failed. For example, thereturned application payload contained a read more..

  • Page - 102

    Your app code should always check the returned NSError value to make sure nothing broke at the OSlevel. This is true even if you know that the app always runs on a well-run and tightly controlled Wi-Fi network. Things do not always work correctly, and your code needs to be defensive when dealingwith the network.Develop a Consistent Method for Handling ErrorsThe causes of networking errors are too numerous to enumerate, and the variety and scope of theirimpact can be overwhelming. When you design read more..

  • Page - 103

    This section describes a design pattern that creates an elegant and robust framework for exceptionhandling and requires little work to extend it for new errors in the future.Consider the three major exception cases for mobile communications:The remote server is not reachable due to insufficient network connectivity from the device.The remote server returns an error response because of an OS error, HTTP error, or applicationerror.The device attempts an unauthenticated request to a server that read more..

  • Page - 104

    Completion notification name — In iOS, controllers register themselves as observers for thisnotification name. When the service call returns successfully, the command object usesNSNotificationCenter to broadcast a notification with this name. Although it is usually uniqueto the command class, in some situations it can be unique to a specific instance if there aremultiple controllers issuing the same command types that want to distinguish individualresponses.Server error exception notification read more..

  • Page - 105

    Controller BehaviorsControllers are focused on executing UI and business logic. When a controller wants data from aservice, it should take the following actions:1. Create a network command object.2. Initialize the request for specific attributes of the command object.3. Register as an observer for the completion of the command.4. Push the command onto an operation queue for execution.5. Wait for the NSNotificationCenter to deliver a completion notification.When the operation completes, the read more..

  • Page - 106

    configuration subsystem.4. Issue the network request using a synchronous request. See the “Synchronous Requests” sectionin Chapter 3 for more details on this.5. Check the status of the request. If the status is an OS or HTTP error, it broadcasts a serverexception notification. If the error is an authentication error, it broadcasts an authenticationexception notification.6. Parse the results. See Chapter 4.7. Broadcast a completion notification with a successful status.When a command object read more..

  • Page - 107

    1. Present a nice looking modal dialog informing the users they need to be on a network withconnectivity.2. Collect any other service exceptions that may be broadcast.3. Listen for reachability changes. When the network is reachable, dismiss the dialog andresubmit the collected commands.The flow for an authentication exception is a bit more complicated. Keep in mind that commandsare independent of one another, and many can be in flight at any one time. The authentication flowdoes not generate read more..

  • Page - 108

    example surveys the major code components and discusses some of the implementation details.The app in the included project is a simple demonstration app. It is not intended for anything otherthan demonstrating this pattern.PrerequisitesThe things you need to have to successfully see this app operate are as follows:A YouTube accountAt least one video uploaded to your YouTube account (it doesn’t need to be public, just uploadedto the account)The project zip file from the Wrox companion read more..

  • Page - 109

    actionGoTo:108,LISTINGactionGoTo:108, 5-1: CommandDispathDemo/service-interface/GetFeed.h- (void)main { NSLog(@"Starting getFeed operation"); // Check to see if the user is logged in if ([self isUserLoggedIn]) { // only do this if the user is logged in // Build the request NSString *urlStr = @"https://gdata.youtube.com/feeds/api/users/default/uploads"; NSLog(@"urlStr=%@",urlStr); NSMutableURLRequest *request = read more..

  • Page - 110

    NetworkErrorViewController: Provides the user with the choice to retry or abort the failedoperations. If the user selects retry, then the failed commands are placed back on the operationqueue.LoginViewController: Solicits a username and password from the user. It stays at the top ofthe view stack until the user successfully logs in.InterstitialViewController: As a parent of the other exception listeners, it providessupport functionality such as the code to collect multiple error notifications read more..

  • Page - 111

    View ControllersThere is one primary view controller in this simple app. The RootViewController (see thefollowing code) extends UITableViewController. When this controller loads it creates andenqueues a command to load the user’s list of videos (aka the YouTube feed). It patiently waits for thecompletion of that command by yielding the flow of control back to the main run loop. It is blissfullyunaware that it will always fail on the first call because the user is not logged in.The read more..

  • Page - 112

    } else { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Videos" message:@"The login to YouTube failed" delegate:self cancelButtonTitle:@"Retry" otherButtonTitles:nil]; [alert show]; [alert release]; }); }}The class YouTubeVideoCell is a UITableViewCell subclass that read more..

  • Page - 113

    experience.SUMMARYThere are many sources of errors that can and will occur when your code uses the network.Understanding the source of the errors can help you quickly diagnose and resolve networking issues.Using the Reachability framework, your code can proactively respond to changing networkconditions, thereby avoiding unnecessary network errors. Following a consistent pattern for issuingnetwork requests and handing the successful or unsuccessful outcomes can make your code cleanerand more read more..

  • Page - 114

    PART IIIAdvanced Networking TechniquesCHAPTER 6: Securing Network TrafficCHAPTER 7: Optimizing Request PerformanceCHAPTER 8: Low-Level NetworkingCHAPTER 9: Testing and Manipulating Network TrafficCHAPTER 10: Using Push Notifications read more..

  • Page - 115

    Chapter 6Securing Network TrafficWHAT’S IN THIS CHAPTER?How to verify your application is communicating with the correct serverAuthenticating with a service using HTTP and client-side certificatesHow to generate cryptographic hashes and use them to verify payload integrityEncrypting and decrypting data within an iOS applicationTips for storing credentials using the device’s keychainWROX.COM DOWNLOADS FOR THIS CHAPTERYou can find the read more..

  • Page - 116

    PHP for simplicity. PHP is relatively straightforward and should be easy to understand even if youlack previous experience with it. Important server-side snippets have been included throughout thechapter and the entire server-side source is available in the Chapter 6 download folder online.VERIFYING SERVER COMMUNICATIONIt is likely that users of your applications will be on the go; these are mobile applications after all,and you can rarely guarantee that any connection to the Internet is secure read more..

  • Page - 117

    NSURLAuthenticationMethodClientCertificateNSURLAuthenticationMethodServerTrustNow that you have created a protection space with your server’s attributes, you need to ensure that itis used to verify your connections. When your code requests a resource from the server that requiresauthentication, the server responds with an HTTP status code of 401 - Access Denied.NSURLConnection receives this response and immediately sends awillSendRequestForAuthenticationChallenge: delegate message with a copy read more..

  • Page - 118

    protocol:NSURLProtectionSpaceHTTPS realm:@"mobilebanking" authenticationMethod:NSURLAuthenticationMethodClientCertificate]; NSArray *validSpaces = [NSArray arrayWithObjects:defaultSpace, trustSpace, nil]; // validate that the authentication challenge // came from a whitelisted protection space if (![validSpaces containsObject:challenge.protectionSpace]) { // dispatch alert view message to the main thread read more..

  • Page - 119

    login credentials, bank account numbers, and so on would never be transmitted.Sophisticated iOS applications often communicate with a web service, and those services may needto change quickly. Unfortunately, consumer iOS application changes require submission and approvalby Apple, which can be unpredictable. Your organization does not want to be in a situation whereweb service authentication must be changed immediately, possibly rendering your applicationinoperable. To mitigate this risk, the read more..

  • Page - 120

    authentication simply prompts users to enter their username and password, whereas expeditedauthentication allows users to register a device and authenticate using a PIN without typing ausername and password each time. To maintain security with expedited authentication, if the userchooses to register the device on a given authentication request, the server response will include anadditional attribute, the user’s certificate. The application stores this certificate and checks for it onsubsequent read more..

  • Page - 121

    actionGoTo:120,LISTINGactionGoTo:120, 6-1: Handling Basic Authentication Challenges (/App/Mobile-Banking/AuthenticateOperation.m)- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge { ... // respond to basic authentication requests // DIGEST and NTLM authentication follow this pattern if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic) { read more..

  • Page - 122

    Now that the user has successfully authenticated, assume the user registered the device during thisparticular authentication request. During device registration, the application must store the certificatereturned from the authentication service. The following provides an example of what a successfulservice tier response may look like when it includes certificate data.{ "result": "SUCCESS", "additional_info": "Authentication Successful", read more..

  • Page - 123

    actionGoTo:122,LISTINGactionGoTo:122, 6-2: Authentication Response Handling with Certificate Data (/App/Mobile-Banking/AuthenticateOperation.m)- (void)connectionDidFinishLoading:(NSURLConnection *)connection { ... // unpack service response NSError *error = nil; NSDictionary *response = [NSJSONSerialization JSONObjectWithData:self.responseData options:0 error:&error]; read more..

  • Page - 124

    actionGoTo:122,LISTINGactionGoTo:122, 6-3: Obtaining Identity and Certificate from .p12 Data (/App/Mobile-Banking/Utils.m)+ (void)identity:(SecIdentityRef*)identity andCertificate:(SecCertificateRef*)certificate fromPKCS12Data:(NSData*)certData withPassphrase:(NSString*)passphrase { // bridge the import data to foundation objects CFStringRef importPassphrase = (__bridge CFStringRef)passphrase; CFDataRef importData = (__bridge CFDataRef)certData; // create dictionary of read more..

  • Page - 125

    // proceed with authentication if (challenge.previousFailureCount == 0) { // retrieve the default credential specifically for // client certificate challenges NSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace: [[Model sharedModel] clientCertificateProtectionSpace]]; if (credential) { [challenge.sender useCredential:credential read more..

  • Page - 126

    SSL certificates. If you test the authentication mechanisms discussed in this section with a self-signedSSL certificate, the majority of the network based code will not be executed. However, emailing yourserver certificate (.cer file extension) to an e-mail account configured on the device allows you toclick and install it. When installed, NSURLConnection requests can recognize your server certificateas trusted and proceed with processing.MESSAGE INTEGRITY WITH HASHINGAND ENCRYPTIONNow that the read more..

  • Page - 127

    transaction. Important values for encryption and decryption as well as the MAC algorithm are knownby both parties in the transaction. Also, the Request Body section aligns with the JSON payloadstructure defined in the previous example.actionGoTo:126,FIGUREactionGoTo:126, 6-2HashingCryptographic hashes, or digests, generate fixed-size bit sequences for a given block of data. Thesehash values make comparing and sorting blocks of data easy. A few common uses of hashes includetracking file changes, read more..

  • Page - 128

    actionGoTo:127,LISTINGactionGoTo:127, 6-4: NSString Hashing Category Definition (/App/Mobile-Banking/NSString+Hashing.h)#import <CommonCrypto/CommonDigest.h> enum { NJHashTypeMD5 = 0, NJHashTypeSHA1, NJHashTypeSHA256,}; typedef NSUInteger NJHashType; @interface NSString (Hashing) - (NSString*)md5;- (NSString*)sha1;- (NSString*)sha256;- (NSString*)hashWithType:(NJHashType)type; @endactionGoTo:129,ListingactionGoTo:129, 6-5 outlines the core logic within your hashing category. Each read more..

  • Page - 129

    actionGoTo:128,LISTINGactionGoTo:128, 6-5: Core Digest Calculation Logic Within hashWithType (/App/Mobile-Banking/NSString+Hashing.m)- (NSString*)hashWithType:(NJHashType)type { // Create pointer to the string as UTF8 – this is NULL terminated const char *ptr = [self UTF8String]; // Create buffer with length for chosen digest NSInteger bufferSize; switch (type) { case NJHashTypeMD5: // 16 bytes bufferSize = CC_MD5_DIGEST_LENGTH; read more..

  • Page - 130

    actionGoTo:129,LISTINGactionGoTo:129, 6-6: Hashing Convenience Method Implementations (/App/Mobile-Banking/NSString+Hashing.m)- (NSString*)md5 { return [self hashWithType:NJHashTypeMD5];} - (NSString*)sha1 { return [self hashWithType:NJHashTypeSHA1];} - (NSString*)sha256 { return [self hashWithType:NJHashTypeSHA256];}This approach has the added benefit of being easily extended to support additional digestcalculations. The following example demonstrates calling each convenience method read more..

  • Page - 131

    request data) and comparing it with a precomputed MAC that is delivered with the payload. MACsare similar to the hash functions previously discussed but are more secure because they are pairedwith a secret key. As depicted in actionGoTo:127,FigureactionGoTo:127, 6-2, your application will compute a MAC that is sent withyour request. This inbound MAC is then compared with a MAC computed in the service tier using thesame key and dataset. If the MAC values are not equal, it is safe to assume that read more..

  • Page - 132

    actionGoTo:131,LISTINGactionGoTo:131, 6-8: hmacWithKey: Implementation (/App/Mobile-Banking/NSString+Hashing.m)- (NSString*)hmacWithKey:(NSString*)key { // Pointer to UTF8 representations of strings const char *ptr = [self UTF8String]; const char *keyPtr = [key UTF8String]; // Implemented with SHA256, create appropriate buffer (32 bytes) unsigned char buffer[CC_SHA256_DIGEST_LENGTH]; // Create hash value CCHmac(kCCHmacAlgSHA256, // algorithm read more..

  • Page - 133

    random array of bytes.Although it is common for developers to output various processing details to the log, you shouldnever print the generated key to the console. Log files can be easily retrieved from the device, whichcould present a serious security flaw if found by an attacker.One downside to preshared keys is that the application needs to plan for key versioning. It isinevitable that you will come across a situation where you must modify your shared secret key, whichrequires you to deploy a read more..

  • Page - 134

    EncryptionNow that you have generated the message authentication code, the client is ready to encrypt therequest payload and send it to the server for processing. Although this section discusses two specific,symmetric encryption algorithms — the Advanced Encryption Standard and Data Encryption Standard— and their suitability for mobile devices, it is not a comprehensive discussion of encryption theory.However, a good rule of thumb is to trust the experts and use a standardized and vetted read more..

  • Page - 135

    C functions, to encrypt and decrypt data that supports a number of algorithms as shown in actionGoTo:135,TableactionGoTo:135, 6-2.The library provides a convenience function, CCCrypt(), which performs a stateless encryption ordecryption operation. This function is robust and should meet most cipher requirements, and is theapproach covered in this chapter. The library also provides a suite of functions that allow developersmore granular control over each step of the cipher read more..

  • Page - 136

    actionGoTo:135,LISTINGactionGoTo:135, 6-10: NSString+Encryption Interface Definition (/Chapter6/App/Mobile-Banking/NSString+Encryption.h)@interface NSString (Encryption) - (NSString*)encryptedWithAESUsingKey:(NSString*)key andIV:(NSData*)iv;- (NSString*)decryptedWithAESUsingKey:(NSString*)key andIV:(NSData*)iv; - (NSString*)encryptedWith3DESUsingKey:(NSString*)key andIV:(NSData*)iv;- (NSString*)decryptedWith3DESUsingKey:(NSString*)key andIV:(NSData*)iv; @endWith your interfaces defined, jump to read more..

  • Page - 137

    Each of the NSString methods is similar; the primary differences are the direction of Base 64encoding and how the result is encoded prior to being returned. Now, it is time to implement the coreactionGoTo:137,ofactionGoTo:137, theactionGoTo:137, cipheractionGoTo:137, processactionGoTo:137, inactionGoTo:137, theactionGoTo:137, NSData+EncrypactionGoTo:137,tionactionGoTo:137, category,actionGoTo:137, asactionGoTo:137, outlinedactionGoTo:137, inactionGoTo:137, ListingactionGoTo:137, read more..

  • Page - 138

    actionGoTo:137,ListingactionGoTo:137, actionGoTo:137,6-12actionGoTo:137, and actionGoTo:137,ListingactionGoTo:137, actionGoTo:137,6-13actionGoTo:137, cover encryption for AES and Triple-DES, using CCCrypt(),respectively. The CCCrypt() function is straightforward, but it is important to allocate proper spacefor your encryptedData pointer. The output length of CCCrypt() will never be more than the inputplus one additional block. Block size is based on the encryption algorithm being read more..

  • Page - 139

    actionGoTo:138,LISTINGactionGoTo:138, 6-14: AES Encryption in Practice (/App/Mobile-Banking/FundsTransferOperation.m)... // build our transfer data NSDictionary *transfer = [NSDictionary dictionaryWithObjectsAndKeys: _toAccount, @"toAccount", _fromAccount, @"fromAccount", date, @"transferDate", _transferNotes, @"transferNotes", read more..

  • Page - 140

    actionGoTo:139,LISTINGactionGoTo:139, 6-15: Initialization Vector Creation Using SecRandomCopyBytes()(/App/Mobile-Banking/Utils.m)+ (NSData*)blockInitializationVectorOfLength:(size_t)ivLength { // default to AES block size if (ivLength == 0) { ivLength = kCCBlockSizeAES128; } NSMutableData *iv = [NSMutableData dataWithLength:ivLength]; int ivResult = SecRandomCopyBytes(kSecRandomDefault, ivLength, read more..

  • Page - 141

    actionGoTo:140,LISTINGactionGoTo:140, 6-16: AES Decryption Using PHP (/Service/index.php)// retrieve the request payload$postData = json_decode(@file_get_contents('php://input'));$inboundMac = $postData->mac;$iv = $postData->iv;$payload = $postData->payload; // decrypt the payload$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $AES_KEY, base64_decode($payload), MCRYPT_MODE_CBC, read more..

  • Page - 142

    be used for both encryption and decryption operations and the intent is specified using the firstparameter.The methods outlined in actionGoTo:142,ListingactionGoTo:142, actionGoTo:142,6-17actionGoTo:142, and actionGoTo:142,ListingactionGoTo:142, actionGoTo:142,6-18actionGoTo:142, should look familiar; they are nearlyidentical to their encryption counterparts. The only difference is that you instruct CCCrypt() toperform a decrypt operation instead of an encrypt read more..

  • Page - 143

    The application implements the list account functionality of the application to illustrate client-sidedecryption. After a user authenticates successfully, the application immediately issues a request toretrieve the user’s accounts. The list of accounts includes name, number, and balance, and transmits tothe application in encrypted form. You can decrypt the account list, validate message integrity, andcreate account objects for display in the view layer.actionGoTo:143,ListingactionGoTo:143, read more..

  • Page - 144

    actionGoTo:143,LISTINGactionGoTo:143, 6-20: Handling AES Encrypted Responses (/App/Mobile-Banking/GetAccountsOperation.m)- (void)connectionDidFinishLoading:(NSURLConnection *)connection { // unpack service response NSError *error = nil; NSDictionary *response = [NSJSONSerialization JSONObjectWithData:self.responseData options:0 error:&error]; // decrypt the payload NSString read more..

  • Page - 145

    STORING CREDENTIALS SECURELY ONTHE DEVICENow that the application can communicate securely with the service tier, it needs to store informationsecurely on the device. Apple provides the Keychain Services API as part of the Security Frameworkto do just that. Keychain is a mechanism to securely store small amounts of data such as passwords,keys, certificates, and identities on the device. Keychain is not intended for general-purposeencryption and data storage, but items that require protection read more..

  • Page - 146

    ITEM ATTRIBUTEDESCRIPTIONkSecAttrAccessibleIndicates when this item can be accessed; discussed further in the chapter textkSecAttrAccessGroupIndicates which access group the item belongs to; discussed further in the chapter textkSecAttrDescriptionUser-visible string describing itemkSecAttrCommentUser-editable comment for itemkSecAttrCreatorItem’s creator as unsigned integer representation of four-character codekSecAttrTypeItem’s type as unsigned integer representation of four-character read more..

  • Page - 147

    kSecAttrAccessibleAlwaysItem data is always accessible. It is not recommended that developers use thisattribute; it is intended for system use.kSecAttrAccessibleWhenUnlockedThisDeviceOnlySimilar to kSecAttrAccessibleWhenUnlocked except that item data cannot bemigrated to a new device.kSecAttrAccessibleAfterFirstUnlockThisDeviceOnlySimilar to kSecAttrAccessibleAfterFirstUnlock except that item datacannot be migrated to a new device.kSecAttrAccessibleAlwaysThisDeviceOnlyItem data is always read more..

  • Page - 148

    NOTE As stated earlier in this section, Chapter 11 covers integrating Keychainstorage into your application, including how to share data between multipleapplications.SUMMARYSecuring network communication is extremely important and can take many forms, such as validatingthat your users are communicating with the correct servers or authenticating users before grantingthem access to your systems. You may also choose to encrypt all, or part of, your network traffic usingciphers such as AES and read more..

  • Page - 149

    Chapter 7Optimizing Request PerformanceWHAT’S IN THIS CHAPTER?Understanding network bandwidth and latencyReducing request bandwidth with compressionReducing request latency with pipeliningMinimizing request bandwidth with cachingWROX.COM CODE DOWNLOADS FOR THIS CHAPTERThe actionURI(http://wrox.com):wrox.com code downloads for this chapter are found read more..

  • Page - 150

    and the real-world bandwidth seen by a networked device can vary greatly from that maximum.actionGoTo:150,FigureactionGoTo:150, 7-1actionGoTo:150, shows the theoretical capacity of current wireless technologies on a logarithmic scale.actionGoTo:150,FIGUREactionGoTo:150, 7-1There are many reasons why the bandwidth your device experiences differs so much from thetheoretical maximum. Chief among them is the fact that wireless network bandwidth is a sharedcommodity. Even if a wireless technology read more..

  • Page - 151

    Consider a situation in which your app has sole use of an LTE base station in the middle of Kansas,but that base station may have a small back haul circuit that connects it to the Internet at large. Youmay get an excellent data rate to the tower, but the back haul restricts the usable bandwidth. Themaximum speed of any network connection is the speed of the slowest link along the communicationpath. Even if there is sufficient back haul bandwidth, carrier network equipment applies a quality read more..

  • Page - 152

    actionGoTo:151,FIGUREactionGoTo:151, 7-3Latency is also dependent on the specific route taken by the packet as it moves between the deviceand the destination server. Refer to actionGoTo:150,FigureactionGoTo:150, actionGoTo:150,7-2actionGoTo:150, to see an example route. Many other factors have anoticeable impact on influencing network latency and are outlined in the following list:Other devices sharing the same base station may cause your packets to be delayedQoS prioritization of network read more..

  • Page - 153

    iOS devices are usually run on battery power, and every action taken by your app consumes power.The primary consumers of power on an iOS device are as follows:Display and display backlightLocation servicesWi-Fi radioWWAN (cellular) radioGraphics processorCPUBluetooth RadioAudio processorWith the exception of the display, your application has control over most of these variables. As youoptimize your program for better network performance, you have a secondary benefit to improve thepower read more..

  • Page - 154

    With the advent of shared wireless networking such as GSM or CDMA, engineers have toreconsider the bandwidth used by the protocols they select for an application and apply methods toreduce the bandwidth used without sacrificing reliability or maintainability of the application. Thereare several ways to reduce the amount of bandwidth consumed by an app:Use an efficient data interchange format — Select an efficient encoding for data between theclient and server. Chapter 4, “Generating and read more..

  • Page - 155

    Response compression of text data can have a dramatic impact on the size of the data returned to theclient. With JSON or XML (see Chapter 4 for details on creating and processing JSON and XMLresponses) the compressed payload can be less than 10 percent the size of the original payload, butyour results may vary depending on the succinctness of the original payload. If the original sourceuses JSON with one-character field names and has all whitespace removed, you see more limitedresults compared read more..

  • Page - 156

    several common content types:AddOutputFilterByType DEFLATE text/plainAddOutputFilterByType DEFLATE text/xmlAddOutputFilterByType DEFLATE application/xhtml+xmlAddOutputFilterByType DEFLATE text/cssAddOutputFilterByType DEFLATE application/xmlAddOutputFilterByType DEFLATE application/atom_xmlAddOutputFilterByType DEFLATE application/x-javascriptAddOutputFilterByType DEFLATE text/htmlAddOutputFilterByType DEFLATE application/jsonEnabling response compression should be transparent to other read more..

  • Page - 157

    Request compression can be of significant benefit to mobile applications because wide areawireless transmission speeds are usually asymmetric, providing greater bandwidth to data sent to thedevice than to data originating from the device. The asymmetry is implemented because most webtraffic is usually asymmetric. If your application defies the standard asymmetric pattern, you shouldstrongly consider request compression. For example, if your application collects data for later uploadto a server, read more..

  • Page - 158

    actionGoTo:157,LISTINGactionGoTo:157, 7-1: Decomp.cgi#!/usr/bin/perlprint "Content-type: text/html\n\n";print "Hello, World.\n";print "Body=\n";foreach (<>) { print;}Next you add the compression code to your iOS app. It needs to both compress the payload and adda Content-Encoding header to the request. The example compression code uses the libz.dylibframework, which requires your project to link against that framework before compiling anycompression read more..

  • Page - 159

    actionGoTo:158,LISTINGactionGoTo:158, 7-2: PostCompress/CompressRequest.m- (NSData *)compressNSData:(NSData *)myData { NSMutableData *compressedData = [NSMutableData dataWithLength:16384]; z_stream compressionStream; // setup the compression stream compressionStream.next_in=(Bytef *)[myData bytes]; compressionStream.avail_in = [myData length]; compressionStream.zalloc = Z_NULL; compressionStream.zfree = Z_NULL; compressionStream.opaque = Z_NULL; read more..

  • Page - 160

    computational time required to compress the payload. actionGoTo:160,FigureactionGoTo:160, actionGoTo:160,7-4actionGoTo:160, shows the response time changeswhen different combinations of request and response compression are applied. The results here arecalculated using the Network Link Conditioner tool, which provides a more consistent performancethan an uncontrolled live cellular network.actionGoTo:160,FIGUREactionGoTo:160, 7-4The benefit is seen by the DSL profile because DSL connections are read more..

  • Page - 161

    seconds, usually about 10, before closing the connection. The technique can be used at a higher levelby holding nonessential updates until a sufficient batch has accumulated or some user action requiresnetwork activity. The app can then perform all the queued requests in close succession, keeping thesame connection active and avoiding the overhead of establishing more than one TCP connection.An alternative is to architect your service tier with a single service endpoint that proxies requeststo read more..

  • Page - 162

    actionURI(http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html):http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html. HTTP was designed for browser-to-server communications, and the caching mechanisms are geared toward that usage pattern. iOSprovides a mechanism to leverage standard HTTP caching and to also adopt alternative behaviors.Every request issued via NSURLRequest goes through a caching component. This component is aninstance of an NSURLCache object or a subclass of it. This object read more..

  • Page - 163

    request to bypass the local cache and to add headers to the request, asking intermediateappliances to also bypass their cache to provide the freshest data from the source server.NSURLRequestReturnCacheDataElseLoad — This setting causes the caching system to returna cached copy of the content without verifying with the server that it has the freshest copy. If acached copy of the request exists in the cache, it will be returned. If a cached copy does not exist,the content is retrieved via a read more..

  • Page - 164

    @implementation NonZeroingCache -(void)setMemoryCapacity:(NSUInteger)newMemSize{ if (newMemSize == 0) { NSLog(@"Attempt to set cache size to 0"); return; } [super setMemoryCapacity: newMemSize];} @endThe code in the setMemoryCapacity: method validates that the size is not zero and calls the superclass to set the new size for any value other than zero.You can maximize app performance by compressing data and pipelining requests, but the fastestrequests are the read more..

  • Page - 165

    Chapter 8Low-Level NetworkingWHAT’S IN THIS CHAPTER?Deciphering BSD SocketsImplementing CFNetwork APIsDeveloping with NSStreamWROX.COM CODE DOWNLOADS FOR THIS CHAPTERactionURI(http://www.wrox.com/remtitle.cgi?isbn=9781118362402):YouactionURI(http://www.wrox.com/remtitle.cgi?isbn=9781118362402): actionURI(http://www.wrox.com/remtitle.cgi?isbn=9781118362402):canactionURI(http://www.wrox.com/remtitle.cgi?isbn=9781118362402): read more..

  • Page - 166

    descriptor when created. The six most common socket API calls are summarized in actionGoTo:166,TableactionGoTo:166, 8-1.actionGoTo:166,TableactionGoTo:166, 8-1: BSD SOCKET API CALLSAPI CALLDESCRIPTIONint socket(int addressFamily, int type, int protocol)Creates and initializes a new socket. Returns a filedescriptor number on success and -1 on failureint bind(int socketFileDescriptor, sockaddr *addressToBind, intaddressStructLength)Assigns the socket to the address and port specified inthe read more..

  • Page - 167

    calls before it is ready to communicate.Configuring a Socket ServerThe BSD socket server must associate the socket with a unique address by calling bind(intsocketFileDescriptor, sockaddr *addressToBind, int addressStructLength). This takesthe socket and assigns, or binds, it to a specific address and port. It returns 0 for a successful bind and-1 otherwise. After the socket is bound, the next step depends on the type of connection you specifiedin the socket() call, either UDP or TCP:For UDP read more..

  • Page - 168

    int flags) and int receive(int socketFileDescriptor, char *buffer, intbufferLength, int flags) pair. When sending, the socket described by socketFileDescriptortransmits buffer’s bytes between 0 and bufferLength. If successful, it returns the number of bytessuccessfully sent and -1 for any failure. When receiving, buffer is populated with a copy of the firstbufferLength bytes read from the socket. Similarly to send(), receive() also returns the numberof bytes successfully read and -1 for any read more..

  • Page - 169

    actionGoTo:168,LISTINGactionGoTo:168, 8-1: Fetching Results in a Background Thread(LLNNetworkingController.m)- (void)start { NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"telnet://%@:%i", self.urlString, self.portNumber]]; NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(loadCurrentStatus:) object:url]; [t start];}The networking controller reports read more..

  • Page - 170

    @selector(networkingResultsDidFail:)]) { [self.delegate networkingResultsDidFail: @"Unable to connect to the warehouse server."]; } return; } NSLog(@"Successfully connected to %@", url); NSMutableData *data = [[NSMutableData alloc] init]; BOOL waitingForData = YES; // continually receive data until you reach the end of the data while (waitingForData){ const char *buffer[1024]; read more..

  • Page - 171

    1,024-byte chunks until a read call indicates that no more data is available. After all the data isdownloaded, it is converted to a string, parsed into each individual piece of environment data, andgiven to the UI for display to the user. Cleaning up a socket is as easy as calling close() on thesocket file descriptor.CFNETWORKCFNetwork is situated one step higher in the framework hierarchy and is a lightweight wrapperaround BSD sockets. You can notice many similarities in the callback methods read more..

  • Page - 172

    // create a read-only socket CFReadStreamRef readStream; CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)[url host], [[url port] integerValue], &readStream, NULL); // schedule the stream on the run loop to enable callbacks if (CFReadStreamSetClient(readStream, registeredEvents, read more..

  • Page - 173

    The only remaining part of initialization is to register the socket callback function, which requiresthree distinct steps:1. First, create a callback function to pass to the stream. Both read and write streams have thesame callback signatures and differ only in the type of stream reference passed as the firstargument. For example, the callback function can be any function that has the method signaturevoid socketCallback(CFReadStreamRef stream, CFStreamEventType event, void*info). The first read more..

  • Page - 174

    actionGoTo:173,LISTINGactionGoTo:173, 8-4: Example Read Stream Callback (LLNCFNetworkController.m)void socketCallback(CFReadStreamRef stream, CFStreamEventType event, void *myPtr) { LLNCFNetworkController *controller = (__bridge LLNCFNetworkController*)myPtr; switch(event) { case kCFStreamEventHasBytesAvailable: // read bytes until there are no more while (CFReadStreamHasBytesAvailable(stream)) { UInt8 buffer[kBufferSize]; int read more..

  • Page - 175

    runLoopMode is almost always kCFRunLoopCommonModes, which encompasses the default mode andany other manually added modes for the current thread. When the stream is integrated into the runloop, it’s as easy as starting the loop with CFRunLoopRun() and waiting for events to happen.NSSTREAMMoving up yet another level in the framework hierarchy leads to NSStream, which is an Objective-Cwrapper around the CFNetwork APIs. It uses a delegate protocol NSStreamDelegate that almostexactly mimics the read more..

  • Page - 176

    actionGoTo:175,LISTINGactionGoTo:175, 8-5: Creating an NSStream to a Hostname without NSHost(NSStream+StreamsToHost.m)+ (void)readStreamFromHostNamed:(NSString *)hostName port:(NSInteger)port readStream:(out NSInputStream **)readStreamPtr { assert(hostName != nil); assert((port > 0) && (port < 65536)); assert((readStreamPtr != NULL)); CFReadStreamRef readStream = NULL; CFStreamCreatePairWithSocketToHost(NULL, read more..

  • Page - 177

    case NSStreamEventHasBytesAvailable: { if (receivedData == nil) { receivedData = [[NSMutableData alloc] init]; } uint8_t buf[1024]; int numBytesRead = [(NSInputStream *)stream read:buf maxLength:1024]; if (numBytesRead > 0) { [receivedData appendBytes:(const void *)buf length:numBytesRead]; } else if (numBytesRead == 0) { read more..

  • Page - 178

    stream = nil;}SUMMARYThis chapter has taken you on a tour of the low-level networking frameworks available for iOS andprovides pros and cons for each. As you move up the framework hierarchy, code becomes shorter andless complex, but you also lose power as each layer of abstraction hides more of the raw networkingsockets that actually perform the communication. The warehouse server examples provide an easyway to determine the proper framework for your app because each implementation can read more..

  • Page - 179

    Chapter 9Testing and Manipulating Network TrafficWHAT’S IN THIS CHAPTER?Observing network trafficManipulating network traffic with proxiesSimulating real-world network conditionsWROX.COM CODE DOWNLOADS FOR THIS CHAPTERThe actionURI(http://wrox.com):wrox.com code downloads for this chapter are found read more..

  • Page - 180

    the exact data received from the server. For example, if your app adds HTTP headers to a request,you may need to know exactly how iOS is further manipulating those headers and what it eventuallytransmits to the server.The act of observing network traffic is called sniffing or packet analysis. Packet analyzers havebeen around since the early days of networking and are available for almost every type of physicalinterconnect and protocol. This section focuses on sniffing Ethernet and Wi-Fi read more..

  • Page - 181

    to switch access points. If the device and computer pair to different networks, the computer may notsee Wi-Fi traffic from the device.A second configuration, shown in actionGoTo:181,FigureactionGoTo:181, 9-2, uses the Internet-sharing feature of OS X to make thesniffing laptop act as the Wi-Fi access point.actionGoTo:181,FIGUREactionGoTo:181, 9-2In this configuration you need to connect the sniffing laptop to a wired Ethernet network and enableInternet sharing in OS X to share the Ethernet read more..

  • Page - 182

    NOTE The sudo command will prompt you for a password. You should use thepassword for the currently logged in account.The host filter can use either an IP address or a DNS host or domain name. If you specify a DNSdomain, any traffic to any host in that domain will be captured. You can also filter traffic frommultiple hosts by using logical operators to include other criteria. The following code captures trafficto host 192.168.1.50 and 10.1.2.25.sudo tcpdump host 192.168.1.50 or 10.1.2.25Depending read more..

  • Page - 183

    devices without being a super-user.When you start Wireshark you see a helpful start page, as shown in actionGoTo:183,FigureactionGoTo:183, 9-3, where you can starta trace directly against an interface, set trace options, or open an existing trace file.actionGoTo:183,FIGUREactionGoTo:183, 9-3If you start a trace directly on an interface, you see a flood of packets that are probably not helpful.If you start a trace by using the Capture->Options menu entry, you can tune your capture to fit read more..

  • Page - 184

    actionGoTo:183,TABLEactionGoTo:183, 9-1: Network Interface DescriptionsINTERFACE NAME INTERFACE TYPE DESCRIPTIONen0EthernetThe wired Ethernet port on an OS X laptopen1Wi-FiThe default Airport interface in OS Xlo0LoopbackThe local loopback interface used if a program connects to localhost or 127.0.0.1Use the capture filter field to specify which packets to capture using the same syntax as the tcpdumpcommand. The sniffer captures only packets going to hostactionURI(http://www.nasa.gov): read more..

  • Page - 185

    The Packet Decomposition panel exposes the values for each protocol layer for the packet selectedin the Captured Packets List. The packet is decomposed into three layers: Ethernet II, InternetProtocol, and Transmission Control Protocol (refer to actionGoTo:184,FigureactionGoTo:184, 9-5).The Packet Hex Dump area displays the hexadecimal values for each byte in the selected packetand an ASCII conversion of those hex values. If you drill down into a protocol layer in the PacketDecomposition panel read more..

  • Page - 186

    continuous set of data. The outbound and inbound data are shaded differently so that you can easilydistinguish the packet direction. In actionGoTo:186,FigureactionGoTo:186, actionGoTo:186,9-7actionGoTo:186, the data outbound from the phone has a darkbackground and the inbound data has a white background. Notice that the response data appears to begibberish because the Content-Encoding of the payload is gzip, and it must be decompressed toreveal its actual read more..

  • Page - 187

    Wireshark is a powerful tool that should be in every network developer’s tool box. It can beextended with modules, called dissectors, which parse many industry-standard protocols, but you canalso develop your own dissectors to parse your own custom protocols. If built from source,Wireshark can be used to decrypt SSL connections under certain circumstances. By using Wireshark,you can examine every bit and packet transmitted from the device for any networking protocol, whichis helpful if you are read more..

  • Page - 188

    discover how an app communicates with its servers.Network proxies are appliances that usually reside at the perimeter of a secured network and act asa go-between for every request sent to a server. Many large enterprises deploy network proxies toprovide content filtering, access control, virus protection, and response caching for personalcomputers within their network. The HTTP client, typically a browser, must be configured to use theactionGoTo:188,applianceactionGoTo:188, asactionGoTo:188, read more..

  • Page - 189

    the attack is intended to protect the enterprise. For this approach to work, the client must have theproxies’ CA certificate installed in its keychain. If the request is allowed, the proxy establishes anSSL connection with the target host and transmits the request securely.There are many proxy software and hardware packages available to network engineers. Thesepackages are designed for network engineers and have limited usefulness to app developers. read more..

  • Page - 190

    3. Next you must configure the iOS device to route all its HTTP traffic through the proxy. First,determine the IP address of the machine running Charles. On that machine, open a Terminalwindow and execute the ifconfig command. The following snippet shows part of the output.$ifconfiglo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384...en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether e0:f8:47:34:98:8a inet6 fe80::e2f8:47ff:fe34:988a%en1 read more..

  • Page - 191

    HTTP transaction. Charles groups these transactions into a single line. If you select a transaction andthe Structure tab above the transaction list, you can drill down into a request and examine the requestand response in detail. actionGoTo:191,FigureactionGoTo:191, 9-13actionGoTo:191, shows the capture of a single request from the app caught by theproxy.actionGoTo:191,FIGUREactionGoTo:191, 9-13HTTP BreakpointsCharles allows you to set a breakpoint on a URL so that you can interrupt and alter read more..

  • Page - 192

    The request Overview panel provides summary information about the request that is extracted fromthe request. Some of the values are undefined because a response has not yet been received. If youselect the Edit Request panel, you see the exact contents of the request that was sent by the device. Onthe Edit Request panel, as shown in actionGoTo:192,FigureactionGoTo:192, actionGoTo:192,9-16, you can manually manipulate the contents of therequest.actionGoTo:192,FIGUREactionGoTo:192, 9-16You can use read more..

  • Page - 193

    Using the response breakpoint panel, you can modify the HTTP response headers and body returnedby the server. Like editing the request, all the content of the response may be altered. This is apowerful feature that allows you to validate an app’s response to erroneous responses or simulateedge conditions that would normally be difficult to reproduce in the service tier.If the app you test has short request timeout values, then intercepting requests with breakpoints maycause timeout errors in read more..

  • Page - 194

    Using this window you can add a new rule set, add target URLs to the rule set, and create newrules. Each rule describes a text manipulation to perform on the requests and responses that match theURL. To add a rule, click the Add button on the rule section. The Rewrite Rule definition dialog, asshown in actionGoTo:194,FigureactionGoTo:194, 9-19, allows you to define the following:actionGoTo:194,FIGUREactionGoTo:194, 9-19The part of the message to modify including headers, query parameters, URL, read more..

  • Page - 195

    applying modifications to the HTTP data so that complex edge conditions or error scenarios can besimulated to validate the service tier or app.Charles has many other features that you can use to manipulate the HTTP conversation betweenyour app and a server. You can map requests to local files or other remote servers, which is helpful ifthe changes to a response are more complex than what can be accomplished with text replacement.You can also intercept and modify HTTPS requests with Charles. To read more..

  • Page - 196

    inform the user of the activity performed by the app.Cache implementation validation — It can be difficult to quantify the improvement provided bydata caching when running your app on a high-speed network. Using a traffic shaper you canquantify the improvement that your users can expect to see when caching is implemented.OS X Lion provides a great traffic shaper called Network Link Conditioner (NLC). NLC interactswith the low-level network interface drivers of OS X and throttles the speed of read more..

  • Page - 197

    SUMMARYAn enterprise-connected iOS application involves the use and cooperation of many networkcomponents outside of your control. Using tools to observe and manipulate network traffic betweenyour app and enterprise infrastructure can help you identify and avoid defects in your application.Network sniffers help you see the truth about what data is moving between the device and any remoteservers. HTTP proxies enable you to manipulate those communications to simulate new or defectiveconditions. read more..

  • Page - 198

    Chapter 10Using Push NotificationsWHAT’S IN THIS CHAPTER?Interacting with local notificationsProviding an excellent user experience with remote notificationsApplying notification best practices to your applicationWROX.COM DOWNLOADS FOR THIS CHAPTERYou can find the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): code downloads for this chapter read more..

  • Page - 199

    you create a custom remote notification service and integrate it into your Relationship Managerapplication.SCHEDULING LOCAL NOTIFICATIONSLocal notifications are ideally suited for self-contained applications where information is restrictedto a single device. Applications such as alarm clocks and task managers are perfect examples ofapplications where local notifications may be used.Unlike remote notifications, local notifications do not require explicit user approval for delivery.As noted read more..

  • Page - 200

    NSMonthCalendarUnitNSDayCalendarUnitNSHourCalendarUnitNSMinuteCalendarUnitNSSecondCalendarUnitNSWeekdayCalendarUnitNSWeekdayOrdinalCalendarUnitNSQuarterCalendarUnitNSWeekOfMonthCalendarUnitNSWeekOfYearCalendarUnitNSYearForWeekOfYearCalendarUnitThe user experience of a local notification will be driven by the configuration options set whilecreating it. The options allow you to alter the behavior of the notification, how the system delivers it,and how the application responds to being launched by read more..

  • Page - 201

    notification with the system for delivery on the fireDate specified during creation. The secondignores the specified fireDate and displays the notification to the user immediately.actionGoTo:201,ListingactionGoTo:201, 10-1actionGoTo:201, covers a method to create, configure, and schedule a local notification. This methodcan serve as the foundation for notification scheduling within an application.actionGoTo:201,LISTINGactionGoTo:201, 10-1: Method to Schedule Local read more..

  • Page - 202

    NOTE Although this will not be an issue for most applications, at the time of writing,there is a 64-notification limit imposed on local notifications. You can still schedulenotifications, but delivery is limited to the 64 closest notifications in chronologicalorder of fireDate, with the system disregarding the remaining notifications. Thismeans that if you currently have 64 local notifications scheduled, scheduling anotherwill discard the notification with the furthest fireDate from the current read more..

  • Page - 203

    notifications of a certain type, or for a certain contact.The lightweight CRM application allows you to schedule follow-up reminders for individualcontacts. In the event that the contact is no longer a customer or changes positions, it should have theability to cancel notifications for an individual contact. To accomplish this, you first need a method toretrieve all currently scheduled notifications for a given contact by looping through all localnotifications and inspecting the userInfo read more..

  • Page - 204

    Handling the Arrival of Local NotificationsHandling remote notifications is important to the overall user experience, therefore you must properlymanage local notifications as they arrive and ensure necessary information is presented to the user.How the application responds to a notification depends on the configuration specified during creationand whether the application is currently active. If the application is not currently active and a userselects the action button (or drags the lock screen read more..

  • Page - 205

    actionGoTo:204,LISTINGactionGoTo:204, 10-5: Local Notification Handling Within Launch Sequence(/Application/RelationshipManager/RelationshipManager/AppDelegate.m)- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // determine if app launched from a local notification UILocalNotification *localNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey]; if read more..

  • Page - 206

    actionGoTo:204,LISTINGactionGoTo:204, 10-6: Local Notification Handling When Application Is Active(/Application/RelationshipManager/RelationshipManager/AppDelegate.m)- (void)application:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification *)notification { // alert the user that a notification was received // because the user was in the application, we present // them with some additional information dispatch_async(dispatch_get_main_queue(), ^{ read more..

  • Page - 207

    UIAlertView display and delegate methods. This is one approach that enables you to handleUIAlertView input with data from the triggering notification. These categories are available atactionURI(https://github.com/MugunthKumar/UIKitCategoryAdditions):https://github.com/MugunthKumar/UIKitCategoryAdditions.WARNING At the time of writing, there is a known issue within the iOS Simulatorwhere the application:didReceiveLocalNotification: is fired twice, split secondsapart. Any logic placed within read more..

  • Page - 208

    different.actionGoTo:207,FIGUREactionGoTo:207, 10-2The process begins when an application requests permission to deliver notifications. This requestis made to the operating system, which then prompts the user for permission. If the user grantspermission, the operating system fetches a device token from APNs, which is delivered to theapplication and subsequently stored at the application’s remote push service. When an appropriateevent occurs, the application’s remote push service registers a read more..

  • Page - 209

    the iOS Provisioning Portal. This section walks you through the steps required to configure remotenotifications for the application and obtaining the necessary certificate files to communicate withAPNs and register notifications for delivery.1. First you need to generate a Certificate Signing Request (CSR) using the Keychain Accessapplication on your computer. A CSR is a request for an identity certificate from a certificateauthority, which for APNs is Apple. actionGoTo:209,FigureactionGoTo:209, read more..

  • Page - 210

    NOTE It may be worthwhile for you to save your CSR. APNs certificates,development, and production have lifespans of one year. Saving your CSR makesthe renewal process easier and could help avoid service interruptions.3. After your CSR has been generated, select the new private key, and export it to a safe,memorable place. You can export the private key by Ctrl+clicking the private key entry inKeychain Access and choosing the export option, but be sure to remember the export passwordyou set.4. read more..

  • Page - 211

    Notification Service box and then choose the Configure option in the right-most column.actionGoTo:210,FIGUREactionGoTo:210, 10-66. After you select Continue, a screen similar to actionGoTo:211,FigureactionGoTo:211, 10-7 appears. Because you have alreadygenerated your CSR (refer to actionGoTo:209,FigureactionGoTo:209, 10-4) you can click Continue through this view.actionGoTo:211,FIGUREactionGoTo:211, 10-7 read more..

  • Page - 212

    actionGoTo:212,7.actionGoTo:212, AfteractionGoTo:212, clickingactionGoTo:212, throughactionGoTo:212, theactionGoTo:212, screenactionGoTo:212, inactionGoTo:212, actionGoTo:211,FigureactionGoTo:211, 10-7actionGoTo:212,,actionGoTo:212, youactionGoTo:212, seeactionGoTo:212, anotheractionGoTo:212, screen,actionGoTo:212, similaractionGoTo:212, toactionGoTo:212, FigureactionGoTo:212, 10-actionGoTo:212,8,actionGoTo:212, withactionGoTo:212, aactionGoTo:212, promptactionGoTo:212, toactionGoTo:212, read more..

  • Page - 213

    8. If everything works as planned, you see a slight overlay while Apple generates your APNscertificate and then a success message that resembles actionGoTo:213,FigureactionGoTo:213, 10-9. Click the Continue button tonavigate to the next screen, and download your certificate, as shown in actionGoTo:214,FigureactionGoTo:214, 10-10.actionGoTo:213,FIGUREactionGoTo:213, 10-9 read more..

  • Page - 214

    actionGoTo:213,FIGUREactionGoTo:213, 10-109. Navigate back to the list of applications; you should now see that push notifications have beensuccessfully configured for development, as shown inactionGoTo:214, FigureactionGoTo:214, 10-11.actionGoTo:214,FIGUREactionGoTo:214, 10-11 read more..

  • Page - 215

    NOTE Application builds (development and distribution) that use remote notificationsmust be signed with a provisioning profile configured for remote notifications. If youhave previously issued provisioning profiles for the application, you should re-issuethem after configuring remote notifications. You cannot request permission to delivernotifications until the application is signed correctly.Because this chapter uses PHP for the service tier, you need to combine the private key createdalong read more..

  • Page - 216

    Remote notifications are now configured, and you have the necessary files for the server to connectto APNs and register notifications. Now, you need to request permission to deliver notifications toyour users.Registering for Remote NotificationsBefore you can send your first notification, the remote server must be configured to register eachuser’s device. Users can have more than one device, and your storage method must allow for it.actionGoTo:216,ListingactionGoTo:216, 10-7actionGoTo:216, read more..

  • Page - 217

    actionGoTo:216,LISTINGactionGoTo:216, 10-8: Server-side Script to Register Users and Devices (/PushServer/register.php)<?php ... // get the post body $userid = $_REQUEST['user']; $token = $_REQUEST['token']; if (empty($userid) || empty($token)) { sendAPIResponse(400); return; } // determine if user exists $sql = "SELECT userid FROM users WHERE userid='".$userid."' LIMIT 1;"; $query = read more..

  • Page - 218

    actionGoTo:217,LISTINGactionGoTo:217, 10-9: Request Permission to Deliver Remote Notifications(/Application/RelationshipManager/RelationshipManager/AppDelegate.m)- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // request permission to deliver remote notifications, if needed BOOL requested = [[NSUserDefaults standardUserDefaults] boolForKey:kPushTokenTransmitted]; if (requested != YES) { read more..

  • Page - 219

    it.UIRemoteNotificationTypeBadgeThis permission allows access to set the application’s icon badge.UIRemoteNotificationTypeSoundThis permission allows access to play a short sound when either an alertor badge notification is delivered.UIRemoteNotificationTypeNewsstandContentAvailabilityThis permission allows access to notify the application when there is newcontent available for download via the Newsstand framework.After a user grants permission, the application invokes read more..

  • Page - 220

    actionGoTo:219,LISTINGactionGoTo:219, 10-10: Handling Remote Notification Approval(/Application/RelationshipManager/RelationshipManager/AppDelegate.m)- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // hardcode the current user, this would typically // be a token or value retrieved after they logged // in to use the app NSString *userId = @"nate@emaildomain.com"; NSString *token = [NSString read more..

  • Page - 221

    Remote Notification PayloadsAPNs payloads are JSON objects with a strict limit of 256 bytes. It is your responsibility to ensurethat the payload does not exceed this limit, or the notification will be rejected by APNs. Payloads arekey-value pairs with a top-level namespace aps. The following snippet outlines a standard APNspayload structure in human-readable form.{ "aps" : { "alert" : "New delivery received.", "badge" : 1, read more..

  • Page - 222

    messages are properly translated.Localizing remote notifications within the application does require up-front planning but onlyrequires that you specify a value for the loc-key parameter, which is the key to the localized valueused as the message body text. You can also provide an optional array of arguments to display in thelocalized message body using the loc-args property. Localized messages are still subject to the 256byte payload restriction. This approach has the added benefit of requiring read more..

  • Page - 223

    actionGoTo:222,LISTINGactionGoTo:222, 10-11: Method to Connect with APNs (/Push Server/apns.php)function sendPushNotification ($token, $payload) { $certificate = "../Path/To/Certificate/AcmeCertKey.pem"; $passphrase = "YourPassphrase"; $endpoint = "ssl://gateway.sandbox.push.apple.com:2195" $context = stream_context_create(); stream_context_set_option ($context, 'ssl', read more..

  • Page - 224

    notification being transmitted. If an error occurs, APNs returns an error response along with theassigned identifier for further investigation. actionGoTo:224,TableactionGoTo:224, 10-5actionGoTo:224, details the different APNs response codes andtheir meaning.actionGoTo:224,TABLEactionGoTo:224, 10-5: APNs Enhanced Format Response CodesRESPONSE CODE DESCRIPTION0No errors encountered1Processing error2Missing device token3Missing topic4Missing payload5Invalid token size6Invalid topic size7Invalid read more..

  • Page - 225

    actionGoTo:224,LISTINGactionGoTo:224, 10-12: Remote Notification Test Delivery Script (/Push Server/sendNotification.php)<?php ... // get request parameter values $userId = $_REQUEST['userid']; $contactEmail = $_REQUEST['contact']; $message = $_REQUEST['message']; $badge = $_REQUEST['badge']; $sound = $_REQUEST['sound']; // clean up the action value $action = $_REQUEST['action']; $action = (!empty($action)) ? $action : "View"; // get read more..

  • Page - 226

    userid: actionURI(mailto:nate@emaildomain.com):nate@emaildomain.comcontact: actionURI(mailto:John@prospect.com):John@prospect.commessage: Email John about proposalbadge: 1action: EmailThe userid value in the preceding parameter list matches the hardcoded value in the registrationprocess covered in actionGoTo:220,ListingactionGoTo:220, actionGoTo:220,10-10. The value specified for contact should match an entry that hasbeen added to the Relationship Manager application. This ensures that you read more..

  • Page - 227

    provider and whether the application is active. If the application is not currently active and the userselects the action button (or drags the lock screen slider) the application launches. Just like a standardlaunch, the application:didFinishLaunchingWithOptions: method is invoked in the applicationdelegate. You can retrieve the remote notification payload from the launchOptions dictionary usingthe key UIApplicationLaunchOptionsRemoteNotificationKey. actionGoTo:227,ListingactionGoTo:227, read more..

  • Page - 228

    (/Application/RelationshipManager/RelationshipManager/AppDelegate.m)- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // alert the user that a notification was received // because the user was in the application, we present // them with some additional information / options dispatch_async(dispatch_get_main_queue(), ^{ NSString *action = [[[userInfo objectForKey:@"aps"] read more..

  • Page - 229

    } } } onCancel:^() { // don't do anything for cancel }]; }); // reset the application badge to 0 [UIApplication sharedApplication].applicationIconBadgeNumber = 0;}The application now contains custom support for remote notifications and provides users with anenhanced experience if a notification is received while they use the application. Install theapplication on a read more..

  • Page - 230

    should request permission only to deliver remote notifications when you need to. For example, ifyou offer remote notifications as a paid upgrade, do not request permission to deliver remotenotifications until the user initiates the upgrade process.Ensure remote notification value is clear: Users must understand the value they will receive byallowing you to deliver remote notifications. Ideally, this value proposition is understood priorto requesting permission.Limit remote notification read more..

  • Page - 231

    using a custom notification payload value, to enhance your understanding of which messages aremost effective.SUMMARYLocal and remote notifications provide a unique channel for engaging your users and drivingefficiency in your business. Local notifications can be effective in driving users to respond to localreminders and require little overhead and management when deployed. Remote notifications offer themost flexibility for external integration but require additional configuration and read more..

  • Page - 232

    PART IVNetworking App to AppCHAPTER 11: Inter-App CommunicationCHAPTER 12: Device-to-Device Communication with Game KitCHAPTER 13: Ad-Hoc Networking with Bonjour read more..

  • Page - 233

    Chapter 11Inter-App CommunicationWHAT’S IN THIS CHAPTER?Registering custom URL schemesChanging behavior based on the presence of other installed appsLeveraging enterprise single sign-onDetecting and reusing data from previous installationsWROX.COM CODE DOWNLOADS FOR THIS CHAPTERThe actionURI(http://wrox.com):wrox.com code downloads for this chapter are found read more..

  • Page - 234

    Implementing a Custom URL SchemeThe first step to implementing a custom URL scheme is to determine which features of yourapplication would be useful for another application to invoke. For example, a shopping app mightwant to display a product’s information when given a UPC code or a messaging app couldprepopulate a recipient and message. It is also useful to allow other apps to link to the most popularviews in your app, which in a tab bar application is commonly the root view for each tab. To read more..

  • Page - 235

    will resume and only application:openURL:sourceApplication:annotation: will be called tohandle the URL. The two possible execution paths are shown inactionGoTo:235, FigureactionGoTo:235, 11-2.actionGoTo:235,FIGUREactionGoTo:235, 11-2Because your URL scheme often displays a different view than would normally show on launch,you can define a variety of default images for each URL scheme you implement. Each variationfollows a specific format with a mix of required and optional values.The read more..

  • Page - 236

    previously. More specific bounds checking, pattern matching, or some other validation may also beappropriate. In the Acme Employee Directory shown in actionGoTo:236,ListingactionGoTo:236, 11-1, the URL is checked to ensure ituses the custom scheme acme-directory, requests the identifier employee, and supplies anemployee identifier that exists.actionGoTo:236,LISTINGactionGoTo:236, 11-1: Validating an Acme Directory URL (EDAppDelegate.m) - (BOOL)canHandleURL:(NSURL *)url read more..

  • Page - 237

    familiar user interface in a client that has already been authorized on the service.To start sensing the presence of another app, you first need to know the custom URL scheme(s)provided by the destination app. Many developers publish the details of any custom schemes in theirAPI documentation or on a developer-specific page on their websites. After you have the schemename, implementing the feature is relatively easy using UIApplication’s canOpenURL: method. Itreturns YES if an application is read more..

  • Page - 238

    actionGoTo:237,LISTINGactionGoTo:237, 11-2: Checking for Companion Applications (EDUtils.m)+ (NSDictionary*)dictionaryOfInstalledCompanionApps { NSMutableDictionary *companionApps = [NSMutableDictionary dictionary]; // employee records if ([[UIApplication sharedApplication] canOpenURL: [NSURL URLWithString:@"acme-records://"]]) { [companionApps setValue:@"acme-records://employee/" forKey:@"Employee Records"]; } read more..

  • Page - 239

    UIImageUIImageJPEGRepresentation() or UIImagePNGRepresentation()Objects conforming to NSCoding NSKeyedArchiverPrimitive typesNSKeyedArchiverAfter the object has been represented as an NSData object, it must be converted to a string to passthrough a URL. An obvious answer is to use NSString’s initWithData:encoding:; however, theresulting string would not be safe to include in a URL. RFC 3986 defines a list of valid charactersthat may be included in a URL, summarized inactionGoTo:239, read more..

  • Page - 240

    Although the base64-encoded string is close, it is still not quite ready for inclusion in the URL.Characters 62 (“+” or plus) and 63 (“/” or forward slash) each have a special meaning in a URL andcould potentially disrupt the receiving app from decoding your binary data correctly. The plus signrepresents a space character when used in the query string, and if your data is interpreted as a space,the parser could stop prematurely or interpret erroneous data. The forward slash character is read more..

  • Page - 241

    actually returns the exact same string unchanged.The second solution is to use a base64 variant called base64url that was created to address thissituation. It uses a modified conversion table that replaces the plus sign with a hyphen (-) and theforward slash with an underscore (_). The modified conversion table is shown in actionGoTo:241,TableactionGoTo:241, 11-4.actionGoTo:241,TABLEactionGoTo:241, 11-4: base64url Conversion TableA fourth sample application Employee Records Image Adder adds an read more..

  • Page - 242

    actionGoTo:241,LISTINGactionGoTo:241, 11-3: Passing an Image in a Custom URL Scheme (IAViewController.m)// encode the image as dataNSData *imageData = UIImagePNGRepresentation(imageView.image); // turn the data into a string by base64-encoding itNSString *imageString = [imageData base64EncodingWithLineLength:0]; // url-encode the base64 stringNSString *encodedString = [IAUtils encodeURL:imageString]; // create and open the URLNSURL *url = [NSURL URLWithString:[NSString stringWithFormat: read more..

  • Page - 243

    requiring the user to log in to those apps as well. If the token cannot be shared, the user’s accountidentifier or e-mail address can still be saved, providing a smaller but still significant productivitygain.Three preliminary steps must be taken before a project can use a shared keychain for SSO:1. Each app must share a common Bundle Seed ID, which is a value set in the iOS ProvisioningPortal when applications are created. actionGoTo:243,FigureactionGoTo:243, read more..

  • Page - 244

    D. Expand Link Binaries with Libraries.E. Click the + button.F. Search for and add Security.framework.Now that the project is configured, it is prudent to begin by developing some low-level keychainutility methods that can help drive high-level functionality of the application. Because this utility classwill be included in each individual SSO-enabled app, its implementation should be decoupled fromimplementation details of any one application. Ideally, it should be compiled into a static library read more..

  • Page - 245

    actionGoTo:244,LISTINGactionGoTo:244, 11-5: Retrieving a Keychain Item (SSOUtils.m)+ (NSString*)getValueForIdentifier:(NSString*)identifier { NSMutableDictionary *search = [self keychainSearch:identifier]; // limit to the first result [search setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; // return data vs a dictionary of attributes [search setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; // perform the search NSData *value = nil; OSStatus status read more..

  • Page - 246

    operations, and your implementation must determine which is appropriate. Thus, it callsgetValueForIdentifier: to determine if an item with this identifier already exists. If it does exist,the method branches into the update logic. If the new value differs from the existing value, it will beconverted to an NSData object and then inserted in the update parameters NSDictionary with thekey kSecValueData. There are many other attributes that can be included in this dictionary, and thefull list is read more..

  • Page - 247

    successful, the utility method returns YES; otherwise it returns NO.actionGoTo:246,LISTINGactionGoTo:246, 11-7: Deleting a Keychain Item (SSOUtils.m) + (BOOL)deleteValueForIdentifier:(NSString*)identifier { NSMutableDictionary *search = [self keychainSearch:identifier]; OSStatus status = SecItemDelete((CFDictionaryRef)search); if (status == errSecSuccess) { return YES; } return NO;}Now that the app has some building blocks to use for keychain interaction, high-level read more..

  • Page - 248

    actionGoTo:247,LISTINGactionGoTo:247, 11-9: Validating Stored Credentials (SSOUtils.m)+ (BOOL)credentialsAreValid { NSString *token = [self credentialToken]; if (token == nil) { return NO; } // you should do a secure check of the token here // we'll do a dummy check to make sure it matches our // secret value 'SSOValidToken' return [token isEqualToString:@"SSOValidToken"];}The last high-level operation logs out the current user by deleting the stored read more..

  • Page - 249

    actionGoTo:248,LISTINGactionGoTo:248, 11-11: Changing the UI Based on a Previous Installation(IDViewController.m)- (void)viewDidLoad { // check for a previous installation NSString *savedBirthday = [IDUtils savedBirthday]; BOOL firstLaunch = [IDUtils isFirstLaunch]; if (savedBirthday != nil && firstLaunch) { [[[UIAlertView alloc] initWithTitle:NSLocalizedString( @"Previously Saved Birthday",@"Previously Saved Birthday") read more..

  • Page - 250

    actionGoTo:249,LISTINGactionGoTo:249, 11-13: Detecting the First Launch of an Application (IDUtils.m)+ (BOOL)isFirstLaunch { BOOL hasBeenLaunched = [[NSUserDefaults standardUserDefaults] boolForKey:kDefaultsHasBeenLaunchedKey]; if (hasBeenLaunched == NO) { // this is the first launch, so set a defaults value // saying that we were launched at least once [[NSUserDefaults standardUserDefaults] setBool:YES read more..

  • Page - 251

    Chapter 12Device-to-Device Communication with Game KitWHAT’S IN THIS CHAPTER?Using Game Kit classes and configuring transfer optionsUnderstanding traditional client-server communicationcreating peer-to-peer connectionsWROX.COM CODE DOWNLOADS FOR THIS CHAPTERThe actionURI(http://wrox.com):wrox.com code downloads for this chapter are found read more..

  • Page - 252

    NOTE This chapter does not discuss the gaming features because they are used onlywith Apple’s Game Center service and are not applicable for general purposecommunication.Game Kit networking gives developers three communication modes that control the flow of datamessages among the devices in a network. These networks are represented on each device as aGKSession instance, and each connected device, or peer, is identified by its peer ID.Peer-to-peer (P2P) — This mode treats each peer equally read more..

  • Page - 253

    responds to both Bluetooth and Wi-Fi peers.GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; // search for only Bluetooth peerspicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby; // search for only Wi-Fi peerspicker.connectionTypesMask = GKPeerPickerConnectionTypeOnline; // search for Bluetooth or Wi-Fi peerspicker.connectionTypesMask = (GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline); [picker show];Although read more..

  • Page - 254

    guarantees of GKSendDataReliable and GKSendDataUnreliable. Examples of both reliabilitymodes are shown in the following code.NSError *error;GKSession *session;NSMutableData *stateUpdatePacket;NSMutableData *heartbeatPacket; // initialization code omitted for brevity // send this state update packet reliablyif (![session sendDataToAllPeers:stateUpdatePacket withDataMode:GKSendDataReliable error:&error]) { NSLog(@"Error sending packet: read more..

  • Page - 255

    NOTE When two devices connect via USB, both appear in the Scheme/Device drop-down along with any installed Simulators. To debug an app on both devices, simplyselect one device and run the app; then select the second device and run the app again.To switch between consoles or debuggers on each device, choose between the devicesin the Debug Area’s top toolbar drop-down.PEER-TO-PEER NETWORKINGPeer-to-peer Game Kit connections allow any peer in the network to behave as both a server andclient read more..

  • Page - 256

    actionGoTo:255,LISTINGactionGoTo:255, 12-1: Creating a GKSession (GANetworkingManager.m)#define kGameKitSessionID @"auctioneer1.0" // create a new GameKit session_session = [[GKSession alloc] initWithSessionID:kGameKitSessionID displayName:nil sessionMode:GKSessionModePeer];_session.delegate = self;The session ID is the first parameter and is constant across all instances of the application andensures that you read more..

  • Page - 257

    actionGoTo:256,FIGUREactionGoTo:256, 12-3When tapping a row of the UITableView, Auctioneer calls the GKSession’sconnectToPeer:withTimeout:, which prompts that peer’s GKSessionDelegate to receivesession:didReceiveConnectionRequestFromPeer:, which shows the invitation UIAlertView. Ifthe remote peer accepts, it calls acceptConnectionFromPeer:error: on its GKSession, and the read more..

  • Page - 258

    local peer receives session:peer:didChangeState: with a new state of GKPeerStateConnected.Other peer states are shown in actionGoTo:258,TableactionGoTo:258, 12-1. The remote peer can then enter the auction UI and wait forthe auction to start. If the remote peer declines the invitation, it calls denyConnectionFromPeer:and the local peer receives session:connectionWithPeerFailed:withError:. Peers that rejectinvitations simply stay in the auction lobby. actionGoTo:258,FigureactionGoTo:258, read more..

  • Page - 259

    actionGoTo:259,ListingactionGoTo:259, actionGoTo:259,12-2 shows the four message types defined as an enumeration GAPacketType, which mapsthem to integer values.actionGoTo:259,LISTINGactionGoTo:259, 12-2: Packet Type Enumeration (GANetworkingPackets.h)typedef enum { GAPacketTypeAuctionStart = 0, GAPacketTypeAuctionEnd, GAPacketTypeAuctionStatus, GAPacketTypeBid} GAPacketType;The integer mapping is important because you can prefix the data of the packet with the integervalue of the read more..

  • Page - 260

    actionGoTo:259,LISTINGactionGoTo:259, 12-3: Populating and Serializing a Data Packet (GALobbyViewController.m)/* * tell all participants this auction is starting */NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];GAPeer *devicePeer = [[GANetworkingManager sharedManager] devicePeer]; // auction owner[dataDict setObject:devicePeer.peerID forKey:@"ownerPeerID"]; // item name[dataDict setObject:itemName forKey:@"itemName"]; // number of participants[dataDict read more..

  • Page - 261

    }Each peer receives the data packet and passes it to GANetworkingManagerAuctionDelegate’smanager:didReceivePacket:ofType: method for further action, as shown in the following snippetfrom the code file GANetworkingManager.m. The packet type is decoded from the beginning of thedata packet, and the remaining data is restored into an exact copy of the NSData that was originallysent.- (void)receiveData:(NSData*)data fromPeer:(NSString*)peerID inSession:(GKSession*)session read more..

  • Page - 262

    actionGoTo:261,FIGUREactionGoTo:261, 12-6 read more..

  • Page - 263

    actionGoTo:261,LISTINGactionGoTo:261, 12-4: Decoding a Packet (GAAuctionViewController.m)- (void)manager:(GANetworkingManager*)manager didReceivePacket:(NSData*)data ofType:(GAPacketType)packetType { switch (packetType) { case GAPacketTypeAuctionStart: { NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; NSDictionary *dataDict = [unarchiver decodeObjectForKey: read more..

  • Page - 264

    _session = [[GKSession alloc] initWithSessionID:kGameKitSessionID displayName:nil sessionMode:GKSessionModeServer]; // create a new GameKit session as a client_session = [[GKSession alloc] initWithSessionID:kGameKitSessionID displayName:nil sessionMode:GKSessionModeClient]; _session.delegate = self;The first difference from P2P networking is that read more..

  • Page - 265

    message = [NSString stringWithFormat:@"You won the auction with a bid of $%i!", winningBid]; } else { message = [NSString stringWithFormat:@"%@ won the auction with a bid of $%i!", [[GANetworkingManager sharedManager] displayNameForPeer: [[GAPeer alloc] initWithPeerID:winnerPeerID]], winningBid]; } UIAlertView read more..

  • Page - 266

    Chapter 13Ad-Hoc Networking with BonjourWHAT’S IN THIS CHAPTER?Using zero configuration networkingResolving and connecting to Bonjour servicesImplementing Bonjour to provide an excellent user experienceWROX.COM DOWNLOADS FOR THIS CHAPTERYou can find the actionURI(http://wrox.com):wrox.comactionURI(http://wrox.com): code downloads for this chapter read more..

  • Page - 267

    getting associates in front of inquisitive customers to provide that exceptional shopping experience.This pair of applications consists of an internal, employee-only application and a consumer-facingapplication like you would find in the App Store.ZEROCONF OVERVIEWBonjour is a technology that enables devices to easily discover and connect with other devices on thesame network. It was released in 2002 under the moniker Rendezvous and in 2005 was eventuallyrenamed to Bonjour. Although Bonjour can read more..

  • Page - 268

    There are two types of mDNS queries: One-Shot Multicast and Continuous Multicast. The One-Shot approach is simpler and takes the first response that it receives without listening for additionalresponses. Although simple, it can fulfill the requirement where an end user enters a fully qualifiedlocal address, such asactionURI(http://njones.local): http://njones.local, or actionURI(http://OfficeJet6300.local):http://OfficeJet6300.local.Continuous querying does not assume that a single response read more..

  • Page - 269

    Domain: Represents the DNS subdomain within which the service name is registered. This valuecould be local. Subdomains are supported and provide a simple means of organizing services.For example, you might broadcast printers onactionURI(http://printers.apple.com): printers.apple.com to unclutter actionURI(http://apple.com):apple.com.BONJOUR OVERVIEWGiven that Bonjour is a zeroconf implementation, it’s natural to assume that deploying and connectingto a Bonjour service follows a series of steps read more..

  • Page - 270

    NOTE There is a similar method, initWithDomain:type:name:, intended for usewhen the domain, type, and name are already known and the application wants tocircumvent the browsing process. It is typically used when the client has previouslyconnected to a service. This is discussed further in the “Resolving a Service” section.The type argument is required and identifies how and what the service does. It consists of theservice type, or Application Protocol Name, and the transport protocol. The read more..

  • Page - 271

    SO_REUSEADDR, (void *)&yes, sizeof(yes)); setsockopt(CFSocketGetNative(ipv6socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); // set up the IPv4 endpoint// if port is 0, causes the kernel to choose a portstruct sockaddr_in addr4;memset(&addr4, 0, sizeof(addr4));addr4.sin_len = sizeof(addr4);addr4.sin_family = AF_INET;addr4.sin_port = htons(port);addr4.sin_addr.s_addr = htonl(INADDR_ANY);NSData read more..

  • Page - 272

    In this listing the application first creates a socket context and two sockets, PF_INET for IPv4 andPF_INET6 for IPv6. kCFSocketAcceptCallback instructs the socket to accept connection requestsand call the callback function passed as a pointer to argument six,(CFCallBack)&BonjourServerAcceptCallback, which is discussed in actionGoTo:286,ListingactionGoTo:286, actionGoTo:286,13-6. The lastargument is the socket context, created to pass a reference to self, which is ultimately passed to read more..

  • Page - 273

    NSNetServiceNoAutoRename, which suppresses the renaming behavior.Success or failure of the publishing process is communicated via the netServiceDidPublish: andnetService:didNotPublish: delegate methods, respectively. The second parameter ofnetService:didNotPublish: is an NSDictionary object containing two key-value pairs. One pairis the error domain, which can be accessed with the key NSNetServicesErrorDomain, and the otheris the error code, which can be accessed with the key read more..

  • Page - 274

    BONJOUR SERVICES IN A MULTITASKINGENVIRONMENTApple’s introduction of multitasking in iOS 4, although a welcome addition, greatlycomplicated how networking is handled within applications as they enter the background andare resumed to the foreground. Applications sent to the background are candidates to besuspended. Bonjour communicates over sockets, which cannot be processed by an applicationwhen it is suspended. The operating system, however, still sees the socket as active andaccepts the read more..

  • Page - 275

    maintain a collection of all services if you want to display them to the user. The moreComingparameter indicates whether this method will be called again with additional services. To provide theoptimal user experience, you should refrain from updating the user interface until the moreComingparameter is NO. If you expect a large number of services and want to provide incremental feedback,the application could “group” results and update the user interface every nth service discovered.Receiving read more..

  • Page - 276

    NSString *errorCode = [errorDict objectForKey:NSNetServicesErrorCode]; NSString *errorDomain = [errorDict objectForKey:NSNetServicesErrorDomain]; // alert user of the error [browser stop];}After the search stops, the netServiceBrowserDidStopSearch: delegate method is called. Thisprovides the application with an opportunity to perform any necessary clean up and update the userinterface to indicate that a search is no read more..

  • Page - 277

    address. To do this, you need to call the resolveWithTimeout: method on the service with whichthe application wants to connect. There are two methods to retrieve an NSNetService object. First,the user could select one from a list fetched by an NSNetServiceBrowser as discussed previously.The second approach is to create an instance of NSNetService directly using theinitWithDomain:type:name: method. The latter is used in situations in which the device haspreviously connected to the service and the read more..

  • Page - 278

    Address information can be retrieved from the addresses property on the NSNetService object,which is passed to the delegate. The addresses property is an NSArray of NSData objects eachcontaining a sockaddr struct. If address information is missing, you can expect another call to thenetServiceDidResolveAddress: method. You can extract address components like so.- (void)netServiceDidResolveAddress:(NSNetService *)sender { for (NSData *addressData in [sender addresses]) { struct read more..

  • Page - 279

    dictionaryFromTXTRecordData: [sender TXTRecordData]]; NSData *versionData = [txtDictionary objectForKey:@"version"]; NSString *version = [[NSString alloc] initWithData:versionData encoding:NSUTF8StringEncoding]; ...}As a reminder, the object stored for each key is an instance of NSData, which typically requires anadditional statement to convert it to read more..

  • Page - 280

    inputStream = is; inputStream.delegate = self; [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; if (inputStream.streamStatus == NSStreamStatusNotOpen) { [inputStream open]; } } ...}This example fetches the input stream and then tests to ensure that a valid stream was returned. If avalid stream were returned, it is assigned to an instance variable used in the stream read more..

  • Page - 281

    maxLength:1024]; if(len) { [receiveData appendBytes:(const void *)buffer length:len]; bytesRead = [NSNumber numberWithInt:([bytesRead intValue]+len)]; if (![inputStream hasBytesAvailable]) { NSString *result = [[NSString alloc] read more..

  • Page - 282

    streamStatus property, this is the proper place to do so. NSStreamEventEndEncountered isequally as straightforward in that it closes the stream that has ended and removes it from the run loopso that it does not continue to be monitored each time through the run loop. If anNSStreamEventErrorOccurred event is received, the application logs a statement to the consolethat includes the additional streamError details.The code within the NSStreamEventHasBytesAvailable event may look foreign compared read more..

  • Page - 283

    Customer help requests are represented by the HelpRequest class, as defined inactionGoTo:283, ListingactionGoTo:283, 13-2.actionGoTo:283,LISTINGactionGoTo:283, 13-2: HelpRequest Class Definition (/Apps/Associate/associate-help/associate-help/HelpRequest.h)@interface HelpRequest : NSObject <NSCoding> @property(nonatomic,strong) NSString *question;@property(nonatomic,strong) NSString *location; @endAs you can see in actionGoTo:283,ListingactionGoTo:283, 13-2, the HelpRequest class conforms read more..

  • Page - 284

    actionGoTo:283,LISTINGactionGoTo:283, 13-4: HelpResponse Interface and Implementation(/Apps/Associate/associate-help/associate-help/HelpResponse.h/m)@interface HelpResponse : NSObject <NSCoding> @property(nonatomic,assign) BOOL response; @end @implementation HelpResponse @synthesize response; #pragma mark - NSCoding- (void)encodeWithCoder:(NSCoder*)aCoder { [aCoder encodeBool:self.response forKey:@"response"];} - (id)initWithCoder:(NSCoder*)aDecoder { self = [super read more..

  • Page - 285

    class, a singleton that handles all NSNetService-related and NSStream-related details. actionGoTo:285,ListingactionGoTo:285, actionGoTo:285,13-5outlines the Bonjour class definition; note the notification constants declared above the interface.These are the notification names broadcast using NSNotificationCenter. All code for the employeeapplication can be found in the Chapter 13 download folder on the companion website.actionGoTo:285,LISTINGactionGoTo:285, 13-5: Bonjour Interface Definition read more..

  • Page - 286

    actionGoTo:272,LISTINGactionGoTo:272, 13-6: Bonjour Implementation (/Apps/Associate/associate-help/associate-help/Bonjour.m)- (BOOL)publishServiceWithName:(NSString*)name { // setup the listening socket for connection attempts // and determine a port on which to advertise the service if (![self setupListeningSocket]) { return NO; } // create the service for publishing // this type should be registered - iana.org service = [[NSNetService alloc] read more..

  • Page - 287

    actionGoTo:286,LISTINGactionGoTo:286, 13-7: NetService Publication Delegate Methods (/Apps/Associate/associate-help/associate-help/Bonjour.m)- (void)netServiceDidPublish:(NSNetService *)sender { [Utils postNotifification:kPublishBonjourSuccessNotification];} - (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict { // typically you would pass along the errorDict // object or some form of error messaging [Utils read more..

  • Page - 288

    actionGoTo:287,LISTINGactionGoTo:287, 13-8: Connection Request Callback Function (/Apps/Associate/associate-help/associate-help/Bonjour.m)static void BonjourServerAcceptCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { Bonjour *server = (__bridge Bonjour*)info; if read more..

  • Page - 289

    underlying native socket when the stream is released. After the stream properties have been set, theyare cast to their respective Objective-C types, and thenactionGoTo:289,handleNewConnectionWithInputStream:outputStream:actionGoTo:289, isactionGoTo:289, called,actionGoTo:289, asactionGoTo:289, implementedactionGoTo:289, inactionGoTo:289, ListingactionGoTo:289, 13-actionGoTo:289,9.actionGoTo:289,LISTINGactionGoTo:289, 13-9: handleNewConnectionWithInputStream:outputStream: read more..

  • Page - 290

    // state stored so that you could determine // which object you are expecting. HelpRequest *request; @try { request = [NSKeyedUnarchiver unarchiveObjectWithData:receiveData]; NSDictionary *info = [NSDictionary read more..

  • Page - 291

    After the employee responds to the HelpRequest (refer to actionGoTo:290,FigureactionGoTo:290, 13-3), the sendHelpResponse:method on Bonjour is invoked. actionGoTo:291,ListingactionGoTo:291, 13-11 details the implementation of sendHelpResponse:.actionGoTo:291,LISTINGactionGoTo:291, 13-11: sendHelpResponse: Implementation (/Apps/Associate/associate-help/associate-help/Bonjour.m)- (void)sendHelpResponse:(HelpResponse*)response { if (sendData == nil) { sendData = [[NSMutableData alloc] read more..

  • Page - 292

    been transmitted, the application cleans the queue and removes the outputStream from the run loop.It is rescheduled when there is additional data to transmit.actionGoTo:291,LISTINGactionGoTo:291, 13-12: NSStreamEventHasSpaceAvailable Logic(/Apps/Associate/associate-help/associate-help/Bonjour.m)- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { ... case NSStreamEventHasSpaceAvailable: { if (aStream == outputStream) { read more..

  • Page - 293

    better experience to disable the feature all together.actionGoTo:293,FigureactionGoTo:293, 13-4actionGoTo:293, shows the shop view, and actionGoTo:293,FigureactionGoTo:293, 13-5 shows the help view in which a single employeeis currently available. As mentioned with the employee app, all presentation tier code can be found inthe Chapter 13 downloads folder. However, as with the employee application, all Bonjour browse,connection, and communication functionality has been abstracted from the read more..

  • Page - 294

    @interface declaration.actionGoTo:293,LISTINGactionGoTo:293, 13-13: BonjourBrowser Interface Definition (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.h)#import "HelpRequest.h"#import "HelpResponse.h" #define kNotificationResultSet @"NotificationObject" #define kBrowseStartNotification @"BonjourBrowseStartNotification"#define kBrowseErrorNotification @"BonjourBrowseErrorNotification"#define kBrowseSuccessNotification read more..

  • Page - 295

    browser instance variable and notify the front end so that any related status indicators can beupdated.actionGoTo:294,LISTINGactionGoTo:294, 13-15: netServiceBrowser:didNotSearch: andnetServiceBrowserDidStopSearch: Implementations (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.m)- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didNotSearch:(NSDictionary *)errorDict { // alert the user and stop the browser [Utils read more..

  • Page - 296

    If there is an issue resolving the service, the netService:didNotResolve: delegate method iscalled, which posts a notification to the front end at which point the customer is informed. As theservice is resolved, the netServiceDidResolveAddress: delegate method is called. actionGoTo:297,ListingactionGoTo:297, actionGoTo:297,13-17covers the implementation of the netService:didNotResolve: andnetServiceDidResolveAddress: delegate methods. As mentioned in the “Resolving a Service”section, read more..

  • Page - 297

    actionGoTo:296,LISTINGactionGoTo:296, 13-17: netService:didNotResolve: and netServiceDidResolveAddress:Implementations (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.m)- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict { [Utils postNotifification:kConnectErrorNotification];} - (void)netServiceDidResolveAddress:(NSNetService *)sender { NSInputStream *tmpIS; NSOutputStream *tmpOS; BOOL error = NO; // this application requires read more..

  • Page - 298

    actionGoTo:297,LISTINGactionGoTo:297, 13-18: sendHelpRequest: Implementation (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.m)- (void)sendHelpRequest:(HelpRequest*)request { if (sendData == nil) { sendData = [[NSMutableData alloc] init]; } // convert the request to NSData (using NSKeyedArchiver/NSCoding) NSData *requestData = [NSKeyedArchiver archivedDataWithRootObject:request]; [sendData appendData:requestData]; read more..

  • Page - 299

    actionGoTo:298,LISTINGactionGoTo:298, 13-19: stream:handleEvent: NSStreamEventHasSpaceAvailableImplementation (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.m)- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventHasSpaceAvailable: { if (aStream == outputStream) { if ([sendData length] > 0) { uint8_t *readBytes = (uint8_t *)[sendData read more..

  • Page - 300

    actionGoTo:299,LISTINGactionGoTo:299, 13-20: stream:handleEvent: NSStreamEventHasBytesAvailableImplementation (/Apps/Consumer/consumer-help/consumer-help/BonjourBrowser.m)- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { ... case NSStreamEventHasBytesAvailable: if (aStream == inputStream) { if (receiveData == nil) { receiveData = [[NSMutableData alloc] init]; } read more..

  • Page - 301

    earlier, and a byte counter is updated to reflect the number of bytes actually read. If the inputStreamdoesn’t have any more bytes available, the application attempts to create a HelpResponse objectusing NSKeyedUnarchiver and then notifies the front end and passes the response. If there areadditional bytes to be read, the delegate continues to receive theNSStreamEventHasBytesAvailable event until the buffer has been exhausted.When the employee response is received, it is presented to the read more..

  • Page - 302

    automation tools.The employee and customer applications provide a good framework to integrate Bonjour into yourapplications. However, there are other networking tools available that you should review to ensureBonjour is best for your needs. One option is Game Kit, which is covered in Chapter 12. Chapter 8covers low-level network programming functionality that may also be something to consider forcertain requirements.This is the final chapter in this book. All three of us thank you for buying the read more..

  • Page - 303

    read more..

  • Page - 304

    Professional iOS Network Programming: Connecting the Enterprise to the iPhone® and iPad®Published byJohn Wiley & Sons, Inc.10475 Crosspoint BoulevardIndianapolis, IN 46256actionURI(http://www.wiley.com):www.wiley.comCopyright © 2012 by John Wiley & Sons, Inc., Indianapolis, IndianaPublished simultaneously in CanadaISBN: 978-1-118-36240-2ISBN: 978-1-118-38223-3 (ebk)ISBN: 978-1-118-41716-4 (ebk)ISBN: 978-1-118-53385-7 (ebk)No part of this publication may be reproduced, stored in a read more..

  • Page - 305

    demand. If this book refers to media such as a CD or DVD that is not included in the version youpurchased, you may download this material at actionURI(http://booksupport.wiley.com):http://booksupport.wiley.com For more informationabout Wiley products, visitactionURI(http://www.wiley.com): www.wiley.com.Library of Congress Control Number: 2012948655Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, andrelated trade dress are trademarks or registered trademarks read more..

  • Page - 306

    ABOUT THE AUTHORS JACK COX is a software developer, a systems architect, and the director at CapTechVentures, Inc., where he is responsible for the firm’s mobile software practice. He has 30 years ofexperience in developing software for businesses of all sizes. He has been involved in three startups,holds multiple patents, and frequently presents to professional groups. He has a degree in computerscience from Taylor University in Upland, Indiana. Jack lives in Richmond, Virginia, with his read more..

  • Page - 307

    ABOUT THE TECHNICAL EDITOR JONATHAN TANG is a senior developer specializing in mobile applications atCapTech Consulting. He has more than 10 years of development experience, including programmingtouchscreen interfaces, medical devices, and iOS mobile applications. Prior to CapTech, Johnworked as the primary software engineer at a startup company that specializes in medical robotics.John received a bachelor of science in biomedical engineering from Johns Hopkins University and amaster of science read more..

  • Page - 308

    CREDITSEXECUTIVE EDITORCarol LongPROJECT EDITORVictoria SwiderTECHNICAL EDITORJonathan TangPRODUCTION EDITORKathleen WisorCOPY EDITORSan Dee PhillipsEDITORIAL MANAGERMary Beth WakefieldFREELANCER EDITORIAL MANAGERRosemarie GrahamASSOCIATE DIRECTOR OF MARKETINGDavid MayhewMARKETING MANAGERAshley ZurcherBUSINESS MANAGERAmy KniesPRODUCTION MANAGERTim TateVICE PRESIDENT AND EXECUTIVE GROUP PUBLISHERRichard SwadleyVICE PRESIDENT AND EXECUTIVE PUBLISHERNeil EddeASSOCIATE PUBLISHERJim Minatel read more..

  • Page - 309

    PROJECT COORDINATOR, COVERKatie CrockerPROOFREADERNancy CarrascoINDEXERJohnna VanHoose DinseCOVER DESIGNERRyan SneedCOVER IMAGE© pagadesign/iStockPhoto read more..

  • Page - 310

    ACKNOWLEDGMENTSI WANT TO THANK the principles, management, and coworkers at CapTech Ventures, especiallyVinnie Schoenfelder, for encouraging and supporting our effort to write this book. I want to extendspecial thanks to Nathan Jones and John Szumski for being willing and faithful in this adventure tocomplete our first book. On behalf of Nathan, John, and myself, I want to thank Carol Long andVictoria Swider at Wiley for tolerating and answering all our newbie questions.To my wife and family, I read more..

  • Page - 311

    INTRODUCTIONAS IPHONES AND IPADS BECOME A UBIQUITOUS part of your personal and professionallife, you become more and more dependent on their capability to seamlessly and flawlessly interactwith hosts across the Internet or with other phones across the room. This book provides a compilationof methods to accomplish this level of connectivity with examples and best practices for each of thesemethods.The release of the iPhone SDK, now known as iOS, started a stampede of experienced and read more..

  • Page - 312

    WHO THIS BOOK IS FOREnterprise iOS developers, including developers working within a corporation or organization, willfind this book to be a valuable resource that provides working examples and guidelines fornetworking iOS apps with enterprise servers. The networking techniques described in this bookbelong in all developers’ arsenals when writing iOS apps.Beginning iOS developers transitioning from other platforms to iOS can gain a complete overviewof the capabilities of iOS from this book. In read more..

  • Page - 313

    WHAT THIS BOOK COVERSThis book focuses on network programming of apps running on Apple’s operating system for theiPhone, iPad, and iPod, called iOS. The topics covered include:Performing HTTP requests between client device and serverManaging data payloads between client device and serverHandling errors in HTTP requestsSecuring network communicationsImproving the performance of network communicationsPerforming socket level communicationsImplementing push notificationsCommunicating between apps read more..

  • Page - 314

    HOW THIS BOOK IS STRUCTUREDThe book is divided into four sections each covering a broad topic in the realm of iOS networkprogramming. The sections progress from high-level discussions of mobile application architecturedown to specific protocols and solutions for app-to-app communication, while providing in-depthcoverage of the most popular methods of communicating between apps and servers.Part I: Understanding iOS and Enterprise NetworkingThis is where most readers should start. This first read more..

  • Page - 315

    The fourth section contains three chapters describing how to communicate between apps on thesame device or other devices.Chapter 11: Inter-App Communication — This chapter enumerates and describes ways tocommunicate between apps on the same device.Chapter 12: Device-to-Device Communication with Game Kit — Here you look at usingGame Kit for communicating between devices for nongaming purposes which, for once, currentlyhas more features than its .NET cousin.Chapter 13: Ad-Hoc Networking with read more..

  • Page - 316

    manually or to use the source code files that accompany the book. All the source code used in thisbook is available for download at actionURI(http://www.wrox.com):http://www.wrox.com. When at the site, simply locate the book’stitle (either by using the Search box or by using one of the title lists) and click the Download Codelink on the book’s detail page to obtain all the source code for the book.NOTE Because many books have similar titles, you may find it easiest to search byISBN; this read more..

  • Page - 317

    industry experts, and your fellow readers are present on these forums.At actionURI(http://p2p.wrox.com):http://p2p.wrox.com you can find a number of different forums to help you not only as you readthis book, but also as you develop your own applications. To join the forums, just follow these steps:1. Go to actionURI(http://p2p.wrox.com):p2p.wrox.com and click the Register link.2. Read the terms of use and click Agree.3. Complete the required information to join as well as any optional read more..

  • Page - 318

    Visit actionURI(http://www.safaribooksonline.com/wrox49):www.safaribooksonline.com/wrox49actionURI(http://www.safaribooksonline.com/wrox49): to get started read more..

  • Page - 319

    read more..

  • Page - 320

    Related Wrox Books Beginning iOS Game DevelopmentISBN: 978-1-118-10732-4No matter your experience level with iOS programming, this beginner’s guide covers the technologiesyou need to know to get started creating fun iOS games. Learning how to create games should benearly as much fun as playing them, so this book offers a complete, playable game in nearly everychapter. Each game is created in simple, easy-to-understand parts, building to a full game bychapter’s end. Professional iPhone and read more..

    You may also read

Essential Mathematics for Games and Interactive ApplicationsEssential Mathematics for Games and Interactive ApplicationsRead Book
Programming in Objective-C 2.0Programming in Objective-C 2.0Read Book
iOS 7 Programming Pushing the LimitsiOS 7 Programming Pushing the LimitsRead Book
Cocoa Programming for Mac OS X, 3rd EditionCocoa Programming for Mac OS X, 3rd EditionRead Book

Write Your Review