GKSession displayNameForPeer prevents releasing the session (iOS 4.0, 4.1)
I can reliably crash the simulator with this when releasing the GKSession after calling displayNameForP开发者_StackOverflow中文版eer for another peer (not self), and I'm not sure if it's something I'm doing wrong or if it's a bug with Apple's Gamekit framework (and whether I need to worry about it, since I only see the crash under 4.0 and 4.1, not 4.2+).
The output is:
found available peer; checking name and ID... m4, 26176566
*** -[GKSessionInternal lock]: message sent to deallocated instance 0x7508900
Here's the minimal reproducible code set -- note that another GKSession must be visible on the network (so that there's an available peer found to call displayNameForPeer on) to trigger the crash. Running this same code on another device but without the makeUnavailable and killSession calls is adequate.
- (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];
}
}
You have an over-release in your code:
[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
You should release the currentSession member variable in dealloc only, like so:
- (void)dealloc
{
[currentSession release];
[super dealloc];
}
精彩评论