GKSession displayNameForPeer阻止释放会话(iOS 4.0、4.1)
在为另一个对等方(不是self)调用displayNameForPeer后,我可以在释放GKSession时可靠地用它使模拟器崩溃,我不确定这是我做错了什么,还是苹果的Gamekit框架有缺陷(我是否需要担心,因为我只看到4.0和4.1下的崩溃,而不是4.2+) 输出为:GKSession displayNameForPeer阻止释放会话(iOS 4.0、4.1),ios,gamekit,gksession,Ios,Gamekit,Gksession,在为另一个对等方(不是self)调用displayNameForPeer后,我可以在释放GKSession时可靠地用它使模拟器崩溃,我不确定这是我做错了什么,还是苹果的Gamekit框架有缺陷(我是否需要担心,因为我只看到4.0和4.1下的崩溃,而不是4.2+) 输出为: found available peer; checking name and ID... m4, 26176566 *** -[GKSessionInternal lock]: message sent to dealloc
found available peer; checking name and ID... m4, 26176566
*** -[GKSessionInternal lock]: message sent to deallocated instance 0x7508900
这里是最小的可复制代码集——请注意,另一个GKSession必须在网络上可见(以便找到一个可用的对等方来调用displayNameForPeer on)才能触发崩溃。在另一台设备上运行相同的代码,但没有makeUnavailable和killSession调用就足够了
- (void)viewDidLoad
{
[self createSession];
[self makeAvailable];
peerListAvailable = [[NSMutableArray alloc] initWithArray:[currentSession peersWithConnectionState:GKPeerStateAvailable]];
for (NSString *peer in peerListAvailable)
{
// this method guarantees the crash on session release
NSLog(@"found available peer; checking name and ID... %@, %@",[currentSession displayNameForPeer:peer], peer);
}
[peerListAvailable release];
peerListAvailable = nil;
[self makeUnavailable];
[self killSession];
[super viewDidLoad];
}
- (void) createSession
{
if (!currentSession)
{
currentSession = [[GKSession alloc] initWithSessionID:@"GKTester" displayName:nil sessionMode:GKSessionModePeer];
currentSession.delegate = self;
currentSession.disconnectTimeout = 30;
[currentSession setDataReceiveHandler: self withContext:nil];
}
}
-(void) killSession
{
if (currentSession)
{
[currentSession disconnectFromAllPeers];
[currentSession setDelegate:nil];
[currentSession setDataReceiveHandler:nil withContext:nil];
[currentSession release]; // crash occurs after this
currentSession = nil;
}
}
-(void) makeAvailable
{
while (currentSession && !currentSession.available)
{
[currentSession setAvailable:YES];
[NSThread sleepForTimeInterval:.5];
}
}
-(void) makeUnavailable
{
while (currentSession && currentSession.available)
{
[NSThread sleepForTimeInterval:.5];
[currentSession setAvailable:NO];
}
}您的代码中存在过度释放:
[currentSession disconnectFromAllPeers];
[currentSession setDelegate:nil];
[currentSession setDataReceiveHandler:nil withContext:nil];
[currentSession release]; // This is an over-release
currentSession = nil; // You are trying to access a variable after it's been released
您应该仅在dealloc中释放currentSession成员变量,如下所示:
- (void)dealloc
{
[currentSession release];
[super dealloc];
}
到目前为止,我找到的唯一解决方法是使用自动释放而不是释放。这至少可以在4.0-4.3版本上可靠地工作。