摘要:当该方法beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo
为contextInfo提供一个 NSArray 或 NSDictionary 的对象时,它实际上将成为指向内存中任何位置的任意指针。什么是正确的解决方案?
下图说明了问题:
- (IBAction)testbutton:(id)sender {
NSAlert *alert = [[NSAlert alloc] init];
[alert beginSheetModalForWindow:theWindow
modalDelegate:self
idEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:[NSArray arrayWithObject:@"bla bla"]];
}
- (void) alertDidEnd:(NSAlert *)alert
returnCode:(NSInteger)returnCode
contextInfo:(NSArray *)contextInfo {
NSLog(@"contextInfo: %@", contextInfo);
}
NSLog 将输出内存中的任意内容,包括指针为空时的崩溃。但是,如果 contextInfo 是更简单的东西,例如 NSString、NSNumber,甚至是 NSTextField 之类的出口,它就可以正常工作。此外,如果我提供一个 NSArray 或 NSDictionary 的实例变量,那么它就可以工作。
在 Apple 的文档中,contextInfo被声明为 (void *),因此它可以是任何东西(甚至是任意指针)。但是因为我知道这个类,所以在这个例子中我将它声明为 NSArray。然而,问题并不取决于我声明的 contextInfo 是什么。
当我有垃圾收集时,Lion 中会出现问题。
在消息Using NSAlert beginSheetModalForWindow with contextInfo 'noa' 中说“如果您正在使用垃圾收集,请存储在实例变量中 - 任何地方都无所谓 - 所以它不会在运行循环结束时释放。你需要坚持直到 didEndSelector 可以对其采取行动。”
这是一个很好的解决方法,但它很奇怪,而且很丑陋。没有更优雅的解决方案吗?
这种行为真的是苹果想要的吗?还是一个明显的错误?NSString 和 NSNumber 等简单对象可以,但 NSArray 不行。如果它真的不是一个错误,是否应该指定 contextInfo 的限制,并且不应该准确指定何时以及如何以某种方式显式保留它?或者除非contextInfo是一个实例变量,否则 GC 是否根本不会用这种方法保证任何事情?