class
实例,但是在类内省方面遇到了困难。以下是问题:
- 是否有Swift等价于Obj-C的
self.class
? - 是否有一种方法可以使用
NSClassFromString
的AnyClass
结果来实例化一个类? - 是否有一种方法可以从泛型参数
T
中严格获取AnyClass
或其他类型信息?(类似于C#的typeof(T)
语法)
class
实例,但是在类内省方面遇到了困难。self.class
?NSClassFromString
的AnyClass
结果来实例化一个类?T
中严格获取AnyClass
或其他类型信息?(类似于C#的typeof(T)
语法)首先,Swift中[NSString class]
的等价语句是.self
(请参见元类型文档,虽然它们非常简洁)。
实际上,NSString.class
根本不起作用!您必须使用NSString.self
。
let s = NSString.self
var str = s()
str = "asdf"
同样地,我尝试了一个迅速的类...
class MyClass {
}
let MyClassRef = MyClass.self
// ERROR :(
let my_obj = MyClassRef()
嗯... 这个错误信息说:
Playground执行失败:错误::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
,但在playground中,MyClass.Type
会出错。
.Type
或.Protocol
,例如:let myObject: MyObject.Type = MyObject.self
。 - Sulthanrequired
前面的 @
应该被删除。 - fujianjin6471以下是如何使用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混淆名称;这是至关重要的,因为否则我们不知道指定每个类的混淆字符串。
现在我们可以使用NSClassFromString
创建Zork类或Zilk类,因为我们知道我们可以将其类型定义为NSObject并且后续不会崩溃:
let aClass = NSClassFromString("Zork") as NSObject.Type
let anObject = aClass()
println(anObject) // "I am a Zork"
而且它是可逆的;println(NSStringFromClass(anObject.dynamicType))
也可以工作。
需要翻译的内容:
And it's reversible; println(NSStringFromClass(anObject.dynamicType))
also works.
if let aClass = NSClassFromString("Zork") as? NSObject.Type {
let anObject = aClass.init()
print(anObject) // "I am a Zork"
print(NSStringFromClass(type(of:anObject))) // Zork
}
@objc(ClassName)
这一部分。我知道@objc
属性,但不知道你还可以提示类名。 - Erikas! NSObject.Type
,在第二行中添加 aClass.init()
。 - Kaji如果我正确阅读文档的话,假设您正在处理实例并且想返回与您获得的对象相同类型的新实例,并且该类型可以使用init()构造,则可以执行以下操作:
let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()
我用 String 快速测试了它:
let someType = "Fooo".dynamicType
let emptyString = someType()
let threeString = someType("Three")
运作良好。
dynamicType
在那里的表现和我预期的一样。然而,我一直无法比较类型。真正大的用处是在泛型中,所以我可以有类似 Generic<T>
的东西,在内部使用 if T is Double {...}
。不幸的是,这似乎是不可能的。 - Erikdefault
关键字的Defaultable
协议,并为诸如String
和Int
之类的类型添加适当的扩展。通过添加T:Defaultable
的泛型约束,我可以检查传递的参数是否为T.default()
。 - Erikvalue is String.default()
...等操作,而你最终只会执行 value is String
。 - Erik在Swift 3中
object.dynamicType
已被弃用。
请改用:
type(of:object)
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
注意: 请注意它也适用于对象可能扩展或不扩展的协议
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()
base
file
display
base
folder
display
var x:NamedItem.Type
,如果我将其分配为x = Folder.Type
,则x()
返回一个新的NamedItem
,而不是Folder
。这使得该技术对许多应用程序无用。我认为这是一个错误。 - phatmann终于让某些东西工作了。虽然有点懒,但即使使用NSClassFromString()方法也无法为我解决问题...
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")
然后,“makeFoo”包含一个Foo实例。
缺点是你的类必须派生自FactoryObject,并且它们必须具有Obj-C +initialize方法,以便通过全局函数“mapClass”将您的类自动插入类映射中。
self.class
会变成self.dynamicType.self
,我相信这样表达更加通俗易懂,但不改变原意。 - Filip Hermansself.dynamicType.foo()
。 - user246672