신속한 클래스 내부 검사 및 제네릭
class
제네릭을 사용하여 인스턴스 기반 유형 을 동적으로 만들려고 하지만 클래스 내부 검사에 어려움이 있습니다.
질문은 다음과 같습니다.
- Obj-C와 같은 Swift가
self.class
있습니까? - 의
AnyClass
결과를 사용하여 클래스를 인스턴스화하는 방법이NSClassFromString
있습니까? AnyClass
일반 매개 변수에서 정보를 엄격하게 얻 거나 입력 하는 방법이T
있습니까? (C #의typeof(T)
구문과 유사 )
글쎄, 스위프트와 동등한 [NSString class]
것은 .self
( Metatype docs 는 꽤 얇지 만 참조하십시오 ).
사실, NSString.class
심지어 작동하지 않습니다! 를 사용해야 NSString.self
합니다.
let s = NSString.self
var str = s()
str = "asdf"
마찬가지로, 빠른 수업으로 시도했습니다 ...
class MyClass {
}
let MyClassRef = MyClass.self
// ERROR :(
let my_obj = MyClassRef()
흠 ... 오류는 말합니다 :
놀이터 실행 실패 : 오류 : : 16 : 1 : 오류 : 메타 타입 값으로 클래스 유형 'X'의 객체를 구성하려면 '@required'이니셜 라이저가 필요합니다
Y().me() ^ <REPL>:3:7: note: selected implicit initializer with type '()' class X { ^
이것이 무엇을 의미하는지 알아내는 데 시간이 걸렸습니다… @required init()
class X {
func me() {
println("asdf")
}
required init () {
}
}
let Y = X.self
// prints "asdf"
Y().me()
일부 문서는 이것을이라고 .Type
하지만 MyClass.Type
놀이터에서 오류가 발생합니다.
사용 방법은 다음과 같습니다 NSClassFromString
. 당신은 당신이 끝내게 될 것의 수퍼 클래스를 알아야합니다. 다음은 자신을 설명하는 방법을 알고있는 수퍼 클래스-서브 클래스 쌍입니다 println
.
@objc(Zilk) class Zilk : NSObject {
override var description : String {return "I am a Zilk"}
}
@objc(Zork) class Zork : Zilk {
override var description : String {return "I am a Zork"}
}
@obj
이 클래스의 Objective-C munged 이름을 지시하기 위해 특수 구문을 사용하십시오 . 그렇지 않으면 각 클래스를 지정하는 녹은 문자열을 알지 못하기 때문에 중요합니다.
Now we can use NSClassFromString
to make the Zork class or the Zilk class, because we know we can type it as an NSObject and not crash later:
let aClass = NSClassFromString("Zork") as NSObject.Type
let anObject = aClass()
println(anObject) // "I am a Zork"
And it's reversible; println(NSStringFromClass(anObject.dynamicType))
also works.
If I'm reading the documentation right, if you deal with instances and e.g. want to return a new instance of the same Type than the object you have been given and the Type can be constructed with an init() you can do:
let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()
I quickly tested it with String:
let someType = "Fooo".dynamicType
let emptyString = someType()
let threeString = someType("Three")
which worked fine.
In swift 3
object.dynamicType
is deprecated.
Instead use:
type(of:object)
Swift implementation of comparing types
protocol Decoratable{}
class A:Decoratable{}
class B:Decoratable{}
let object:AnyObject = A()
object.dynamicType is A.Type//true
object.dynamicType is B.Type//false
object.dynamicType is Decoratable.Type//true
NOTE: Notice that it also works with protocols the object may or may not extend
Finally got something to work. Its a bit lazy but even the NSClassFromString() route did not work for me...
import Foundation
var classMap = Dictionary<String, AnyObject>()
func mapClass(name: String, constructor: AnyObject) -> ()
{
classMap[name] = constructor;
}
class Factory
{
class func create(className: String) -> AnyObject?
{
var something : AnyObject?
var template : FactoryObject? = classMap[className] as? FactoryObject
if (template)
{
let somethingElse : FactoryObject = template!.dynamicType()
return somethingElse
}
return nil
}
}
import ObjectiveC
class FactoryObject : NSObject
{
@required init() {}
//...
}
class Foo : FactoryObject
{
class override func initialize()
{
mapClass("LocalData", LocalData())
}
init () { super.init() }
}
var makeFoo : AnyObject? = Factory.create("Foo")
and bingo, "makeFoo" contains a Foo instance.
The downside is your classes must derrive from FactoryObject and they MUST have the Obj-C +initialize method so your class gets automagically inserted in the class map by global function "mapClass".
Here is another example showing class hierarchy implementation, similar to accepted answer, updated for the first release of Swift.
class NamedItem : NSObject {
func display() {
println("display")
}
required override init() {
super.init()
println("base")
}
}
class File : NamedItem {
required init() {
super.init()
println("folder")
}
}
class Folder : NamedItem {
required init() {
super.init()
println("file")
}
}
let y = Folder.self
y().display()
let z = File.self
z().display()
Prints this result:
base
file
display
base
folder
display
참고URL : https://stackoverflow.com/questions/24049673/swift-class-introspection-generics
'development' 카테고리의 다른 글
TDD 대 유닛 테스트 (0) | 2020.07.19 |
---|---|
DLL 함수를 보는 방법? (0) | 2020.07.19 |
xxx의 사본이 모듈 트리에서 제거되었지만 여전히 활성입니다. (0) | 2020.07.19 |
이 문자열 확장 메소드가 예외를 발생시키지 않는 이유는 무엇입니까? (0) | 2020.07.19 |
.NET Core 및 ASP.NET Core (0) | 2020.07.19 |