Apple将NSPathControl更改为与Yosemite中的NSPathControlItem一起使用。
但是从我所在的地方来看,这些新课程根本不起作用。 我试图在我的数据结构中显示自定义路径,但我有一个常规文件路径的类似问题。是我还是Apple?
这是我的代码:
第一个代码段工作,它将显示一个路径。但这就是一切有效。
//MARK: notifications
func selectionDidChange(notification : NSNotification)
{
if let item = notification.object as? Group
{
//get "path" components
var components : [String] = [item.title ?? "a"]
var ancestor : Group? = item.parent
while (ancestor != nil)
{
components.append(ancestor?.title ?? "b")
ancestor = ancestor?.parent
}
components.append("")
//convert to url
let path = ("MyScheme:/" + "/".join(components.reverse()))
pathControl?.URL = NSURL(string: path.stringByAddingPe
}
}
单击路径的任何部分以尝试从NSPathControlItem中获取任何属性根本不起作用。一切都归零。
@IBAction func select(sender : AnyObject)
{
println(sender.clickedPathItem??.title)
println(sender.clickedPathItem??.URL)
}
如果我尝试使用NSPathControlItem构建路径,则无法设置任何属性(title,url)。
pathComponent.URL = NSURL(string: path.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)
//let url : NSURL? = NSURL(string: "/")
//let path = NSURL(fileURLWithPath: "/")
//pathComponent.URL = path as NSURL
pathComponent.attributedTitle = NSAttributedString(string: "/atttributes")
self.pathControl?.pathItems = [pathComponent]
println(pathComponent.description)
NSPathControlItem也不应该是子类。
这里发生了什么?
修改
据我所知,NSPathControlItem存在问题。 用于创建NSPathControlItem的辅助函数。
func pathItem(title: String, imageName: String) -> NSPathControlItem
{
let item = NSPathControlItem()
item.title = title
item.image = NSImage(named: imageName)
return item
}
用于创建NSPathControlItem并打印出标题的测试函数。
var pathItems : [NSPathControlItem] = []
for title in ["a","b","c"]
{
pathItems.append(self.pathItem(title, imageName: NSImageNameFolder))
}
for item in pathItems
{
println(item.title)
}
预期输出是三行a,b和c。我没有,b,没有。
如果直接在NSPathControl上设置pathItems,它将起作用。
self.pathControl?.pathItems = [
self.pathItem("a", imageName: NSImageNameFolder),
self.pathItem("b", imageName: NSImageNameFolder),
self.pathItem("c", imageName: NSImageNameFolder)]
但是,如果间接设置pathItems,那么一切都会变成地狱。
self.pathControl?.pathItems = pathItems //array of NSPathControl (see above)
修改2
我再看看这个。我在pathItem函数中配置NSPathControlItem。我在这里设置标题。如果我设置了attributesTitle,则没有任何区别。使用lldb检查项目会显示正确的(属性)标题值。
但是当我将NSPathControlItem的数组分配给NSPathControl时,标题的值为“”,而attributesTitle是未初始化的。
答案 0 :(得分:7)
NSPathControlItem
严重受损。从10.11.3开始,它包含以下方法,由Hopper反编译:
int -[NSPathControlItem release](int arg0) {
[arg0->_secretCell autorelease];
objc_assign_ivar(0x0, arg0, *_OBJC_IVAR_$_NSPathControlItem._secretCell);
rax = [[arg0 super] release];
return rax;
}
这显然应该是标准dealloc
覆盖,它会释放ivar,将其归零,并调用super。但相反,由于某些未知原因可能与非法毒品相关,它是release
覆盖。这意味着即使在一些无害的操作过程中释放其中一个物体的那一刻,它也会自我毁灭并变得无法使用。
我创建了一些代码来使用运行时来消除错误的release
覆盖并替换为正确的dealloc
覆盖。这几乎没有经过测试,使用风险由您自行承担:
extension NSPathControl {
class func fix() {
let itemClass = NSPathControlItem.self
let superclass: AnyClass = class_getSuperclass(itemClass)
let releaseSelector = Selector("release")
let releaseMethod = class_getInstanceMethod(itemClass, releaseSelector)
let superReleaseIMP = class_getMethodImplementation(superclass, releaseSelector)
if method_getImplementation(releaseMethod) != superReleaseIMP {
method_setImplementation(releaseMethod, superReleaseIMP)
let ivars = class_copyIvarList(itemClass, nil)
var offsets: [Int] = []
var cursor = ivars
while cursor.memory != nil {
let ivar = cursor.memory
if String.fromCString(ivar_getTypeEncoding(ivar))?.hasPrefix("@") == true {
offsets.append(ivar_getOffset(ivar))
}
cursor++
}
free(ivars)
let superDeallocIMP = class_getMethodImplementation(superclass, "dealloc")
let dealloc: @convention(block) UnsafeMutablePointer<Int8> -> Void = { obj in
for offset in offsets {
let ivarPtr = UnsafeMutablePointer<COpaquePointer>(obj + offset)
let unmanaged = Unmanaged<AnyObject>.fromOpaque(ivarPtr.memory)
unmanaged.release()
ivarPtr.memory = nil
}
typealias DeallocF = @convention(c) (UnsafeMutablePointer<Int8>, Selector) -> Void
let superDeallocF = unsafeBitCast(superDeallocIMP, DeallocF.self)
superDeallocF(obj, "dealloc")
}
let deallocIMP = imp_implementationWithBlock(unsafeBitCast(dealloc, AnyObject.self))
class_addMethod(itemClass, "dealloc", deallocIMP, "v@:")
}
}
}
答案 1 :(得分:1)
我认为它不仅充满了错误,而且还没有记录。 AppKit框架参考中缺少NSPathControlItem
的文档..很奇怪。
我得到与你相同的结果。使用sender.clickedPathComponentCell()
的替代方案对我来说也适用:
class ViewController: NSViewController {
@IBOutlet weak var pathControl: NSPathControl!
override func viewDidLoad() {
super.viewDidLoad()
pathControl.URL = NSURL(fileURLWithPath: "/System/Library/Fonts")
}
@IBAction func pathItemSelected(sender: NSPathControl) {
if let cell = sender.clickedPathComponentCell() {
println(cell.URL)
}
}
}
这样可以正确打印我点击的部分路径。