我正在使用MCNearbyServiceBrowser和MCNearbyServiceAdvertiser将两个对等体加入到MCSession中。我可以使用MCSession的sendData方法在它们之间发送数据。在我通过会话的MCSessionDelegate didChangeState处理程序随机(而不是由于我控制的任何事件)接收到MCSessionStateNotConnected之前,一切似乎都像预期的那样工作。此外,MCSession的connectedPeers数组不再有我的同级。
两个问题:为什么?如何防止MCSession断开连接?
发布于 2013-10-31 07:59:03
这是一个bug,我刚刚报告给了苹果。文档声称didReceiveCertificate回调是可选的,但事实并非如此。将此方法添加到MCSessionDelegate中
- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
certificateHandler(YES);
}随机断开应该会停止。
发布于 2013-10-21 23:26:21
更新在使用苹果的支持票证后,他们确认,调用sendData的频率太高,数据太多会导致连接断开。
当命中断点和背景时,我会断开连接。由于断点不会发生在应用程序商店上,因此您需要通过在应用程序即将进入后台时开始一个后台任务来处理后台情况。然后在应用程序返回前台时结束此任务。在iOS 7上,这为你提供了大约3分钟的后台时间,这总比什么都没有好。
一个额外的策略是使用[[UIApplication sharedApplication] backgroundTimeRemaining]在你的后台时间到期之前安排一个大约15秒的本地通知,这样你就可以在应用程序暂停和关闭多点框架之前将用户带回应用程序。也许本地通知会警告他们,他们的会话将在10秒内到期或其他什么……
如果后台任务到期,而应用程序仍在后台,则必须拆除与多点连接相关的所有内容,否则将会崩溃。
- (void) createExpireNotification
{
[self killExpireNotification];
if (self.connectedPeerCount != 0) // if peers connected, setup kill switch
{
NSTimeInterval gracePeriod = 20.0f;
// create notification that will get the user back into the app when the background process time is about to expire
NSTimeInterval msgTime = UIApplication.sharedApplication.backgroundTimeRemaining - gracePeriod;
UILocalNotification* n = [[UILocalNotification alloc] init];
self.expireNotification = n;
self.expireNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:msgTime];
self.expireNotification.alertBody = TR(@"Text_MultiPeerIsAboutToExpire");
self.expireNotification.soundName = UILocalNotificationDefaultSoundName;
self.expireNotification.applicationIconBadgeNumber = 1;
[UIApplication.sharedApplication scheduleLocalNotification:self.expireNotification];
}
}
- (void) killExpireNotification
{
if (self.expireNotification != nil)
{
[UIApplication.sharedApplication cancelLocalNotification:self.expireNotification];
self.expireNotification = nil;
}
}
- (void) applicationWillEnterBackground
{
self.taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
{
[self shutdownMultiPeerStuff];
[[UIApplication sharedApplication] endBackgroundTask:self.taskId];
self.taskId = UIBackgroundTaskInvalid;
}];
[self createExpireNotification];
}
- (void) applicationWillEnterForeground
{
[self killExpireNotification];
if (self.taskId != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:self.taskId];
self.taskId = UIBackgroundTaskInvalid;
}
}
- (void) applicationWillTerminate
{
[self killExpireNotification];
[self stop]; // shutdown multi-peer
}由于苹果的bug,你也需要在你的MCSession委托中使用这个处理程序:
- (void) session:(MCSession*)session didReceiveCertificate:(NSArray*)certificate fromPeer:(MCPeerID*)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
if (certificateHandler != nil) { certificateHandler(YES); }
}发布于 2014-02-05 05:32:18
造成这种情况的原因很多,根据我的经验,到目前为止,这两个答案都是正确的。你会在其他类似的问题中发现的另一个问题是:只有一个对等点可以接受另一个对等点的邀请。
因此,为了澄清,如果你设置了一个所有设备都既是广告商又是浏览器的应用程序,任何设备都可以自由地邀请任何其他人加入会话。但是,在任意两台给定设备之间,只有一台设备可以实际接受邀请并连接到另一台设备。如果两个设备都接受对方的邀请,它们将在一分钟或更短时间内断开连接。
请注意,此限制不会阻止所需的行为,因为-不像我在构建多点实现之前的直觉所说的那样-当一个设备接受邀请并连接到另一个设备时,它们都变得已连接并接收连接委托方法,并且可以相互发送消息。
因此,如果您连接的是浏览和广告的设备,请自由发送邀请,但只接受其中之一。
只接受两个邀请中的一个的问题可以有无数种方法来解决。首先,您可以将任意对象或字典(存档为数据)作为context参数传递到邀请中。因此,两个设备都可以访问对方的任何任意信息(当然还有自身)。因此,您至少可以使用以下策略:
compare: peerID的显示名称即可。但不能保证它们不会相等。compare:的对象都可以。https://stackoverflow.com/questions/18935288
复制相似问题