【问题标题】:Extending CollectionType with optional initialiser使用可选初始化器扩展 CollectionType
【发布时间】:2016-02-13 10:25:03
【问题描述】:
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)

【问题讨论】:

  • 你能解释一下你想做什么吗?
  • 我添加了更多信息。我想通过扩展集合类型来实现 let aArray = [A](data: dArray)。
  • @RahulKatariya 在 Swift 中,初始化器没有返回值。这与 Obj-C 不同。在初始化失败的情况下,您使用return nil 来指示可能触发初始化失败的点。此外,您不要使用return 关键字来指示初始化成功。所以编译器抱怨你的 return elements 声明,因为你不能返回任何东西,除了 nil ...
  • @RahulKatariya:你想做什么?这段代码应该是什么let a = A(data: d)
  • 感谢旋风。我的错。所以我必须扩展 Array 然后才有一个 init 方法。

标签: ios swift swift2 swift-protocols


【解决方案1】:

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

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

【讨论】:

  • 谢谢奥利弗。辅助方法工作正常,但正在寻找一种方法,以便我通过初始化来完成。
  • Oliver,协议无法初始化,但是 init?仍然可以通过协议扩展来定义。 OP 收到错误,因为 init?必须返回(如果)只有零值。
【解决方案2】:

让我们定义一个协议

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
    }
}

看看下一个sn-p会发生什么

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?没有协议扩展的相同参数,编译器会抱怨。

【讨论】:

  • 谢谢,我想在协议扩展数组中有 init。
  • @RahulKatariya 数组是结构,而不是协议。所以,(就像你一样)你可以定义init?在类型扩展中。扩展可以为类型添加新功能,但不能覆盖现有功能。您可以使用协议扩展为该协议的任何方法或属性要求提供默认实现。如果符合标准的类型提供了它自己的所需方法或属性的实现,则将使用该实现而不是扩展提供的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 1970-01-01
  • 2011-08-27
  • 2018-06-21
  • 2012-09-23
  • 1970-01-01
相关资源
最近更新 更多