GKSession displayNameForPeer 防止释放会话(iOS 4.0、4.1)
Posted
技术标签:
【中文标题】GKSession displayNameForPeer 防止释放会话(iOS 4.0、4.1)【英文标题】:GKSession displayNameForPeer prevents releasing the session (iOS 4.0, 4.1) 【发布时间】:2011-05-28 16:29:24 【问题描述】:在为另一个对等方(不是自己)调用 displayNameForPeer 后释放 GKSession 时,我可以可靠地使模拟器崩溃,我不确定这是我做错了什么还是苹果的 Gamekit 框架的错误(以及我是否需要担心它,因为我只看到 4.0 和 4.1 下的崩溃,而不是 4.2+)。
输出是:
found available peer; checking name and ID... m4, 26176566
*** -[GKSessionInternal lock]: message sent to deallocated instance 0x7508900
这是最小的可重现代码集——请注意,另一个 GKSession 必须在网络上可见(以便找到一个可用的对等方来调用 displayNameForPeer)才能触发崩溃。在另一台设备上运行相同的代码但没有 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];
【问题讨论】:
到目前为止,我发现的唯一解决方法是使用自动释放而不是释放。这至少在 4.0 - 4.3 版本上可靠地工作。 【参考方案1】:您的代码中有过度发布:
[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];
【讨论】:
以上是关于GKSession displayNameForPeer 防止释放会话(iOS 4.0、4.1)的主要内容,如果未能解决你的问题,请参考以下文章