考虑以下简化代码示例。它在Swift中提供,但在objective-c中也会出现相同的行为。
import Foundation
import Cocoa
class MainWindow : NSWindow {
@IBAction func onClick_openFile(sender : AnyObject?) {
let path = runOpenPanel(false);
NSLog(path as String)
}
@IBAction func onClick_crashyByeBye(sender : AnyObject?) {
let path = runOpenPanel(true);
NSLog(path as String)
}
private func runOpenPanel(useCrashyDelegate : Bool) -> NSString {
let openPanel = NSOpenPanel.init()
openPanel.canChooseDirectories = false
openPanel.canChooseFiles = true
openPanel.allowsMultipleSelection = false
let safeDelegate = MyOpenPanelDelegate.init() //same scope as openPanel.runModal()--works fine
if (useCrashyDelegate) {
let crashyDelegate = MyOpenPanelDelegate.init() //falls out of scope before openPanel.runModal() and crashes
openPanel.delegate = crashyDelegate
} else {
openPanel.delegate = safeDelegate
}
if (openPanel.runModal() == NSFileHandlingPanelOKButton && openPanel.URLs.count == 1) {
return openPanel.URLs[0].path!
}
return ""
}
}
class MyOpenPanelDelegate : NSObject, NSOpenSavePanelDelegate {
func panel(sender: AnyObject, shouldEnableURL url: NSURL) -> Bool {
var isDir : ObjCBool = false
if (NSFileManager.defaultManager().fileExistsAtPath(url.path!, isDirectory: &isDir)) {
return isDir || (url.path! as NSString).lastPathComponent.lowercaseString == "foo.txt"
}
return false
}
}
当useCrashyDelegate
的{{1}}参数为真时,runOpenPanel
在嵌套范围内实例化,并且在调用crashyDelegate
之前超出范围。由于open面板将crashyDelegate指定为其委托,因此我希望openPanel.runModal()
引用计数增加。但是,当crashyDelegate's
为真时,应用程序会以EXC_BAD_ACCESS
崩溃。如果useCrashyDelegate
为false,则会在与useCrashyDelegate
的调用相同的范围内实例化safeDelegate
,并将其分配给开放面板,并且没有openPanel.runModal()
。
这让我相信NSOpen EXC_BAD_ACCESS
anel并没有增加其代表的引用计数。这是预期的行为,还是这可能是一个错误?
答案 0 :(得分:1)
这让我相信NSOpenPanel没有增加其委托的引用计数。这是预期的行为,还是这可能是一个错误?
预计。检查属性的类型,您将看到它是assign
(Objective-C)或unsafe
(Swift),不保留强引用。这是Cocoa代表的常见设计模式。
HTH