天天品尝iOS7甜点 :: Day 23 :: Multipeer Connectivity

这篇文章是天天品尝iOS7甜点系列的一部分,你可以查看完整的系列目录:天天品尝iOS7甜点


Introducation - 介绍

在iOS7中介绍了一个全新的框架 MultipeerConnectivity。这个是代表这传统苹果中第一个困难问题:考虑到移动设备都有多种不同的无线电技术建成的,当然,他们应该能够相互通信而无需通过互联网发送数据。在过去就可以创建一个特别的wifi网络,在蓝牙或对设备,但这些选项提供了一个非常友好的方法。伴随MultipeerConnectivity框架的变化——设置网络脱离用户和开发人员,通过与技术无关的API,而通信发生。

框架在现实中无论技术具备——无论是蓝牙,或wifi,要么使用基础设施网络,或特别的网络如果设备不共享相同的网络。这是真正的,用户就可以选择它周围的设备希望连接到框架将处理所有的休息。甚至能够使用一个节点作为一个路由器2节点之间相互看不到mesh-network的方式。

在今天的帖子里,我们会通过代码的运行需要建立一个multipeer这样的网络,以及如何在设备之间发送数据。

本章的实例程序能够在github上面进行访问,访问地址:github.com/ShinobiControls/iOS7-day-by-day

Browsing for devices - 查找浏览设备

为了发送数据,有必要建立一个设备之间的连接,这是完成一个设备“浏览”适当的设备范围内。可以请求发送到这些设备之一,它将提醒用户,允许他们接受或拒绝连接。如果连接被接受,那么框架将建立链接,允许数据被转移。

有2种方法可以浏览本地设备——一个视觉的,和一个可编程的版本。我们只是去看看视觉的方法。

multipeer网络中的所有节点必须有一个ID——这是由MCPeerID类:

1
_peerID = [[MCPeerID alloc] initWithDisplayName:self.peerNameTextField.text];

在这里我们允许用户输入一个名称将用于识别用户试图收集装置。

MCSession对象是用来协调同事之间发送数据在该会话。我们首先创建一个,然后添加同行:

1
2
_session = [[MCSession alloc] initWithPeer:_peerID];
_session.delegate = self;

MCSession委托财产采用MCSessionDelegate协议。这包括方法监测同行改变状态(如断开),以及方法,对等网络中的启动时被调用的数据传输。

为了同伴添加到会话有ViewController子类提供了一个列表,本地设备的用户,并允许他们选择他们想建立一个连接。我们创建一个,然后将其归纳为一个模态视图控制器:

1
2
3
MCBrowserViewController *browserVC = [[MCBrowserViewController alloc] initWithServiceType:@"shinobi-stream" session:_session];
browserVC.delegate = self;
[self presentViewController:browserVC animated:YES completion:NULL];

serviceType参数是一个字符串代表我们试图连接到的服务。这个字符串可以包含小写字母,数字和连字符,应该hi 类似于bonjour域。

我们再次分配委托——这一次采用MCBrowserViewControllerDelegate协议。有两个方法,我们需要为完成和实现——取消浏览器视图控制器。这里我们将把浏览器和启用按钮,如果我们成功:

1
2
3
4
5
6
7
8
9
10
11
12
#pragma mark - MCBrowserViewControllerDelegate methods
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
[browserViewController dismissViewControllerAnimated:YES completion:NULL];
}

- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
[browserViewController dismissViewControllerAnimated:YES completion:^{
self.takePhotoButton.enabled = YES;
}];
}

如果我们运行应用程序在这一点上我们可以输入一个同伴的名字,然后打开浏览器搜索其他设备。在这个阶段我们不没有其他设备实现广告的功能,所以我们不能连接到任何东西。这在下一节中,我们会执行下面的图片显示了连接过程,如果我们有一个设备连接,连接被接受:

Advertising avaiability - 广告可用性

广告通过MCAdvertiserAssistant类可用性成为可能,这既要负责管理网络层,并向用户呈现一个警告的让他们接受或拒绝传入的连接。

以同样的方式,我们需要一个会话和同行ID来浏览,我们需要他们的广告,所以我们允许用户指定一个字符串用作对等名称:

1
2
3
4
_peerID = [[MCPeerID alloc] initWithDisplayName:self.peerNameTextField.text];
_session = [[MCSession alloc] initWithPeer:_peerID];
_session.delegate = self;
_advertiserAssistant = [[MCAdvertiserAssistant alloc] initWithServiceType:@"shinobi-stream" discoveryInfo:nil session:_session];

我们使用相同的字符串serviceType参数是在浏览器中——这将使与适当的连接。      

最后,我们需要开始广告我们的可用性:

1
[_advertiserAssistant start];

如果我们现在启动浏览器在一个设备,然后广告商在另一个他们应该能够找到彼此。当设备出现在浏览器,用户水龙头,然后用广告设备用户将看到一个警告让他们选择是否连接:

Sending Data - 发送数据

有三个方法可以通过multipeer网络传输数据,我们建立了——一个NSData对象,一个NSStream或发送一个基于文件的资源。所有这三个共享一个共同的范式——MCSession对象发起这些转移的方法,然后在接收端将会话调用适当的代表方法。

例如,我们要拍照与一个设备,然后让它自动显示在屏幕上的其他设备。我们将使用NSData方法对于这个示例,但每个人的方法非常相似。

我们使用UIImagePickerController简单的照片

1
2
3
4
UIImagePickerController *imagePicker = [UIImagePickerController new];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:YES completion:NULL];

并实现以下委托方法获得预想的照片:

1
2
3
4
5
6
7
8
9
10
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *photo = info[UIImagePickerControllerOriginalImage];
UIImage *smallerPhoto = [self rescaleImage:photo toSize:CGSizeMake(800, 600)];
NSData *jpeg = UIImageJPEGRepresentation(smallerPhoto, 0.2);
[self dismissViewControllerAnimated:YES completion:^{
NSError *error = nil;
[_session sendData:jpeg toPeers:[_session connectedPeers] withMode:MCSessionSendDataReliable error:&error];
}];
}

我们感兴趣的是MCSession对象调用sendData:toPeers:withMode:error:方法。这可以采取一个NSDataobject网络中并将其发送到其他同行。在这里我们选择寄给所有的同事网络。模式允许您选择要传输的数据是否可靠。如果您选择可靠然后肯定会到达的消息,将会以正确的顺序,但将有一个更高的时间开销。使用不可靠的模式意味着一些消息可能会丢失,但延误将会小得多。

接受其他设备上的数据我们只是为正确的代表提供一个适当的实现方法:

1
2
3
4
5
6
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
UIImage *image = [UIImage imageWithData:data];
self.imageView.image = image;
self.imageView.contentScaleFactor = UIViewContentModeScaleAspectFill;
}

在这里我们简单地创建一个从NSData UIImage对象,然后设置UIImageView的形象。以下图片显示这张照片上一个设备,然后显示在另一个问题:

流和资源API几乎以相同的方式工作,虽然资源API提供了异步更新进展,因此更适用于大型数据传输。

Conclusion - 总结

MultipeerConnectivity框架非常强大,是类似的概念抽象的技术细节的开发人员。很明显,出现的新的空投功能iOS7是建立在这个框架,非常的冰山一角的可以使用这个框架构建。想象一个iBeacon,当你靠近它时,不仅会通知你的,然后给你发送信息不使用互联网。也许你可以多角度的视频到你的设备在一个体育赛事,但只有如果你在会场?我等不及要看别人怎么构建!

本文翻译自:iOS7 Day-by-Day :: Day 23 :: Multipeer Connectivity

文章目录
  1. 1. Introducation - 介绍
  2. 2. Browsing for devices - 查找浏览设备
  3. 3. Advertising avaiability - 广告可用性
  4. 4. Sending Data - 发送数据
  5. 5. Conclusion - 总结
,