Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CocoaHeads BNE July 2014

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

CocoaHeads BNE July 2014

"The WWDC 2014 Edition", including latest news, Gabriel Huber's presentation on Multipeer Connectivity & Peter Ryder's presentation on JavaScriptCore.

Avatar for Ben Stovold

Ben Stovold

June 03, 2014
Tweet

More Decks by Ben Stovold

Other Decks in Technology

Transcript

  1. +

  2. Service'Type • used&for&discovery:&peers&connect&via&common& service&name • name&must&conform&to&the&format&of&a&Bonjour& service&type: • Must&be&1–15&characters&long •

    Can&contain&only&ASCII&lowercase&leCers,& numbers,&and&hyphens NSString * const kMyServiceTypeName = @"my-service-type";
  3. Mul$peer(Session • needed%in%order%to%make%connec.ons • send/receive%data • delegate%is%no.fied%of%peer%state%changes%(not% connected,%connec.ng,%connected) self.localSession =

    [[MCSession alloc] initWithPeer:self.myPeerID securityIdentity:nil encryptionPreference:MCEncryptionNone]; self.localSession.delegate = self;
  4. MCNearbyServiceAdver/serDelegate - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL

    accept, MCSession *session))invitationHandler • Use%the%peerID%and%info%parameters%to%present%a% suitable%UI • (Will%describe%how%to%accept%shortly)
  5. Invi%ng'a'peer'to'a'session MCPeerID *peerToInvite = ...; NSDictionary *contextDictionary = @{@"player.name" :

    self.myPlayerName}; NSData *context = [NSKeyedArchiver archivedDataWithRootObject:contextDictionary]; [self.browser invitePeer:peerToInvite toSession:self.localSession withContext:context timeout:30];
  6. Accep%ng(an(invita%on // advertiser:didReceiveInvitationFromPeer:withContext:invitationHandler: // extract info NSDictionary *contextDictionary = (NSDictionary*)

    [NSKeyedUnarchiver unarchiveObjectWithData:context]; NSString *otherPlayerName = contextDictionary[@"player.name"]; // present UI UIActionSheet *actionSheet = [UIActionSheet SH_actionSheetWithTitle:otherPlayerName]; [actionSheet SH_addButtonWithTitle:@"Play Game" withBlock:^(NSInteger theButtonIndex) { invitationHandler(YES, [RTSSessionContainer sharedInstance].localSession); }]; [actionSheet SH_addButtonCancelWithTitle:@"Reject" withBlock:^(NSInteger theButtonIndex) { invitationHandler(NO, nil); }]; [actionSheet showInView:self.view];
  7. Second'connec(on • C#discovers#A,#sends#invita1on • A#accepts • C#is#now#connected#to#A • C"is"also"connected"to"B •

    Any#of#the#three#devices#can#send#messages#to#any# other#device#in#the#peer9to9peer#network
  8. Sending'Data • via%MCSession%instance • send%arbitrary%data%to%one%or%more%peers%2%NSData • send%resource%/%stream%to%a%single%peer - (BOOL)sendData:toPeers:withMode:error: -

    (NSProgress *)sendResourceAtURL:withName:toPeer:withCompletionHandler: - (NSOutputStream *)startStreamWithName:toPeer:error:
  9. MCSessionDelegate!to!receive! data // receive NSData - (void)session:didReceiveData:fromPeer: // data available

    at temp URL when didFinishReceiving - (void)session:didStartReceivingResourceWithName:fromPeer:withProgress: - (void)session:didFinishReceivingResourceWithName:atURL:withError: // provided an NSInputStream to read from - (void)session:didReceiveStream:withName:fromPeer:
  10. Browsing)&)Mul.tasking - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:)

    name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [self startBrowsing]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self stopBrowsing]; }
  11. Session'&'Mul,tasking - (void)applicationDidEnterBackground:(NSNotification *)notification { self.backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

    [self teardownSession]; [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId]; self.backgroundTaskId= UIBackgroundTaskInvalid; }]; } - (void)applicationWillEnterForeground:(NSNotification *)notification { // cancel the background task if (self.backgroundTaskId != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId]; self.backgroundTaskId = UIBackgroundTaskInvalid; } } - (void)applicationWillTerminate:(NSNotification *)notification { [self teardownSession]; }
  12. #import <JavaScriptCore/JavaScriptCore.h> • Objective-C (ARC) -> JavaScript (GC) • JavaScript

    -> Objective-C • Objective-C interface to procedural JavaScriptCore API • Real men don’t need documentation…header files & WWDC session best resources • Is the same as the WebKit JS engine (-Nitro/JIT)
  13. • Most interaction via JSContext (hosted by JSVirtualMachine) via JSValue

    • Thread-safe via locking at JSVirtualMachine granularity • An app can have multiple JSContext in a single JSVirtualMachine, and multiple JSVirtualMachine
  14. • Automatic conversion of key foundation types
 NSString=>JS string, NSNumber=>JS

    number, NSDate=>JS Date etc… • Block=>JS function (avoid capturing JSContext or JSValue in block) • Custom classes via JSExport protocol
  15. Caveats • Where is the documentation? WWDC ’14? • Aren’t

    aware of how to connect WebKit debugger • Pay special attention to retain cycles (JSManagedValue can be used to break cycle) • for…in doesn’t work on NSArray (JS limitation of Prototype?) • Occasionally lose the JSExports of an object which a JSExport property of another object (JSC GC bug?)