如何在Swift中成功编译NSClassFromString

时间:2019-02-27 09:53:38

标签: swift macos cocoa

下面的代码无法成功编译。我还附上了截图以供参考!

map(lambda x: (x[0], x[1]), cornerWithEdges)

screenshot for reference

2 个答案:

答案 0 :(得分:0)

您可以使用

进行测试
Map

if viewInArray.isKind(of: MyClass) { ... } 

但是我认为您不能将Swift转换为在编译时不可用的类。无论如何,您将无法直接调用其任何方法。您可以将其强制转换为某个if viewInArray.isMember(of: MyClass) { ... } // strict class match 子类,然后向其发送任意(未在编译时定义)消息。

答案 1 :(得分:0)

此处的主要错误是您无法asis检查动态类型。您需要具有在编译时已知的静态类型才能使用它。如要说明的那样,您需要在基础NSObject上使用isKind(of:)isMember(of:)。我建议这样做的方法如下:

func firstXibViewOfClass(named classNameString: String) -> NSView? {
    // Create an AnyClass object
    guard let projectName = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String,
        let myClass = NSClassFromString(projectName + "." + classNameString)
        else {
            return nil
    }

    // Load the nib
    var topLevelObjects: NSArray?
    Bundle.main.loadNibNamed(classNameString, owner: nil, topLevelObjects: &topLevelObjects)

    // Convert it to NSObjects (since they all are going to be)
    guard let nsObjectArray = topLevelObjects as? [NSObject] else { return nil }

    // Find the first matching view and return it as an NSView if possible
    return nsObjectArray.first(where: {
        $0.isKind(of: myClass)  // Or isMember(of:) if you want to be strict
    }) as? NSView
}

但是,如果不需要包含子类,则可能只想直接检查类名。这摆脱了所有AnyClass的东西:

func firstXibViewOfClass(named classNameString: String) -> NSView? {
    // Load the nib
    var topLevelObjects: NSArray?
    Bundle.main.loadNibNamed(classNameString, owner: nil, topLevelObjects: &topLevelObjects)

    // Convert it to NSObjects (since they all are going to be)
    guard let nsObjectArray = topLevelObjects as? [NSObject] else { return nil }

    // Find the first matching view and return it as an NSView if possible
    return nsObjectArray.first(where: { $0.className == classNameString }) as? NSView
}

您当然可以只返回AnyObject?,但是方法的名称表明您希望它是一个视图,因此应强制执行该方法或重命名该方法。