code

빠른 언어 NSClassFromString

starcafe 2023. 9. 5. 20:40
반응형

빠른 언어 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!

다음 문서를 확인합니다.

https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/ #//apple_ref/c/func/NSClassFromString

동적으로 객체를 인스턴스화할 수 있었습니다.

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

반응형