Swift flatMap和泛型

时间:2016-06-08 23:07:06

标签: ios swift generics flatmap

我正在尝试使用flatMap在Swift中构建Resource<T>,但是一直遇到一个奇怪的错误,只有当我强制执行强制转换时才会有效。

Resource<T>

public struct Resource<T> {
    let record: CKRecord
    let parser: [String: AnyObject] -> T?
}

工作代码:

public func buildResource<T>(resource: Resource<T>) -> T? {
    var dataJson: [String: AnyObject] = [:]
    dataJson["recordID"] = resource.record.recordID
    for name in resource.record.attributeKeys {
        dataJson[name] = resource.record[name]
    }
    return (dataJson as? [String: AnyObject]).flatMap(resource.parser)
}

上面的代码给出了一个警告,表明强制转换总是成功,这是真的。但是当我试图像这样删除演员时:

public func buildResource<T>(resource: Resource<T>) -> T? {
    var dataJson: [String: AnyObject] = [:]
    dataJson["recordID"] = resource.record.recordID
    for name in resource.record.attributeKeys {
        dataJson[name] = resource.record[name]
    }
    return dataJson.flatMap(resource.parser)
}

它出现以下错误:'flatMap' produces '[S.Generator.Element]', not the expected contextual result type 'T'?

解析器是struct init,如此:

struct Example {

    let name: String
    let id: Int
}

extension Example {

    init?(dataJson: [String: AnyObject]) {
        guard let name = dataJson["name"] as? String else {
            return nil
        }
        guard let id = dataJson["id"] as? Int else {
            return nil
        }
        self.name = name
        self.id = id
        return
    }

}

任何想法如何解决这个或不同的方法?这里的想法是将任何CKRecord转换为结构,而无需编写大量的样板代码。

2 个答案:

答案 0 :(得分:4)

Daniel Hall的回答是正确的,但是,通过这样做,您将被迫更改parser初始签名以接收(String, AnyObject)

最好的选择是使用此签名创建另一个init并将其解析为json签名的init,仍然可以从原始{{1}创建此结构}。

json

修改

当您将extension Example { init?(json: [String: AnyObject]) { guard let name = json["name"] as? String else { return nil } guard let id = json["id"] as? Int else { return nil } self.name = name self.id = id return } init (tuple : (String, AnyObject)) { var json : [String : AnyObject] = [:] json["name"] = tuple.0 json["id"] = tuple.1 self.init(json: json)! } } 创建为dataJson时,您无需在其上[String : AnyObject],只需返回flatMap

答案 1 :(得分:3)

您的解析器功能看起来有错误的签名。整个json字典的类型为[String : AnyObject],但使用flatMap()枚举时该字典中的各个元素的类型为(String, AnyObject),而不是[String : AnyObject]

尝试更改此内容:

public struct Resource<T> {
    let record: CKRecord
    let parser: [String: AnyObject] -> T?
}

到此:

public struct Resource<T> {
    let record: CKRecord
    let parser: (String, AnyObject) -> T?
}