4

我正在尝试使用 flatMapResource<T>在 Swift 中构建一个,但不断收到一个奇怪的错误,并且仅在我强制转换时才有效。

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 轻松转换为结构,而无需编写大量样板代码。

4

2 回答 2

4

Daniel Hall 的回答是正确的,但是这样做,您将被迫将您的parserinit 签名更改为 receive (String, AnyObject)

最好的选择是init使用此签名创建另一个并将其解析为您的json签名init,仍然能够从 raw 创建此结构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)!
    }
}

编辑

当你创建你的dataJsonas a[String : AnyObject]时,你不需要做 a flatMap,你可以返回resource.parser(json: dataJson)

于 2016-06-09T00:15:43.330 回答
3

看起来您的解析器函数签名错误。整个 json 字典是 type [String : AnyObject],但在枚举时该字典中的各个元素flatMap()是 type (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?
}
于 2016-06-08T23:34:42.770 回答