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
¿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'.
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];
<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
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
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
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
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.
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

What's hot

Authentication
AuthenticationAuthentication
Authentication
soon
 
Google
GoogleGoogle
Google
soon
 
A Django like messages framework for Tornado
A Django like messages framework for TornadoA Django like messages framework for Tornado
A Django like messages framework for Tornado
Chao Gao
 
Micro Web Service - Slim and JWT
Micro Web Service - Slim and JWTMicro Web Service - Slim and JWT
Micro Web Service - Slim and JWT
Tuyen Vuong
 
Вещи на Python - Сергей Матвеенко, DataArt
Вещи на Python - Сергей Матвеенко, DataArtВещи на Python - Сергей Матвеенко, DataArt
Вещи на Python - Сергей Матвеенко, DataArt
it-people
 
Json web token api authorization
Json web token api authorizationJson web token api authorization
Json web token api authorization
Giulio De Donato
 
How to integrate bit coin wallet using blockchain methodology
How to integrate bit coin wallet using blockchain methodologyHow to integrate bit coin wallet using blockchain methodology
How to integrate bit coin wallet using blockchain methodology
Mitosis Technology
 
Mongoose getting started-Mongo Db with Node js
Mongoose getting started-Mongo Db with Node jsMongoose getting started-Mongo Db with Node js
Mongoose getting started-Mongo Db with Node js
Pallavi Srivastava
 
Evented Javascript
Evented JavascriptEvented Javascript
Evented Javascript
waw325
 
Jquery Basics
Jquery BasicsJquery Basics
Jquery Basics
Umeshwaran V
 
Client side
Client sideClient side
From Node.js to Design Patterns
From Node.js to Design Patterns From Node.js to Design Patterns
From Node.js to Design Patterns
Luciano Mammino
 
Introduction to Polymer
Introduction to PolymerIntroduction to Polymer
Introduction to Polymer
Egor Miasnikov
 
JavaOne 2014 - Securing RESTful Resources with OAuth2
JavaOne 2014 - Securing RESTful Resources with OAuth2JavaOne 2014 - Securing RESTful Resources with OAuth2
JavaOne 2014 - Securing RESTful Resources with OAuth2
Rodrigo Cândido da Silva
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand DwrJoe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
deimos
 
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
PROIDEA
 

What's hot (16)

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

Similar to Synchronizing without internet - Multipeer Connectivity (iOS)

iPhone project - Wireless networks seminar
iPhone project - Wireless networks seminariPhone project - Wireless networks seminar
iPhone project - Wireless networks seminar
Silvio Daminato
 
Integrating Angular js & three.js
Integrating Angular js & three.jsIntegrating Angular js & three.js
Integrating Angular js & three.js
Josh Staples
 
Курсы по мобильной разработке под iOS. 4 лекция. Возможности телефона
Курсы по мобильной разработке под iOS. 4 лекция. Возможности телефонаКурсы по мобильной разработке под iOS. 4 лекция. Возможности телефона
Курсы по мобильной разработке под iOS. 4 лекция. Возможности телефона
Глеб Тарасов
 
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
How to Hack a Road Trip  with a Webcam, a GSP and Some Fun with NodeHow to Hack a Road Trip  with a Webcam, a GSP and Some Fun with Node
How to Hack a Road Trip with a Webcam, a GSP and Some Fun with Node
pdeschen
 
iOS Training Session-3
iOS Training Session-3iOS Training Session-3
iOS Training Session-3
Hussain Behestee
 
Writing JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptxWriting JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptx
Ed Charbeneau
 
Forge - DevCon 2016: Visual Reporting with Connected Design Data
Forge - DevCon 2016: Visual Reporting with Connected Design DataForge - DevCon 2016: Visual Reporting with Connected Design Data
Forge - DevCon 2016: Visual Reporting with Connected Design Data
Autodesk
 
CakePHP in iPhone App
CakePHP in iPhone AppCakePHP in iPhone App
CakePHP in iPhone App
Akihiro Matsuura
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
DroidConTLV
 
303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code
jonmarimba
 
Standardized API Development using Node.js
Standardized API Development using Node.jsStandardized API Development using Node.js
Standardized API Development using Node.js
ndsmyter
 
Implementing New Web
Implementing New WebImplementing New Web
Implementing New Web
Julian Viereck
 
Implementing new WebAPIs
Implementing new WebAPIsImplementing new WebAPIs
Implementing new WebAPIs
Julian Viereck
 
UIWebView Tips
UIWebView TipsUIWebView Tips
UIWebView Tips
Katsumi Kishikawa
 
Marker-based Augmented Monuments on iPhone and iPad
Marker-based Augmented Monuments on iPhone and iPadMarker-based Augmented Monuments on iPhone and iPad
Marker-based Augmented Monuments on iPhone and iPad
Enrico Micco
 
Android Camera Architecture
Android Camera ArchitectureAndroid Camera Architecture
Android Camera Architecture
Picker Weng
 
Intro to HTML5
Intro to HTML5Intro to HTML5
Intro to HTML5
Jussi Pohjolainen
 
I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)
Katsumi Kishikawa
 
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
Conceitos e prática no desenvolvimento iOS - Mobile Conf 2014
Fábio Pimentel
 
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIViewCocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads France
 

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

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

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
  • 4.
  • 5.
  • 6.
  • 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'.
  • 14.
  • 15.
  • 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];
  • 26.
  • 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
  • 35.
  • 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
  • 43.
  • 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; } }
  • 50.
  • 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(); }
  • 55.
  • 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.
  • 59.
  • 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.