#ios #xcode #ios7 #xcode5 #swift
#iOS #xcode #ios7 #xcode5 #swift
Вопрос:
Следующий код выводится, nil
несмотря ListCell
на то, что это допустимый класс.
var lCellClass : AnyClass! = NSClassFromString("ListCell");
println(lCellClass);
В документах говорится, что метод возвращает
Объект класса с именем aClassName или
nil
, если в данный момент не загружен класс с таким именем. Если имя_акласса равноnil
, возвращаетсяnil
.
Я также пытался получить NSClassFromString()
от текущего viewcontroller, который загружен, но все равно получаю nil
В чем может быть проблема?
Обновление: Даже пытаясь сделать это NSClassFromString("Array")
, я все еще получаю nil
Комментарии:
1. «Даже пытаясь сделать это, NSClassFromString(«Массив») Я все еще получаю nil» Массив<T> — это структура, а не класс.
Ответ №1:
NSClassFromString
Функция работает для (чистых и производных от Objective-C) классов swift, но только если вы используете полное имя.
Например, в модуле, вызываемом MyApp
с помощью чистого класса swift, называемого Person
:
let personClass: AnyClass? = NSClassFromString("MyApp.Person")
Имя модуля определяется параметром сборки «Product Module Name» ( PRODUCT_MODULE_NAME
), обычно тем же именем, что и ваша цель (с некоторой нормализацией, применяемой, например, для удаления пробелов).
Это нетипично, но если класс, который вы загружаете, находится в текущем модуле, и вы не знаете имени модуля во время компиляции, например, потому что код компилируется как часть нескольких целевых объектов, вы можете динамически искать имя пакета, которое обычно соответствует имени модуля:
let moduleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
let personClass: AnyClass? = NSClassFromString(moduleName "." "Person")
Однако я не рекомендую это, если вы действительно не знаете во время компиляции.
Смотрите Использование имен классов Swift с API Objective-C в разделе Использование Swift с Cocoa и Objective-C для получения дополнительной информации.
Комментарии:
1. Интересно! Спасибо за это.
2. И вот почему я так люблю!!
3. 1 Просто любопытно, задокументировано ли это где-нибудь подобным образом?
4. В настоящее время нет, пожалуйста, отправьте отчет об ошибке в документации swift по адресу bugreport.apple.com
5. В вашем примере «MyApp» было бы целевым именем, а не названием проекта. Таким образом, универсальный пример для «MyCustomClass» был бы чем-то вроде:
NSClassFromString(Bundle.main.infoDictionary!["CFBundleName"] as! String "." "MyCustomClass")
Ответ №2:
Также можно указать имя для символа в Objective-C, которое опускает пространство имен в objective C, используя аннотацию @objc. Если вы предпочитаете использовать имя без модуля, просто используйте то же имя класса:
@objc(Foobar)
class Foobar{
}
NSClassFromString(«Foobar») вернет класс Foobar.
Комментарии:
1. На самом деле, это самый релевантный ответ. Спасибо.
2. Вы не должны делать это только для того, чтобы печатать немного меньше при использовании
NSClassFromString
. Вы теряете все преимущества пространства имен. Вы не «определяете пространство имен класса swift», вы удаляете все пространство имен.3. Поддерживает ли objective C пространства имен сейчас?
4. Нет. Этого никогда не было и никогда не будет. Как только вы добавите их, вы получите быстрый и хрупкий способ метапрограммирования, используя рецепт JackLawrence.
Ответ №3:
Возможно, проблема в том, что ваш класс не расширен из NSObject. Поскольку по умолчанию swift не имеет суперкласса.
Ответ №4:
Например:
Просто используя UIViewController в качестве примера,
func getVc(from stringName: String) -> UIViewController? {
let appName = Bundle.main.infoDictionary!["CFBundleName"] as! String
guard let vc = NSClassFromString(appName "." stringName) as? UIViewController.Type else {
return nil
}
return vc.init()
}
Если имя вашего приложения содержит «-» или число, просто замените их на «_»