1

摘要:当该方法beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfocontextInfo提供一个 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 是否根本不会用这种方法保证任何事情?

4

0 回答 0