使用可选的初始化

时间:2016-02-13 10:25:03

标签: ios swift swift2 swift-protocols

protocol Decodable {
    init?(data: [String: AnyObject])
}

struct A: Decodable {

    var data: [String: AnyObject]!

    init?(data: [String: AnyObject]) {
        self.data = data
    }

}

当我想创建一个对象时,这是有效的

let d = ["name":"Rahul"]
let a = A(data: d)

我正在尝试实现以下功能,但它在编译时出错。

let dArray = [["name":"Rahul"],["name":"Rahul"],["name":"Rahul"]]
let aArray = [A](data: dArray)

以下代码给出了错误' nil是初始化程序允许的唯一返回值'。

public extension CollectionType where Generator.Element: Decodable {

    init?(data: [[String: AnyObject]]) {
        var elements: [Generator.Element] = []

        for d in data {
            let element = Generator.Element(data: d)
            if let element = element {
                element.append(element)
            }
        }

        return elements

    }

}

================================= 答案: -

public extension Array where Element: Decodable {

    init?(data: [String: AnyObject]) {
        var elements: [Element] = []
        for d in data {
            let element = Element(data: d)
            if let element = element {
                element.append(element)
            }
        }
        self = elements
    }

}

这将允许您使用以下代码初始化

let dArray = [["name":"Rahul"],["name":"Rahul"],["name":"Rahul"]]
let aArray = [A](data: dArray)

2 个答案:

答案 0 :(得分:0)

您的错误是因为CollectionType是一个无法初始化的协议。 您是否尝试创建一个帮助类方法来返回集合,例如

func collectionWithData(data: [[String: AnyObject]]) -> [Generator.Element] {

答案 1 :(得分:0)

让我们定义一个协议

protocol P {
    init?(b: Bool)
}
如Oliver所述,协议无法初始化,但我们仍然可以在协议扩展中定义init

extension P {
    init?(b: Bool) {
        print("init defined in extension")
        if b == false { return nil }
        self.init(b: b)
    }
}

请注意,你不能从init返回任何内容但是nil(如果初始化失败)

让我们定义一个符合我们协议的类

class C: P {
    var b: Bool
    required init(b: Bool) {
        self.b = b
    }
}

看看下一个代码段中会发生什么

let c1: C? = C(b: false)
let c2 = C(b: false)
dump(c1)
dump(c2)
/*
init defined in extension
- nil
▿ C #0
  - b: false
*/

相同的表达式C(b: false)给出了两个不同的结果:-)。那么,如果你定义init和init,要小心吗?通过协议扩展。如果您尝试定义init和init?没有协议扩展的相同参数,编译器会抱怨。