SlideShare a Scribd company logo
Synchronizing 
without internet 
Codemotion 2014, Madrid
Who am I? 
Jorge Maroto 
(@patoroco) 
http://maroto.me 
· iOS Developer 
@ticketeaeng 
· Playing with iOS since 
2010 
· Fanboy
Synchronize
Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)
¿Internet?
LAN (wired / wi-fi)
What about iOS?
Changelog 
· iOS 3: Game Kit 
· iOS 4: Game Center 
· iOS 5: Core Bluetooth 
· iOS 6: Core Bluetooth advertising 
· iOS 7: Multipeer Connectivity & 
iBeacons 
· iOS 8: Handoff
Changelog 
· iOS 3: Game Kit 
· iOS 4: Game Center 
· iOS 5: Core Bluetooth 
· iOS 6: Core Bluetooth advertising 
· iOS 7: Multipeer Connectivity & 
iBeacons 
· iOS 8: Handoff
Multipeer 
Connectivity
Multipeer connectivity 
· Appears in iOS7. 
· Ability to connect to a mesh of peers. 
· Able to connect to peers over WiFi, ad-hoc 
wireless, and Bluetooth. 
· Doesn't require server infraestructure. 
· Peers must be 'nearby'.
Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)
MultipeerConnectivity.framework 
Bonjour | CFNetwork
Two phases 
· Discovery 
· Session
Classes 
#import <MultipeerConnectivity/MultipeerConnectivity.h> 
Session info 
Discovery 
Advertisement
Session info 
· MCPeerId 
· MCSession
MCPeerId 
MCPeerID *peerId = 
[[MCPeerID alloc] initWithDisplayName:self.deviceName];
MCSession 
MCSession *session = 
[[MCSession alloc] initWithPeer:self.peerId]; 
session.delegate = self;
<MCSessionDelegate> 
- (void)session:(MCSession *)session 
peer:(MCPeerID *)peerID 
didChangeState:(MCSessionState)state 
{ 
switch (state): 
{ 
case MCSessionStateConnected: 
... 
case MCSessionStateConnecting: 
... 
case MCSessionStateNotConnected: 
... 
} 
}
<MCSessionDelegate> 
// DATA 
- (void)session:(MCSession *)session 
didReceiveData:(NSData *)data 
fromPeer:(MCPeerID *)peerID {} 
// RESOURCES 
- (void)session:(MCSession *)session 
didStartReceivingResourceWithName:(NSString *)resourceName 
fromPeer:(MCPeerID *)peerID 
withProgress:(NSProgress *)progress {} 
- (void)session:(MCSession *)session 
didFinishReceivingResourceWithName:(NSString *)resourceName 
fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL 
withError:(NSError *)error{} 
// STREAMS 
- (void)session:(MCSession *)session 
didReceiveStream:(NSInputStream *)stream 
withName:(NSString *)streamName 
fromPeer:(MCPeerID *)peerID{}
Discovery · MCBrowserViewController 
· MCNearbyServiceBrowser
MCBrowserViewController 
NSString * const serviceIdentifier = @"codemotion-demo"; 
MCBrowserViewController *browser = 
[[MCBrowserViewController alloc] initWithServiceType:serviceIdentifier 
session:self.appdelegate.session]; 
browser.delegate = self; 
[self presentViewController:browser animated:YES completion:nil];
Synchronizing without internet - Multipeer Connectivity (iOS)
<MCBrowserViewControllerDelegate> 
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)b {} 
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)b {}
Advertisement 
· MCAdvertiserAssistant 
· MCNearbyServicesAdvertiser
MCAdvertiserAssistant 
NSString * const serviceIdentifier = @"codemotion-demo"; 
MCAdvertiserAssistant *advertiser = 
[[MCAdvertiserAssistant alloc] 
initWithServiceType:self.serviceIdentifier 
discoveryInfo:nil session:session]; 
[advertiser start];
Session phase
Sending data 
· NSData to an array of peers. 
· NSURL resource to a peer. 
· NSStream to a peer.
Send NSData to an array of peers 
- (BOOL)sendData:(NSData *)data 
toPeers:(NSArray *)peerIDs 
withMode:(MCSessionSendDataMode)mode 
error:(NSError **)error; 
Modes 
· MCSessionSendDataReliable 
· MCSessionSendDataUnreliable
DEMO Hello world in MC
Video
Synchronizing without internet - Multipeer Connectivity (iOS)
Send resource to a peer 
- (NSProgress *)sendResourceAtURL:(NSURL *)resourceURL 
withName:(NSString *)resourceName 
toPeer:(MCPeerID *)peerID 
withCompletionHandler:(void(^)(NSError *error))completionHandler;
Example Share images from photo 
library
@property (weak, nonatomic) IBOutlet UIImageView *picture;
- (IBAction)choosePhoto:(UIButton *)sender 
{ 
UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 
picker.delegate = self; 
picker.allowsEditing = NO; 
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 
picker.mediaTypes = @[(NSString *)kUTTypeImage]; 
[self presentViewController:picker animated:YES completion:nil]; 
}
<UIImagePickerDelegate> 
#pragma mark - UIImagePickerDelegate 
- (void)imagePickerController:(UIImagePickerController *)picker 
didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
UIImage *selectedImage = info[UIImagePickerControllerOriginalImage]; 
NSData *jpegImg = UIImageJPEGRepresentation(selectedImage, 0.5); 
NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingString:@"pic.jpg"]; 
self.imageURL = [NSURL fileURLWithPath:tmpPath]; 
[jpegImg writeToURL:self.imageURL atomically:NO]; 
self.picture.image = selectedImage; 
[picker dismissViewControllerAnimated:YES completion:nil]; 
} 
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { 
[picker dismissViewControllerAnimated:YES completion:NULL]; 
}
<MCSessionDelegate> 
#pragma mark - 
- (void)session:(MCSession *)session 
didStartReceivingResourceWithName:(NSString *)resourceName 
fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress 
{ 
dispatch_async(dispatch_get_main_queue(), ^{ 
self.picture.image = nil; 
self.picture.backgroundColor = [UIColor yellowColor]; 
}); 
} 
- (void)session:(MCSession *)session 
didFinishReceivingResourceWithName:(NSString *)resourceName 
fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL 
withError:(NSError *)error 
{ 
NSData *data = [NSData dataWithContentsOfURL:localURL]; 
UIImage *image = 
[[UIImage alloc] initWithData:data]; 
dispatch_async(dispatch_get_main_queue(), ^{ 
self.picture.image = image; 
}); 
}
Video Share images from photo 
library
Synchronizing without internet - Multipeer Connectivity (iOS)
Streaming - (NSOutputStream *)startStreamWithName:(NSString *)streamName 
toPeer:(MCPeerID *)peerID 
error:(NSError **)error;
NSOutputStream: open 
- (void)session:(MCSession *)session 
peer:(MCPeerID *)peerID 
didChangeState:(MCSessionState)state 
{ 
... 
if (state == MCSessionStateConnected) 
{ 
NSError *error; 
NSOutputStream *output = 
[session startStreamWithName:@"streamName" toPeer:peer error:&error]; 
if (error) { return; } 
[output scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 
[output open]; 
} 
... 
}
NSOutputStream: write 
NSData *data = [NSData data]; 
[self.output write:data.bytes maxLength:data.length];
NSInputStream 
- (void)session:(MCSession *)session 
didReceiveStream:(NSInputStream *)stream 
withName:(NSString *)streamName 
fromPeer:(MCPeerID *)peerID 
{ 
stream.delegate = self; 
[stream scheduleInRunLoop:[NSRunLoop mainRunLoop] 
forMode:NSDefaultRunLoopMode]; 
[stream open]; 
}
<NSStreamDelegate> 
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode 
{ 
switch (eventCode) { 
case NSStreamEventOpenCompleted: 
... 
case NSStreamEventEndEncountered: 
... 
case NSStreamEventHasBytesAvailable: 
{ 
NSInputStream *inputStream = (NSInputStream *)aStream; 
uint8_t buffer[1024]; 
NSInteger size = [inputStream read:(uint8_t *)buffer maxLength:1024]; 
NSData *data = [NSData dataWithBytes:buffer length:size]; 
... 
// Manage data received 
... 
break; 
} 
default: 
break; 
} 
}
Example Shared whiteboard
Synchronizing without internet - Multipeer Connectivity (iOS)
UIPanGestureRecognizer 
- (IBAction)panReceived:(UIPanGestureRecognizer *)sender 
{ 
CGPoint point = [sender locationInView:sender.view]; 
[self.drawable drawPoint:point state:sender.state]; 
NSData *data = 
[NSData drawDataWithGestureState:sender.state 
point:[sender locationInView:sender.view]]; 
[self.output write:data.bytes maxLength:data.length]; 
}
- (void)drawPoint:(CGPoint)point state:(UIGestureRecognizerState)state 
{ 
switch (state) { 
case UIGestureRecognizerStateBegan: 
{ 
lastPoint = point; 
break; 
} 
case UIGestureRecognizerStateChanged: 
{ 
CGPoint currentPoint = point; 
UIGraphicsBeginImageContext(self.layout.frame.size); 
[self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height)]; 
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); 
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); 
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); 
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10); 
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1.0); 
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal); 
CGContextStrokePath(UIGraphicsGetCurrentContext()); 
self.tmpLayout.image = UIGraphicsGetImageFromCurrentImageContext(); 
[self.tmpLayout setAlpha:1]; 
UIGraphicsEndImageContext(); 
lastPoint = currentPoint; 
break; 
} 
case UIGestureRecognizerStateEnded: 
{ 
UIGraphicsBeginImageContext(self.layout.frame.size); 
[self.layout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; 
[self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; 
self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); 
self.tmpLayout.image = nil; 
UIGraphicsEndImageContext(); 
break; 
} 
default: 
break; 
} 
}
- (void)clearScreen 
{ 
UIGraphicsBeginImageContext(self.layout.frame.size); 
CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGContextSetRGBFillColor(ctx, 255.0, 255.0, 255.0, 1.0); 
CGContextFillRect(ctx, CGRectMake(0, 0, 
self.tmpLayout.frame.size.width, self.tmpLayout.frame.size.height)); 
self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
}
Video Shared whiteboard
Synchronizing without internet - Multipeer Connectivity (iOS)
All together
'simple sync' example 
· n-devices. 
· Create a hash by each register based 
in time. 
· First sync in batch using a file. 
· NSOutputstream to send 'ligth data'. 
· Off and on send counters & timers 
using MCSessionSendDataReliable.
'simple sync' example 
· n-devices. 
· Create a hash by each register based 
in time. 
· First sync in batch using a file. 
· NSOutputstream to send 'ligth data'. 
· Off and on send counters & timers 
using MCSessionSendDataReliable.
Synchronizing without internet - Multipeer Connectivity (iOS)
Ensembles1 
"Sync for Core Data Apps" 
1 http://www.ensembles.io
How far can I ...
How far can I ... 
- RADIOUS2. 
- DevRocket3 
... 
2 RADIOUS: https://itunes.apple.com/nz/app/radious-walkie-talkie/ 
id738480541?mt=8. 
3 DeckRocket: https://github.com/jpsim/DeckRocket.
Questions 
?
Thanks @patoroco

More Related Content

PDF
Multipeer Connectivity
PDF
NSCoder Keynote - Multipeer Connectivity Framework
KEY
Practical Use of MongoDB for Node.js
PDF
Mongoose: MongoDB object modelling for Node.js
PPTX
Mongoose and MongoDB 101
PPTX
Simple blog wall creation on Java
PDF
How to build microservices with node.js
PDF
03 Web Events and jQuery
Multipeer Connectivity
NSCoder Keynote - Multipeer Connectivity Framework
Practical Use of MongoDB for Node.js
Mongoose: MongoDB object modelling for Node.js
Mongoose and MongoDB 101
Simple blog wall creation on Java
How to build microservices with node.js
03 Web Events and jQuery

What's hot (16)

KEY
Authentication
KEY
Google
PDF
A Django like messages framework for Tornado
PPTX
Micro Web Service - Slim and JWT
PDF
Вещи на Python - Сергей Матвеенко, DataArt
PDF
Json web token api authorization
ODP
How to integrate bit coin wallet using blockchain methodology
DOCX
Mongoose getting started-Mongo Db with Node js
PPTX
Evented Javascript
PPTX
Jquery Basics
PDF
From Node.js to Design Patterns
PDF
Introduction to Polymer
PDF
JavaOne 2014 - Securing RESTful Resources with OAuth2
PDF
Joe Walker Interactivewebsites Cometand Dwr
PDF
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
Authentication
Google
A Django like messages framework for Tornado
Micro Web Service - Slim and JWT
Вещи на Python - Сергей Матвеенко, DataArt
Json web token api authorization
How to integrate bit coin wallet using blockchain methodology
Mongoose getting started-Mongo Db with Node js
Evented Javascript
Jquery Basics
From Node.js to Design Patterns
Introduction to Polymer
JavaOne 2014 - Securing RESTful Resources with OAuth2
Joe Walker Interactivewebsites Cometand Dwr
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
Ad

Similar to Synchronizing without internet - Multipeer Connectivity (iOS) (20)

KEY
iPhone project - Wireless networks seminar
PDF
Integrating Angular js & three.js
PDF
Курсы по мобильной разработке под iOS. 4 лекция. Возможности телефона
PDF
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
PPT
iOS Training Session-3
PPTX
Writing JavaScript for C# Blazor.pptx
PDF
Forge - DevCon 2016: Visual Reporting with Connected Design Data
KEY
CakePHP in iPhone App
PPTX
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
PDF
303 TANSTAAFL: Using Open Source iPhone UI Code
PDF
Standardized API Development using Node.js
PDF
Implementing new WebAPIs
PDF
Implementing New Web
KEY
UIWebView Tips
PDF
Marker-based Augmented Monuments on iPhone and iPad
ODP
Android Camera Architecture
PDF
Intro to HTML5
KEY
I phone勉強会 (2011.11.23)
PDF
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
KEY
CocoaHeads Toulouse - Guillaume Cerquant - UIView
iPhone project - Wireless networks seminar
Integrating Angular js & three.js
Курсы по мобильной разработке под iOS. 4 лекция. Возможности телефона
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
iOS Training Session-3
Writing JavaScript for C# Blazor.pptx
Forge - DevCon 2016: Visual Reporting with Connected Design Data
CakePHP in iPhone App
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
303 TANSTAAFL: Using Open Source iPhone UI Code
Standardized API Development using Node.js
Implementing new WebAPIs
Implementing New Web
UIWebView Tips
Marker-based Augmented Monuments on iPhone and iPad
Android Camera Architecture
Intro to HTML5
I phone勉強会 (2011.11.23)
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
CocoaHeads Toulouse - Guillaume Cerquant - UIView
Ad

Recently uploaded (6)

PDF
Lesson 13- HEREDITY _ pedSAWEREGFVCXZDSASEWFigree.pdf
DOC
Camb毕业证学历认证,格罗斯泰斯特主教大学毕业证仿冒文凭毕业证
DOC
证书学历UoA毕业证,澳大利亚中汇学院毕业证国外大学毕业证
PPTX
ASMS Telecommunication company Profile
PDF
6-UseCfgfhgfhgfhgfhgfhfhhaseActivity.pdf
PDF
heheheueueyeyeyegehehehhehshMedia-Literacy.pdf
Lesson 13- HEREDITY _ pedSAWEREGFVCXZDSASEWFigree.pdf
Camb毕业证学历认证,格罗斯泰斯特主教大学毕业证仿冒文凭毕业证
证书学历UoA毕业证,澳大利亚中汇学院毕业证国外大学毕业证
ASMS Telecommunication company Profile
6-UseCfgfhgfhgfhgfhgfhfhhaseActivity.pdf
heheheueueyeyeyegehehehhehshMedia-Literacy.pdf

Synchronizing without internet - Multipeer Connectivity (iOS)

  • 1. Synchronizing without internet Codemotion 2014, Madrid
  • 2. Who am I? Jorge Maroto (@patoroco) http://maroto.me · iOS Developer @ticketeaeng · Playing with iOS since 2010 · Fanboy
  • 8. LAN (wired / wi-fi)
  • 10. Changelog · iOS 3: Game Kit · iOS 4: Game Center · iOS 5: Core Bluetooth · iOS 6: Core Bluetooth advertising · iOS 7: Multipeer Connectivity & iBeacons · iOS 8: Handoff
  • 11. Changelog · iOS 3: Game Kit · iOS 4: Game Center · iOS 5: Core Bluetooth · iOS 6: Core Bluetooth advertising · iOS 7: Multipeer Connectivity & iBeacons · iOS 8: Handoff
  • 13. Multipeer connectivity · Appears in iOS7. · Ability to connect to a mesh of peers. · Able to connect to peers over WiFi, ad-hoc wireless, and Bluetooth. · Doesn't require server infraestructure. · Peers must be 'nearby'.
  • 17. Two phases · Discovery · Session
  • 19. Session info · MCPeerId · MCSession
  • 20. MCPeerId MCPeerID *peerId = [[MCPeerID alloc] initWithDisplayName:self.deviceName];
  • 21. MCSession MCSession *session = [[MCSession alloc] initWithPeer:self.peerId]; session.delegate = self;
  • 22. <MCSessionDelegate> - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state { switch (state): { case MCSessionStateConnected: ... case MCSessionStateConnecting: ... case MCSessionStateNotConnected: ... } }
  • 23. <MCSessionDelegate> // DATA - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID {} // RESOURCES - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress {} - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error{} // STREAMS - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID{}
  • 24. Discovery · MCBrowserViewController · MCNearbyServiceBrowser
  • 25. MCBrowserViewController NSString * const serviceIdentifier = @"codemotion-demo"; MCBrowserViewController *browser = [[MCBrowserViewController alloc] initWithServiceType:serviceIdentifier session:self.appdelegate.session]; browser.delegate = self; [self presentViewController:browser animated:YES completion:nil];
  • 27. <MCBrowserViewControllerDelegate> - (void)browserViewControllerDidFinish:(MCBrowserViewController *)b {} - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)b {}
  • 28. Advertisement · MCAdvertiserAssistant · MCNearbyServicesAdvertiser
  • 29. MCAdvertiserAssistant NSString * const serviceIdentifier = @"codemotion-demo"; MCAdvertiserAssistant *advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:self.serviceIdentifier discoveryInfo:nil session:session]; [advertiser start];
  • 31. Sending data · NSData to an array of peers. · NSURL resource to a peer. · NSStream to a peer.
  • 32. Send NSData to an array of peers - (BOOL)sendData:(NSData *)data toPeers:(NSArray *)peerIDs withMode:(MCSessionSendDataMode)mode error:(NSError **)error; Modes · MCSessionSendDataReliable · MCSessionSendDataUnreliable
  • 34. Video
  • 36. Send resource to a peer - (NSProgress *)sendResourceAtURL:(NSURL *)resourceURL withName:(NSString *)resourceName toPeer:(MCPeerID *)peerID withCompletionHandler:(void(^)(NSError *error))completionHandler;
  • 37. Example Share images from photo library
  • 38. @property (weak, nonatomic) IBOutlet UIImageView *picture;
  • 39. - (IBAction)choosePhoto:(UIButton *)sender { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.allowsEditing = NO; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.mediaTypes = @[(NSString *)kUTTypeImage]; [self presentViewController:picker animated:YES completion:nil]; }
  • 40. <UIImagePickerDelegate> #pragma mark - UIImagePickerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *selectedImage = info[UIImagePickerControllerOriginalImage]; NSData *jpegImg = UIImageJPEGRepresentation(selectedImage, 0.5); NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingString:@"pic.jpg"]; self.imageURL = [NSURL fileURLWithPath:tmpPath]; [jpegImg writeToURL:self.imageURL atomically:NO]; self.picture.image = selectedImage; [picker dismissViewControllerAnimated:YES completion:nil]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:NULL]; }
  • 41. <MCSessionDelegate> #pragma mark - - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress { dispatch_async(dispatch_get_main_queue(), ^{ self.picture.image = nil; self.picture.backgroundColor = [UIColor yellowColor]; }); } - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error { NSData *data = [NSData dataWithContentsOfURL:localURL]; UIImage *image = [[UIImage alloc] initWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ self.picture.image = image; }); }
  • 42. Video Share images from photo library
  • 44. Streaming - (NSOutputStream *)startStreamWithName:(NSString *)streamName toPeer:(MCPeerID *)peerID error:(NSError **)error;
  • 45. NSOutputStream: open - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state { ... if (state == MCSessionStateConnected) { NSError *error; NSOutputStream *output = [session startStreamWithName:@"streamName" toPeer:peer error:&error]; if (error) { return; } [output scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [output open]; } ... }
  • 46. NSOutputStream: write NSData *data = [NSData data]; [self.output write:data.bytes maxLength:data.length];
  • 47. NSInputStream - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID { stream.delegate = self; [stream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [stream open]; }
  • 48. <NSStreamDelegate> - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventOpenCompleted: ... case NSStreamEventEndEncountered: ... case NSStreamEventHasBytesAvailable: { NSInputStream *inputStream = (NSInputStream *)aStream; uint8_t buffer[1024]; NSInteger size = [inputStream read:(uint8_t *)buffer maxLength:1024]; NSData *data = [NSData dataWithBytes:buffer length:size]; ... // Manage data received ... break; } default: break; } }
  • 51. UIPanGestureRecognizer - (IBAction)panReceived:(UIPanGestureRecognizer *)sender { CGPoint point = [sender locationInView:sender.view]; [self.drawable drawPoint:point state:sender.state]; NSData *data = [NSData drawDataWithGestureState:sender.state point:[sender locationInView:sender.view]]; [self.output write:data.bytes maxLength:data.length]; }
  • 52. - (void)drawPoint:(CGPoint)point state:(UIGestureRecognizerState)state { switch (state) { case UIGestureRecognizerStateBegan: { lastPoint = point; break; } case UIGestureRecognizerStateChanged: { CGPoint currentPoint = point; UIGraphicsBeginImageContext(self.layout.frame.size); [self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height)]; CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10); CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1.0); CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal); CGContextStrokePath(UIGraphicsGetCurrentContext()); self.tmpLayout.image = UIGraphicsGetImageFromCurrentImageContext(); [self.tmpLayout setAlpha:1]; UIGraphicsEndImageContext(); lastPoint = currentPoint; break; } case UIGestureRecognizerStateEnded: { UIGraphicsBeginImageContext(self.layout.frame.size); [self.layout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; [self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); self.tmpLayout.image = nil; UIGraphicsEndImageContext(); break; } default: break; } }
  • 53. - (void)clearScreen { UIGraphicsBeginImageContext(self.layout.frame.size); CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(ctx, 255.0, 255.0, 255.0, 1.0); CGContextFillRect(ctx, CGRectMake(0, 0, self.tmpLayout.frame.size.width, self.tmpLayout.frame.size.height)); self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); }
  • 57. 'simple sync' example · n-devices. · Create a hash by each register based in time. · First sync in batch using a file. · NSOutputstream to send 'ligth data'. · Off and on send counters & timers using MCSessionSendDataReliable.
  • 58. 'simple sync' example · n-devices. · Create a hash by each register based in time. · First sync in batch using a file. · NSOutputstream to send 'ligth data'. · Off and on send counters & timers using MCSessionSendDataReliable.
  • 60. Ensembles1 "Sync for Core Data Apps" 1 http://www.ensembles.io
  • 61. How far can I ...
  • 62. How far can I ... - RADIOUS2. - DevRocket3 ... 2 RADIOUS: https://itunes.apple.com/nz/app/radious-walkie-talkie/ id738480541?mt=8. 3 DeckRocket: https://github.com/jpsim/DeckRocket.