Как успешно скомпилировать NSClassFromString в Swift - PullRequest
0 голосов
/ 27 февраля 2019

Код ниже не может скомпилироваться успешно. Я также приложил скриншот для справки!

func getXibViewWithClassNameString(classNameString:String)->AnyObject?{
    let projectName = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String
    let MyClass:AnyClass = NSClassFromString(projectName! + "." + classNameString)!

    var viewArray:NSArray?
    var xibView:AnyClass?
    Bundle.main.loadNibNamed(classNameString, owner: nil, topLevelObjects: &viewArray)
    for viewInArray in viewArray ?? [] {
        if (viewInArray is MyClass){
        xibView = viewInArray as MyClass
        }
    }
    return xibView
}

скриншот для справки

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Ключевая ошибка здесь в том, что вы не можете as или is проверить динамический тип.Вам нужно иметь статический тип, известный во время компиляции, чтобы использовать это.Как отмечает Pointum, вам нужно использовать isKind(of:) или isMember(of:) для базового NSObject.Вот как я бы порекомендовал сделать это:

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?, но название метода предполагает, что вы ожидаете, что это будет представление, поэтому вы должны принудительно применить это илипереименуйте метод.

0 голосов
/ 27 февраля 2019

Вы можете проверить с помощью

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

или

if viewInArray.isMember(of: MyClass) { ... } // strict class match

Но я не думаю, что вы можете привести к классу, который не доступен во время компиляции в Swift.В любом случае, вы не сможете напрямую вызвать ни один из его методов.Вы можете привести его к некоторому подклассу NSObject и отправить ему произвольные (не определенные во время компиляции) сообщения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...