首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将Protocol<>任意转换为字符串(或其他)

将Protocol<>任意转换为字符串(或其他)
EN

Stack Overflow用户
提问于 2016-01-06 15:31:50
回答 2查看 326关注 0票数 3

我有一个名为User()的类

代码语言:javascript
运行
复制
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?
}

我想得到类中的所有变量及其各自的值。在这种情况下,我试图使用Mirror

代码语言:javascript
运行
复制
func updateProfile(user: User) {

    let mirror = Mirror(reflecting: user)

    for child in mirror.children {
        print("\(child.label!), \(child.value)")
    }

}

我的问题是,我如何将child.value转换为任何其他数据类型,比如String?我只需要知道child.value是属于child.value的

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-06 17:39:48

创建一个扩展Optional<Any>类型以返回它的非可选值的协议:

代码语言:javascript
运行
复制
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,然后允许我们使用AnyOptional.objectValue属性。

代码语言:javascript
运行
复制
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)")
        }
    }
}

,它产生以下输出

代码语言:javascript
运行
复制
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       */

使用此解决方案的好处是,它将“解包”child.value的可选非零值(没有"Optional(...)"填充)以及非可选的child.value值,而不需要对这两种情况分别进行“展开”。在上面的switch案例中,您可以处理需要处理的User对象的任何非零属性,不仅作为String,还可以处理User类中的任何类型。obj属性在switch中将是类的每个非零属性的非可选类型。默认情况对应于值nil (未指定)的选项。

票数 2
EN

Stack Overflow用户

发布于 2016-01-06 15:36:33

child.value具有Any类型。从Any到可选的转换会带来一些问题,幸运的是桑迪·查普曼在this post中给出了一个很好的解决方案。

使用他的函数,代码将如下所示:

代码语言:javascript
运行
复制
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)")
        }
    }
}

因此,如果要查找字符串,则需要同时查找可选和非可选字符串。这适用于您需要检查的所有类型。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34636854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档