GKSession-如果我关闭了蓝牙和Wi-Fi,会发生什么?

11
我正在开发一款iPhone应用程序,它可以实现点对点连接。据我所知,我可以选择使用GKPeerPicker或GKSession。我不想使用PeerPicker,因为我想展示自定义界面,所以我决定使用GKSession,并且额外的好处是它还可以通过Wi-Fi工作,而PeerPicker则不能。
问题是...如果用户关闭了蓝牙和Wi-Fi呢?在PeerPicker中,有一个提示可以在不离开应用程序的情况下打开蓝牙。GKSession没有这个功能...但是等等,看起来我甚至无法编程检查蓝牙是否已打开! Carpe Cocoa声称没有问题,只需使用Delegate的session:didFailWithError:方法。但是,正如评论中所解释的那样...这似乎不再起作用了!根据我的经验,我也同意这一点。
有没有其他方法可以编程检查蓝牙是否已打开?这是我应该利用可达性吗?还是这只是苹果尚未修复的错误?
更具体地说,我是这样创建我的会话的:
GKSession *aSession = [[GKSession alloc] initWithSessionID:nil
                                                  displayName:user.displayName 
                                                  sessionMode:GKSessionModePeer];

self.gkSession = aSession;
[aSession release];

self.gkSession.delegate = self;
self.gkSession.available = YES;

[self.gkSession setDataReceiveHandler:self withContext:NULL];

该类实现了GKSessionDelegate,并且我知道它正在工作,因为当我打开蓝牙时,委托方法就会被调用,没有问题。我已经将它们实现为以下方式:
#pragma mark -
#pragma mark GKSessionDelegate methods

- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
     if (GKPeerStateAvailable == state) {
          [session connectToPeer:peerID withTimeout:10];
     } else if (GKPeerStateConnected == state) {
          // gets user

          NSError *error = nil;
          [session sendData:user.connectionData
                      toPeers:[NSArray arrayWithObjects:peerID,nil]
                withDataMode:GKSendDataReliable error:&error];
          if (error)
               NSLog(@"%@",error);
     }
}



- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID {
     NSError *error = nil;
     [session acceptConnectionFromPeer:peerID error:&error];
     if (error)
          NSLog(@"%@",error);
}

- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error {
     NSLog(@"%@",error);
}

- (void)session:(GKSession *)session didFailWithError:(NSError *)error {
     NSLog(@"%@",error);
}

当用户关闭蓝牙和Wi-Fi时,没有任何日志语句被打印出来,我在每个方法中设置了断点,但是它们都没有被触发。我希望能够触发session:didFailWithError:以便提示用户打开蓝牙或连接到Wi-Fi网络。


2
听起来像是一个错误或者可能是一个增强请求。你应该提交一个雷达报告。 - Martin Gordon
6个回答

2

iOS 5中可以通过以下方式实现:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
NSMutableArray * discoveredPeripherals = [NSMutableArray new];
CBCentralManager * manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[manager scanForPeripheralsWithServices:discoveredPeripherals options:options];
[manager stopScan];

在iOS 5中,这需要您导入CoreBluetooth框架。如果蓝牙关闭,系统将弹出一个警示框,提供打开蓝牙的选项。否则,如果发现外围设备,它将调用相应的委托方法,但如果在该实现中没有任何东西,您不需要担心。


1

我同意Martin Gordon的观点,但是一个解决办法可能是使用苹果的可达性


1

有趣的一点,你是否尝试过在关闭蓝牙同时开启 WiFi 的情况下进行测试?最近我发现虽然我的程序提示了“蓝牙不可用”的信息,但它实际上根本没有使用蓝牙,而是通过我的 WiFi 网络连接。我不知道是否有办法强制 GKSession 建立蓝牙连接,而不使用苹果的 PeerPicker 对象,但 PeerPicker 对象确实允许人们自己制作接口。它似乎不允许除对等之外的其他连接类型,所以如果您想要客户端/服务器安排,它不会有太大的帮助。

-Ash


0

我赞同使用苹果的可达性(reachability)的观点。作为奖励,它被列为苹果应用商店提交指南之一。

实现起来也不难,因为大部分所需代码已经为您编写好了。

Slf提供了一个使用Reachability类的源代码链接,此外这里还有一个Apple Dev官方可达性示例的链接。

但是,请确保您异步地检查连接性。

我在我的应用程序中使用它,虽然它不是最好的解决方案,但至少它会通知用户需要调整连接设置或者没有网络存在。


0

您可以通过使用苹果的私有API(我认为是BluetoothManger.h)来编程开启蓝牙,但请注意,这将导致在苹果应用商店推送中被拒绝。


-1

你应该使用相同的 sessionID


1
你是什么意思?为什么? - Jonathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接