• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Bonjour, iCloud
 

Bonjour, iCloud

on

  • 2,986 views

Mobile devices are so useful because they can get on the net with their built-in wi-fi or cellular data radios. But how does this work? In iOS, we have a slew of networking APIs, each appropriate in ...

Mobile devices are so useful because they can get on the net with their built-in wi-fi or cellular data radios. But how does this work? In iOS, we have a slew of networking APIs, each appropriate in different situations. From decades-old BSD sockets to the new-in-iOS-5 iCloud, there are a wide range of networking calls available to your app, and an equally wide range of semantics in how to use them. In this talk, we'll start with high-level abstractions like iCloud and other objects that can either load from or save to a URL, then progress down through the stack, grabbing arbitrary content from URLs, self-networking with Bonjour and Game Kit, and finally accessing the socket layer with CFNetwork and BSD sockets.

iCloud sample code at: http://dl.dropbox.com/u/12216224/conferences/codemash12/bonjour-icloud/CloudNotes.zip

Statistics

Views

Total Views
2,986
Views on SlideShare
2,986
Embed Views
0

Actions

Likes
4
Downloads
41
Comments
1

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Bonjour, iCloud Bonjour, iCloud Presentation Transcript

    • iOS Networking: Bonjour, iCloud! Chris Adamson • @invalidname CodeMash 2012Monday, January 16, 12
    • What we’ll cover • Obvious networking APIs • iCloud, Bonjour, GameKit, CFNetwork • Not-so-obvious networking APIs • Foundation, media APIs, System ConfigurationMonday, January 16, 12
    • The first thing your network app should do?Monday, January 16, 12
    • Monday, January 16, 12
    • Do I have network access at all?Monday, January 16, 12
    • Reachability • Defined in SystemConfiguration.framework • C-based API, Obj-C wrapper available as sample code from Apple • Your network-based app will be rejected if it turtles without network accessMonday, January 16, 12
    • Monday, January 16, 12
    • Reachability • Create a SCNetworkReachabilityRef from host name (as a C string) or address (as a sockaddr) • Get network info with SCNetworkReachabilityGetFlags()Monday, January 16, 12
    • Reachability Flags enum { kSCNetworkReachabilityFlagsTransientConnection = 1<<0, kSCNetworkReachabilityFlagsReachable = 1<<1, kSCNetworkReachabilityFlagsConnectionRequired = 1<<2, kSCNetworkReachabilityFlagsConnectionOnTraffic = 1<<3, kSCNetworkReachabilityFlagsInterventionRequired = 1<<4, kSCNetworkReachabilityFlagsConnectionOnDemand = 1<<5, kSCNetworkReachabilityFlagsIsLocalAddress = 1<<16, kSCNetworkReachabilityFlagsIsDirect = 1<<17, kSCNetworkReachabilityFlagsIsWWAN = 1<<18, kSCNetworkReachabilityFlagsConnectionAutomatic = kSCNetworkReachabilityFlagsConnectionOnTraffic }; typedef uint32_t SCNetworkReachabilityFlags;Monday, January 16, 12
    • Reachability callbacks • Networks come and go; your app should handle this • SCNetworkReachabilitySetCallback() MyNetworkReachabilityCallBack( SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info );Monday, January 16, 12
    • Monday, January 16, 12
    • http://mattgemmell.com/2011/07/25/network-link- conditioner-in-lion/Monday, January 16, 12
    • Assuming the network is working…Monday, January 16, 12
    • Say hello to iCloudMonday, January 16, 12
    • The iCloud API • • • • •Monday, January 16, 12
    • iCloud: UIDocument • iCloud does not have its own API, per se • Special case of saving documents • Same code to save to local or cloud documents directory by URL • There are also iCloud APIs for simple key-value storage, and Core Data persistent storesMonday, January 16, 12
    • iCloud set-up Enable iCloud for AppID in provisioning portal Enable entitlements in .xcodeproj (also creates .entitlements file)Monday, January 16, 12
    • Browsing in iCloud • Compose an NSMetadataQuery (from Spotlight API) • Include NSMetadataQueryUbiquitousDocu mentsScope in search scopes • Start search (asynchronous!)Monday, January 16, 12
    • -(void) refreshNotes { NSLog (@"refreshNotes"); [self.noteDictsArray removeAllObjects]; self.currentQuery = [[NSMetadataQuery alloc] init]; // register for notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:self.currentQuery]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(initalGatherComplete:) name:NSMetadataQueryDidFinishGatheringNotification object:self.currentQuery];Monday, January 16, 12
    • // Configure the search predicate NSPredicate *searchPredicate; searchPredicate=[NSPredicate predicateWithFormat:@"%K LIKE %@", NSMetadataItemFSNameKey, @"*.cloudnote"]; [self.currentQuery setPredicate:searchPredicate]; // Set the search scope to only search iCloud NSArray *searchScopes; searchScopes=[NSArray arrayWithObjects: NSMetadataQueryUbiquitousDocumentsScope,nil]; [self.currentQuery setSearchScopes:searchScopes]; // Start the query! [self.currentQuery startQuery];Monday, January 16, 12
    • - (void)initalGatherComplete:sender; { // Stop the query, the single pass is completed. [self.currentQuery stopQuery]; for (int i=0; i < [self.currentQuery resultCount]; i++) { NSMetadataItem *noteMetadata = [self.currentQuery resultAtIndex:i]; NSString *noteName = [noteMetadata valueForAttribute:NSMetadataItemDisplayNameKey]; NSURL *noteURL = [noteMetadata valueForAttribute:NSMetadataItemURLKey]; NSDate *noteModifiedDate = [noteMetadata valueForAttribute:NSMetadataItemFSContentChangeDateKey]; NSLog(@"%@: %@", noteName, noteURL); NSDictionary *noteDict = [NSDictionary dictionaryWithObjectsAndKeys: noteName, NSMetadataItemDisplayNameKey, noteURL, NSMetadataItemURLKey, noteModifiedDate, NSMetadataItemFSContentChangeDateKey, nil]; [self.noteDictsArray addObject:noteDict]; }Monday, January 16, 12
    • Monday, January 16, 12
    • But what about document contents?Monday, January 16, 12
    • iCloud documents • Subclass UIDocument (new in iOS 5) • Override contentsForType: and loadFromContents:ofType:error:Monday, January 16, 12
    • UIDocument overrides - (id)contentsForType:(NSString *)typeName error:(NSError **)outError { NSLog (@"archiving: %@", self.noteDict); return [NSKeyedArchiver archivedDataWithRootObject:self.noteDict]; } - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { BOOL success = NO; if([contents isKindOfClass:[NSData class]] && [contents length] > 0) { NSData *data = (NSData *)contents; self.noteDict = [NSMutableDictionary dictionaryWithDictionary: [NSKeyedUnarchiver unarchiveObjectWithData:data]]; success = YES; } NSLog (@"noteDict: %@", self.noteDict); return success; }Monday, January 16, 12
    • Start a new document in iCloud NSFileManager *fm = [NSFileManager defaultManager]; NSURL *newDocumentURL = [fm URLForUbiquityContainerIdentifier:nil]; newDocumentURL = [newDocumentURL URLByAppendingPathComponent:@"Documents" isDirectory:YES]; // fileName calculation omitted newDocumentURL = [newDocumentURL URLByAppendingPathComponent:fileName]; CDMNoteDocument *doc = [[CDMNoteDocument alloc] initWithFileURL:newDocumentURL]; // Save the new document to disk. [doc saveToURL:newDocumentURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { NSLog (@"new document %@ saved", success ? @"was" : @"was not"); }];Monday, January 16, 12
    • Open an existing iCloud document NSURL *noteURL = (NSURL*) [noteDict valueForKey:NSMetadataItemURLKey]; CDMNoteDocument *doc = [[CDMNoteDocument alloc] initWithFileURL:noteURL]; [doc openWithCompletionHandler:^(BOOL success){ NSLog (@"opening doc at %@ %@", doc.fileURL, success ? @"succeeded" : @"failed"); }Monday, January 16, 12
    • Saving changes [note updateChangeCount:UIDocumentChangeDone]; [note closeWithCompletionHandler:^(BOOL success) { NSLog (@"document close was %@", success ? @"successful" : @"not successful"); }];Monday, January 16, 12
    • Detecting iCloud conflicts • Register for NSNotificationCenter for UIDocumentStateChangedNotification • Inspect the documentState property for the value UIDocumentStateInConflict • Use NSFileVersion method unresolvedConflictVersionsOfItemAtURL to inspect the versionsMonday, January 16, 12
    • Demo: CloudNotesMonday, January 16, 12
    • But what if my data isn’t in iCloud?Monday, January 16, 12
    • Networking in Foundation • NSURL • Classes that load from URLs • Property lists • URL Loading SystemMonday, January 16, 12
    • initWithContentsOfURL: • Supported by NSString, NSData • Also NSArray and NSDictionary if contents are a property list • These calls block!Monday, January 16, 12
    • URL Loading System • NSURL + NSURLRequest + NSURLConnection + delegate callbacks • connection:didReceiveResponse:, connection:didReceiveData:, etc. • Fairly deep HTTP support (incl. authentication) • Not an arbitrary socket networking APIMonday, January 16, 12
    • But I want to host a server on my iPhone!Monday, January 16, 12
    • CFNetwork • C-based API, abstractions over network protocols and BSD sockets • Deep support for HTTP, HTTPS, FTP, DNS • Built to work asynchronously in RunLoop- based applications (incl. Cocoa Touch)Monday, January 16, 12
    • If you must run a server • Create CFSocketRef with CFSocketCreate() [or similar] setting callbackTypes to kCFSocketAcceptCallback • Callback receives a CFSocketNativeHandle • From this, CFStreamCreatePairWithSocket() to get CFReadStreamRef and CFWriteStreamRefMonday, January 16, 12
    • Network DiscoveryMonday, January 16, 12
    • Bonjour! • Protocol for address self-assignment and service discovery • Published ZEROCONF standard • Open-source implementations for Mac, Windows, Linux, Java • APIs: NSNetService and CFNetServiceRefMonday, January 16, 12
    • Searching for Bonjour http servers -(void) startSearchingForWebServers { ! NSNetServiceBrowser bonjourBrowser = [[NSNetServiceBrowser alloc] init]; ! [bonjourBrowser setDelegate: self]; ! [bonjourBrowser searchForServicesOfType:@"_http._tcp" inDomain:@""]; } - (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didFindService:(NSNetService *)netService moreComing:(BOOL)moreServicesComing { ! [discoveredWebServices addObject: netService]; ! [tableView reloadData]; ! if (! moreServicesComing) ! ! [activityIndicator stopAnimating]; }Monday, January 16, 12
    • Got a service,now what? • Bonjour provides the discovery, not the service itself • The NSNetService object includes addresses, host name, and port • Client connects to the host via NSURLConnection, CFNetwork, etc.Monday, January 16, 12
    • GameKit • Simplified Bonjour over Bluetooth or WiFi • GKPeerPickerController UI for peer discovery • APIs allow client-server or peer-to-peerMonday, January 16, 12
    • GKSession • All about the delegate callbacks: • didReceiveConnectionRequestFromPeer: • peer:didChangeState: • receiveData:fromPeer:inSession:Monday, January 16, 12
    • Demo (if we are really, really lucky)Monday, January 16, 12
    • GameKit voice chat • Set up through Game Center • Create with -[GKMatch voiceChatWithName:] • Does anyone use this?Monday, January 16, 12
    • Speaking of media…Monday, January 16, 12
    • HTTP Live Streaming • Firewall-friendly audio/video streaming for iOS and Mac OS X 10.6+ (replaces RTP/ RTSP) • Required for any app that streams more than 10MB over mobile network • Client support: AVPlayer, MPMoviePlayerControllerMonday, January 16, 12
    • HLS: How It Works • Segmenting server splits source media into separate files (usually .m4a for audio- only, .ts for A/V), usually 10 seconds each, and creates an .m3u8 playlist file • Playlist may point to bandwidth-appropriate playlists • Clients continually reload playlist, fetch the segments, queue them upMonday, January 16, 12
    • Sample playlist #EXTM3U #EXT-X-TARGETDURATION:8 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:8, 0640/0640_090110_120505_0.ts #EXTINF:8, 0640/0640_090110_120505_1.ts #EXTINF:8, 0640/0640_090110_120505_2.ts #EXTINF:8, 0640/0640_090110_120505_3.ts #EXTINF:8, 0640/0640_090110_120505_4.tsMonday, January 16, 12
    • Bandwidth-delimited playlist #EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000 http://example.com/low.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000 http://example.com/mid.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000 http://example.com/hi.m3u8Monday, January 16, 12
    • Demo: HLS bandwidthMonday, January 16, 12
    • TakeawaysMonday, January 16, 12
    • iOS Priorities • Asynchronicity — don’t block the UI • Many network APIs are difficult or impossible to block on • Domain-appropriate abstractions • iCloud, GameKit, HLS • You don’t need to know the difference between cellular and wifiMonday, January 16, 12
    • End of line.Monday, January 16, 12