스위프트 언어 NSClassFromString
스위프트 언어로 반영 하는 방법은 무엇입니까?
클래스를 인스턴스화하는 방법
[[NSClassFromString(@"Foo") alloc] init];
덜 해키 솔루션 : https://stackoverflow.com/a/32265287/308315
Swift 클래스는 이제 네임 스페이스가 지정되므로 "MyViewController"대신 "AppName.MyViewController"가됩니다.
XCode6-beta 6/7부터 사용되지 않음
XCode6-beta 3을 사용하여 개발 된 솔루션
Edwin Vermeer의 답변 덕분에 다음과 같이 Swift 클래스를 Obj-C 클래스로 인스턴스화하는 무언가를 만들 수있었습니다.
// swift file
// extend the NSObject class
extension NSObject {
// create a static method to get a swift class for a string name
class func swiftClassFromString(className: String) -> AnyClass! {
// get the project name
if var appName: String? = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as String? {
// generate the full name of your class (take a look into your "YourProject-swift.h" file)
let classStringName = "_TtC\(appName!.utf16count)\(appName)\(countElements(className))\(className)"
// return the class!
return NSClassFromString(classStringName)
}
return nil;
}
}
// obj-c file
#import "YourProject-Swift.h"
- (void)aMethod {
Class class = NSClassFromString(key);
if (!class)
class = [NSObject swiftClassFromString:(key)];
// do something with the class
}
편집하다
순수 obj-c에서도 수행 할 수 있습니다.
- (Class)swiftClassFromString:(NSString *)className {
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *classStringName = [NSString stringWithFormat:@"_TtC%d%@%d%@", appName.length, appName, className.length, className];
return NSClassFromString(classStringName);
}
나는 이것이 누군가를 도울 수 있기를 바랍니다!
이것은 클래스 이름으로 파생 된 UIViewController를 초기화하는 방법입니다.
var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass()
자세한 정보는 여기
iOS 9에서
var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass.init()
당신은 @objc(SwiftClassName)
당신의 신속한 클래스 위에 두어야합니다 .
처럼:
@objc(SubClass)
class SubClass: SuperClass {...}
업데이트 : 베타 6부터 NSStringFromClass는 번들 이름과 점으로 구분 된 클래스 이름을 반환합니다. 따라서 MyApp.MyClass와 같은 것입니다.
Swift 클래스는 다음 부분으로 구성된 구성된 내부 이름을 갖습니다.
- _TtC로 시작합니다.
- 애플리케이션 이름의 길이에 해당하는 숫자,
- 애플리케이션 이름,
- 수업 이름의 길이에 해당하는 숫자가 표시됩니다.
- 수업 이름이 이어집니다.
따라서 클래스 이름은 _TtC5MyApp7MyClass와 같습니다.
다음을 실행하여이 이름을 문자열로 가져올 수 있습니다.
var classString = NSStringFromClass(self.dynamicType)
업데이트 Swift 3에서는 다음과 같이 변경되었습니다.
var classString = NSStringFromClass(type(of: self))
해당 문자열을 사용하여 다음을 실행하여 Swift 클래스의 인스턴스를 만들 수 있습니다.
var anyobjectype : AnyObject.Type = NSClassFromString(classString)
var nsobjectype : NSObject.Type = anyobjectype as NSObject.Type
var rec: AnyObject = nsobjectype()
거의 똑같아
func NSClassFromString(_ aClassName: String!) -> AnyClass!
이 문서를 확인하십시오.
객체를 동적으로 인스턴스화 할 수있었습니다.
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!")
}
(Obj-C를 사용하지 않고) AnyClass
에서 만드는 방법을 찾지 못했습니다 String
. 나는 기본적으로 유형 시스템을 깨뜨리기 때문에 당신이 그렇게하는 것을 원하지 않는다고 생각합니다.
swift2의 경우이 작업을 더 빠르게 수행 할 수있는 매우 간단한 확장 기능을 만들었습니다. https://github.com/damienromito/NSObject-FromClassName
extension NSObject {
class func fromClassName(className : String) -> NSObject {
let className = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String + "." + className
let aClass = NSClassFromString(className) as! UIViewController.Type
return aClass.init()
}
}
제 경우에는 원하는 ViewController를로드하기 위해 이렇게합니다.
override func viewDidLoad() {
super.viewDidLoad()
let controllers = ["SettingsViewController", "ProfileViewController", "PlayerViewController"]
self.presentController(controllers.firstObject as! String)
}
func presentController(controllerName : String){
let nav = UINavigationController(rootViewController: NSObject.fromClassName(controllerName) as! UIViewController )
nav.navigationBar.translucent = false
self.navigationController?.presentViewController(nav, animated: true, completion: nil)
}
인스턴스화하려는 클래스의 이름을 얻을 수 있습니다. 그런 다음 Edwins 답변 을 사용 하여 클래스의 새 개체를 인스턴스화 할 수 있습니다 .
베타 6 _stdlib_getTypeName
부터는 변수의 유형 이름이 변경됩니다. 이것을 빈 플레이 그라운드에 붙여 넣으십시오.
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
출력은 다음과 같습니다.
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swick의 블로그 항목은 다음 문자열을 해독하는 데 도움이됩니다. http://www.eswick.com/2014/06/inside-swift/
예를 들어 _TtSi
Swift의 내부 Int
유형을 나타냅니다 .
Swift 2.0에서 (Xcode 7.01에서 테스트 됨) _20150930
let vcName = "HomeTableViewController"
let ns = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
// Convert string to class
let anyobjecType: AnyObject.Type = NSClassFromString(ns + "." + vcName)!
if anyobjecType is UIViewController.Type {
// vc is instance
let vc = (anyobjecType as! UIViewController.Type).init()
print(vc)
}
xcode 7 베타 5 :
class MyClass {
required init() { print("Hi!") }
}
if let classObject = NSClassFromString("YOURAPPNAME.MyClass") as? MyClass.Type {
let object = classObject.init()
}
클래스의 문자열
let classString = NSStringFromClass(TestViewController.self)
또는
let classString = NSStringFromClass(TestViewController.classForCoder())
문자열에서 UIViewController 클래스를 초기화합니다.
let vcClass = NSClassFromString(classString) as! UIViewController.Type
let viewController = vcClass.init()
적어도 현재 베타 (2)에서는 할 수 없다고 말하는 것이 옳다고 생각합니다. 바라건대 이것은 향후 버전에서 변경 될 것입니다.
를 사용 NSClassFromString
하여 유형의 변수를 가져올 수 AnyClass
있지만 Swift에서 인스턴스화 할 방법이없는 것 같습니다. Objective C에 대한 브리지를 사용하여 거기에서 수행 하거나-만약 그것이 당신의 경우에 작동한다면- 스위치 문을 사용하는 것으로 돌아갈 수 있습니다.
분명히, 클래스 이름이 런타임에만 알려지면 Swift에서 객체를 인스턴스화하는 것이 (더 이상) 불가능합니다. Objective-C 래퍼는 NSObject의 하위 클래스에 대해 가능합니다.
최소한 Objective-C 래퍼없이 런타임에 주어진 다른 객체와 동일한 클래스의 객체를 인스턴스화 할 수 있습니다 (xCode 버전 6.2-6C107a 사용).
class Test : NSObject {}
var test1 = Test()
var test2 = test1.dynamicType.alloc()
Swift 2.0 (Xcode 7의 beta2에서 테스트 됨)에서는 다음과 같이 작동합니다.
protocol Init {
init()
}
var type = NSClassFromString(className) as? Init.Type
let obj = type!.init()
에서 오는 유형 NSClassFromString
은이 초기화 프로토콜을 구현해야합니다.
나는 그것이 분명하다고 생각하고, className
기본적으로 "Foo"가 아닌 클래스의 Obj-C 런타임 이름을 포함하는 문자열이지만이 토론은 IMHO가 귀하의 질문의 주요 주제가 아닙니다.
기본적으로 모든 Swift 클래스는 init
메소드를 구현하지 않기 때문에이 프로토콜이 필요합니다 .
올바른 주문은 ...
func newForName<T:NSObject>(p:String) -> T? {
var result:T? = nil
if let k:AnyClass = NSClassFromString(p) {
result = (k as! T).dynamicType.init()
}
return result
}
... 여기서 "p"는 "packaged"를 의미합니다. 이는 별개의 문제입니다.
그러나 AnyClass에서 T 로의 중요한 캐스트는 현재 컴파일러 크래시를 유발하므로 그 동안 k 초기화를 별도의 클로저로 버스트해야합니다.
다른 타겟을 사용하는데이 경우 신속한 클래스를 찾을 수 없습니다. CFBundleName을 CFBundleExecutable로 바꿔야합니다. 또한 경고를 수정했습니다.
- (Class)swiftClassFromString:(NSString *)className {
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"];
NSString *classStringName = [NSString stringWithFormat:@"_TtC%lu%@%lu%@", (unsigned long)appName.length, appName, (unsigned long)className.length, className];
return NSClassFromString(classStringName);
}
이 카테고리를 Swift 3에 사용하고 있습니다.
//
// String+AnyClass.swift
// Adminer
//
// Created by Ondrej Rafaj on 14/07/2017.
// Copyright © 2017 manGoweb UK Ltd. All rights reserved.
//
import Foundation
extension String {
func convertToClass<T>() -> T.Type? {
return StringClassConverter<T>.convert(string: self)
}
}
class StringClassConverter<T> {
static func convert(string className: String) -> T.Type? {
guard let nameSpace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String else {
return nil
}
guard let aClass: T.Type = NSClassFromString("\(nameSpace).\(className)") as? T.Type else {
return nil
}
return aClass
}
}
사용은 다음과 같습니다.
func getViewController(fromString: String) -> UIViewController? {
guard let viewController: UIViewController.Type = "MyViewController".converToClass() else {
return nil
}
return viewController.init()
}
Also in Swift 2.0 (possibly before?) You can access the type directly with the dynamicType
property
i.e.
class User {
required init() { // class must have an explicit required init()
}
var name: String = ""
}
let aUser = User()
aUser.name = "Tom"
print(aUser)
let bUser = aUser.dynamicType.init()
print(bUser)
Output
aUser: User = {
name = "Tom"
}
bUser: User = {
name = ""
}
Works for my use case
Try this.
let className: String = String(ControllerName.classForCoder())
print(className)
I have implemented like this,
if let ImplementationClass: NSObject.Type = NSClassFromString(className) as? NSObject.Type{
ImplementationClass.init()
}
Isn't the solution as simple as this?
// Given the app/framework/module named 'MyApp'
let className = String(reflecting: MyClass.self)
// className = "MyApp.MyClass"
A page jump example shown here, the hope can help you!
let vc:UIViewController = (NSClassFromString("SwiftAutoCellHeight."+type) as! UIViewController.Type).init()
self.navigationController?.pushViewController(vc, animated: true)
// Click the Table response
tableView.deselectRow(at: indexPath, animated: true)
let sectionModel = models[(indexPath as NSIndexPath).section]
var className = sectionModel.rowsTargetControlerNames[(indexPath as NSIndexPath).row]
className = "GTMRefreshDemo.\(className)"
if let cls = NSClassFromString(className) as? UIViewController.Type {
let dvc = cls.init()
self.navigationController?.pushViewController(dvc, animated: true)
}
Swift3+
extension String {
var `class`: AnyClass? {
guard
let dict = Bundle.main.infoDictionary,
var appName = dict["CFBundleName"] as? String
else { return nil }
appName.replacingOccurrences(of: " ", with: "_")
let className = appName + "." + self
return NSClassFromString(className)
}
}
Here is a good example:
class EPRocks {
@require init() { }
}
class EPAwesome : EPRocks {
func awesome() -> String { return "Yes"; }
}
var epawesome = EPAwesome.self();
print(epawesome.awesome);
참고URL : https://stackoverflow.com/questions/24030814/swift-language-nsclassfromstring
'programing' 카테고리의 다른 글
OS X의 Bash 스크립트 절대 경로 (0) | 2020.10.04 |
---|---|
파일 선택시 이벤트를 발생시키는 방법 (0) | 2020.10.04 |
하나의 Sublime Text 3 창에 둘 이상의 폴더 / 프로젝트 (0) | 2020.10.04 |
JavaScript 함수 앨리어싱이 작동하지 않는 것 같습니다. (0) | 2020.10.04 |
SurfaceView를 투명하게 만드는 방법 (0) | 2020.10.04 |