Bonjour, iCloud

  • 2,558 views
Uploaded on

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
2,558
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
44
Comments
1
Likes
4

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. iOS Networking: Bonjour, iCloud! Chris Adamson • @invalidname CodeMash 2012Monday, January 16, 12
  • 2. What we’ll cover • Obvious networking APIs • iCloud, Bonjour, GameKit, CFNetwork • Not-so-obvious networking APIs • Foundation, media APIs, System ConfigurationMonday, January 16, 12
  • 3. The first thing your network app should do?Monday, January 16, 12
  • 4. Monday, January 16, 12
  • 5. Do I have network access at all?Monday, January 16, 12
  • 6. 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
  • 7. Monday, January 16, 12
  • 8. 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
  • 9. 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
  • 10. Reachability callbacks • Networks come and go; your app should handle this • SCNetworkReachabilitySetCallback() MyNetworkReachabilityCallBack( SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info );Monday, January 16, 12
  • 11. Monday, January 16, 12
  • 12. http://mattgemmell.com/2011/07/25/network-link- conditioner-in-lion/Monday, January 16, 12
  • 13. Assuming the network is working…Monday, January 16, 12
  • 14. Say hello to iCloudMonday, January 16, 12
  • 15. The iCloud API • • • • •Monday, January 16, 12
  • 16. 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
  • 17. iCloud set-up Enable iCloud for AppID in provisioning portal Enable entitlements in .xcodeproj (also creates .entitlements file)Monday, January 16, 12
  • 18. Browsing in iCloud • Compose an NSMetadataQuery (from Spotlight API) • Include NSMetadataQueryUbiquitousDocu mentsScope in search scopes • Start search (asynchronous!)Monday, January 16, 12
  • 19. -(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
  • 20. // 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
  • 21. - (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
  • 22. Monday, January 16, 12
  • 23. But what about document contents?Monday, January 16, 12
  • 24. iCloud documents • Subclass UIDocument (new in iOS 5) • Override contentsForType: and loadFromContents:ofType:error:Monday, January 16, 12
  • 25. 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
  • 26. 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
  • 27. 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
  • 28. Saving changes [note updateChangeCount:UIDocumentChangeDone]; [note closeWithCompletionHandler:^(BOOL success) { NSLog (@"document close was %@", success ? @"successful" : @"not successful"); }];Monday, January 16, 12
  • 29. 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
  • 30. Demo: CloudNotesMonday, January 16, 12
  • 31. But what if my data isn’t in iCloud?Monday, January 16, 12
  • 32. Networking in Foundation • NSURL • Classes that load from URLs • Property lists • URL Loading SystemMonday, January 16, 12
  • 33. initWithContentsOfURL: • Supported by NSString, NSData • Also NSArray and NSDictionary if contents are a property list • These calls block!Monday, January 16, 12
  • 34. 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
  • 35. But I want to host a server on my iPhone!Monday, January 16, 12
  • 36. 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
  • 37. 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
  • 38. Network DiscoveryMonday, January 16, 12
  • 39. 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
  • 40. 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
  • 41. 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
  • 42. GameKit • Simplified Bonjour over Bluetooth or WiFi • GKPeerPickerController UI for peer discovery • APIs allow client-server or peer-to-peerMonday, January 16, 12
  • 43. GKSession • All about the delegate callbacks: • didReceiveConnectionRequestFromPeer: • peer:didChangeState: • receiveData:fromPeer:inSession:Monday, January 16, 12
  • 44. Demo (if we are really, really lucky)Monday, January 16, 12
  • 45. GameKit voice chat • Set up through Game Center • Create with -[GKMatch voiceChatWithName:] • Does anyone use this?Monday, January 16, 12
  • 46. Speaking of media…Monday, January 16, 12
  • 47. 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
  • 48. 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
  • 49. 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
  • 50. 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
  • 51. Demo: HLS bandwidthMonday, January 16, 12
  • 52. TakeawaysMonday, January 16, 12
  • 53. 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
  • 54. End of line.Monday, January 16, 12