繁体   English   中英

Swift协议:由于递归循环,自定义属性设置器崩溃

[英]Swift Protocols: Custom Property Setter Crash because of Recursive loop

Swift:由于无限循环,自定义属性设置器崩溃

public protocol RequestType {
    var parameters: AnyObject? { get set }
}

public extension RequestType {

    public var parameters: AnyObject? {
        get { return nil }
        set { parameters = newValue }
    }

    public printParameters() {
        print(parameters)
    }

}

用法:

class HTTPBinRequest: RequestType { }

let request = HTTPBinRequest()
request.parameters = ["name" : "Rahul"]
request.printParameters()

它崩溃,因为它被卡在递归循环中。

但是,当我在类中声明该属性并将设置器保留为空时,它就可以正常工作。

class HTTPBinRequest: RequestType { 
    public var parameters: AnyObject?
}

public extension RequestType {

    public var parameters: AnyObject? {
        get { return nil }
        set {}
    }

    public printParameters() {
        print(parameters)
    }

}

let request = HTTPBinRequest()
request.parameters = ["name" : "Rahul"]

谁能建议我如何解决这个更好的方法。

似乎您正在尝试在协议扩展中创建存储的属性 你不能那样做。 您只能在协议扩展中创建计算的属性

这是一个存储的属性:

class A {
    var value: Int?      // Stored property
}

这是一个计算属性:

class B {                       
    var someString: String?     // Stored property

    var value: Int? {           // Computed property
        get { return Int(someString) }
        set { someString = "\(newValue)" }
    }
}

计算属性无法设置自身-如果您尝试设置该属性,它将创建您遇到的递归循环。 但是它可以做其他事情,例如设置类的其他存储属性,如上面的示例所示,它接受Int作为新值,然后将其存储为String 永远不会存储Int值本身。 当您检索Int值时,每次访问它时,它都会从someString计算得出。

如果您尝试将其作为协议来执行,则可以将计算属性放到协议中,而不要放到存储属性中:

protocol BProtocol {
    var someString: String? { get set }
    var value: Int? { get set }
}

extenstion BProtocol {

    var value: Int? {        
        get { return Int(someString) }
        set { someString = "\(newValue)" }
    }
}

但是然后您仍然需要在类中定义存储的属性:

class B: BProtocol {                       
    var someString: String?
}

但是您无需定义value属性。 class B将从BProtocol扩展继承BProtocol

因此,对该问题的简短回答是,在您的类中创建存储的属性,而不是在协议扩展中创建。

编辑:

根据评论,也许您需要使用两层协议。 第一个协议列出了不使用parameters属性的对象的要求:

protocol BaseProtocol {
   var someStuff: String? { get set }
}

protocol BaseProtocolWithParameters: BaseProtocol {
   var parameters: AnyObject? { get set }
}

我之所以这样说是因为,通常来说,具有要求用户创建从未使用过的属性的协议的协议是不好的设计。 如果某些对象永远不会使用parameters ,那么这些对象就不需要符合它们不需要的协议要求。 它们可以符合BaseProtocol 实际上确实需要使用对象parameters能够符合BaseProtocolWithParameters从继承BaseProtocol

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM