빠른 언어 NSClassFromString
어떻게 하면 빠른 언어로 반영할 수 있을까요?
클래스를 인스턴스화하는 방법
[[NSClassFromString(@"Foo") alloc] init];
꼭 넣어야 합니다.@objc(SwiftClassName)
당신의 급 이상의.
예:
@objc(SubClass)
class SubClass: SuperClass {...}
이것은 초기에 클래스 이름별로 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()
덜 진부한 솔루션: https://stackoverflow.com/a/32265287/308315
Swift 클래스는 이제 네임스페이스로 지정되므로 "MyViewController" 대신 "AppName"이 됩니다.내 보기 컨트롤러"
XCode 6-beta 6/7 이후 사용되지 않음
XCode6-beta3를 사용하여 개발한 솔루션
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);
}
이것이 누군가에게 도움이 되기를 바랍니다!
업데이트: 베타 6 NSStringFromClass로 시작하면 번들 이름과 클래스 이름을 점으로 구분하여 반환합니다.그래서 마이앱과 같은 것이 될 것입니다.나의 수업
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!")
}
▁i습했▁a▁havent▁found'를 만드는 방법을 찾지 못했습니다.AnyClass
에서.String
(Obj-C를 사용하지 않음).제 생각에 그들은 당신이 그렇게 하는 것을 원하지 않는 것 같습니다. 왜냐하면 그것은 기본적으로 유형 시스템을 파괴하기 때문입니다.
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()
}
}
이 경우 원하는 View 컨트롤러를 로드하기 위해 다음 작업을 수행합니다.
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 베타 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()
저는 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()
}
적어도 현재 베타(2)로는 할 수 없다고 말하는 것이 맞는 것 같습니다.바라건대 이것이 미래 버전에서 변화할 것입니다.
사용할 수 있습니다.NSClassFromString
유형의 AnyClass
하지만 스위프트에서는 그것을 예시할 방법이 없는 것 같습니다.목표 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의 베타2에서 테스트됨)에서는 다음과 같이 작동합니다.
protocol Init {
init()
}
var type = NSClassFromString(className) as? Init.Type
let obj = type!.init()
확실한 유형은 다음과 같습니다.NSClassFromString
이 init 프로토콜을 구현해야 합니다.
분명하기를 합니다, 분할겁니다.className
클래스의 Obj-C 런타임 이름을 포함하는 문자열로, 기본적으로 "Foo"가 아니지만, 이 토론은 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"는 "discovery"를 의미합니다. 즉, 별개의 문제입니다.
그러나 AnyClass에서 T로의 임계 캐스트는 현재 컴파일러 충돌을 유발하므로 그 동안 k의 초기화를 별도의 폐쇄로 중단해야 하며, 이는 정상적으로 컴파일됩니다.
저는 다른 타겟을 사용하고 있으며, 이 경우 swift 클래스를 찾을 수 없습니다.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);
}
해결책은 이렇게 간단하지 않습니까?
// Given the app/framework/module named 'MyApp'
let className = String(reflecting: MyClass.self)
// className = "MyApp.MyClass"
Swift 2.0에서도 마찬가지입니다(아마도 이전에?).를 사용하여 직접 유형에 액세스할 수 있습니다.dynamicType
소유물
예.
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)
산출량
aUser: User = {
name = "Tom"
}
bUser: User = {
name = ""
}
내 사용 사례에 적합
이거 먹어봐요.
let className: String = String(ControllerName.classForCoder())
print(className)
저는 이렇게 구현했습니다.
if let ImplementationClass: NSObject.Type = NSClassFromString(className) as? NSObject.Type{
ImplementationClass.init()
}
@Ondrej Rafaj 덕분에 사용하기 쉬운 Swift 5.
소스 코드:
extension String { fileprivate func convertToClass<T>() -> T.Type? { return StringClassConverter<T>.convert(string: self) } var controller: UIViewController?{ guard let viewController: UIViewController.Type = convertToClass() else { return nil } return viewController.init() } } class StringClassConverter<T> { fileprivate static func convert(string className: String) -> T.Type? { guard let nameSpace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String, let aClass = NSClassFromString("\(nameSpace).\(className)") as? T.Type else { return nil } return aClass } }
다음과 같은 통화:
guard let ctrl = "ViewCtrl".controller else { return } // ctrl do sth
여기에 표시된 페이지 점프의 예는 희망이 여러분을 도울 수 있습니다!
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)
}
스위프트3+
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)
}
}
다음은 좋은 예입니다.
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
'code' 카테고리의 다른 글
Spring Boot REST API에서 시간 초과를 설정하는 방법은 무엇입니까? (0) | 2023.09.05 |
---|---|
도커 컨테이너에 셸링한 후 파일을 편집하려면 어떻게 해야 합니까? (0) | 2023.09.05 |
10분마다 vba를 실행시키는 방법은? (0) | 2023.09.05 |
JavaScript를 사용하여 특정 지연 후 스크립트 실행 (0) | 2023.08.26 |
sql 쿼리를 사용하여 문자열을 int로 변환 (0) | 2023.08.26 |