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

CocoaHeads BNE July 2014

CocoaHeads BNE July 2014

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

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?)