我有一个名为 User()
的课程class User {
var name: String?
var email: String?
var id: String?
var identification_number: String?
var phone_number: NSMutableArray?
var user_group: String?
var date: NSDate?
}
我希望得到类中的所有变量及其各自的值。我想在这种情况下使用镜像。
func updateProfile(user: User) {
let mirror = Mirror(reflecting: user)
for child in mirror.children {
print("\(child.label!), \(child.value)")
}
}
我的问题是,如何将child.value
转换为任何其他数据类型,比如String
?
我只是发现child.value属于 Protocol 'Any'
答案 0 :(得分:3)
child.value
具有Any
类型。从Any
转换为可选项会带来一些问题,幸运的是Sandy Chapman在this post中提供了一个非常好的解决方案。
使用他的功能,代码看起来像这样:
func castToOptional<T>(x: Any) -> T? {
return Mirror(reflecting: x).descendant("Some") as? T
}
func updateProfile(user: User) {
let mirror = Mirror(reflecting: user)
for child in mirror.children {
print("\(child.label!), \(child.value)")
if let stringVal = castToOptional(child.value) as String? {
print("Unwrapped a string: \(stringVal)")
} else if let stringVal = child.value as? String {
print("Found a non-optional string: \(stringVal)")
}
}
}
因此,如果您正在寻找字符串,则需要查找可选字符串和非可选字符串。这适用于您需要检查的所有类型。
答案 1 :(得分:2)
创建用于扩展Optional<Any>
类型的协议以返回其非可选值:
private protocol AnyOptional {
var objectValue: Any? { get }
}
extension Optional: AnyOptional {
var objectValue: Any? {
switch self {
case .None:
return nil
case .Some(_):
return self! as Any
}
}
}
此后,您可以使用AnyOptional
协议作为类型,并将Any?
个对象转换为AnyOptional
,然后允许我们使用.objectValue
AnyOptional
属性}}
class User {
var name: String?
var email: String?
var id: String = "Default ID" // Lets try also with one non-optional
var identification_number: String?
var phone_number: NSMutableArray?
var user_group: String?
var date: NSDate?
}
var myUser = User()
myUser.name = "John"
myUser.phone_number = ["+44", "701 23 45 67"]
func updateProfile(user: User) {
let mirror = Mirror(reflecting: user)
for child in mirror.children {
let value : Any = (child.value as? AnyOptional)?.objectValue ?? child.value
switch(value) {
case let obj as String: print("String item: User.\(child.label!) = " + obj)
case let obj as NSMutableArray: print("NSMutableArray item: User.\(child.label!) = \(obj)")
case let obj as NSDate: print("NSDate item: User.\(child.label!) = \(obj)")
case _ : print("Non-initialized optional item: User.\(child.label!) = \(value)")
}
}
}
产生以下输出
updateProfile(myUser)
/*
String item: User.name = John
Non-initialized optional item: User.email = nil
String item: User.id = Default ID
Non-initialized optional item: User.identification_number = nil
NSMutableArray item: User.phone_number = (
"+44",
"701 23 45 67"
)
Non-initialized optional item: User.user_group = nil
Non-initialized optional item: User.date = nil */
使用此解决方案的好处是它将解开&#34;展开&#34;可选的非零值child.value
(不包含"Optional(...)"
填充)以及作为不可选的child.value
的值,无需单独打开&#34;展开&#34;对于这两个案件。在上面的switch
情况下,您可以处理需要使用的User
对象的任何非零属性,而不仅仅是String
,而是User
中的任何类型obj
1}}类。 switch
案例中的nil
属性将属于您的类的每个非零属性的非可选类型。默认情况对应于值为master
(未分配)的选项。