ios - swift 协议(protocol) : Custom Property Setter Crash because of Recursive loop

标签 ios swift swift2

Swift:自定义属性 setter 因无限循环而崩溃

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()

它崩溃是因为它卡在了递归循环中。

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

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"]

谁能建议我如何更好地解决这个问题。

最佳答案

看来您正在尝试在协议(protocol)扩展中创建一个存储属性。你不能那样做。您只能在协议(protocol)扩展中创建计算属性

这是一个存储属性:

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)来执行,则可以将计算属性放入协议(protocol)中,而不是存储属性:

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 属性。 B 类 将从 BProtocol 扩展继承。

所以对你的问题的简短回答是,在你的类中创建存储的属性,而不是在协议(protocol)扩展中。

编辑:

根据评论,您可能需要使用双层协议(protocol)。第一个协议(protocol)规定了不使用 parameters 属性的对象的要求:

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

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

我之所以这么说,是因为通常来说,如果协议(protocol)的要求是要求用户创建从未使用过的属性,那这种设计是糟糕的设计。如果某些对象永远不会使用 parameters,则不应要求这些对象遵守它们不需要的协议(protocol)要求。它们可以符合 BaseProtocol。真正需要使用parameters的对象可以遵循继承自BaseProtocolBaseProtocolWithParameters

关于ios - swift 协议(protocol) : Custom Property Setter Crash because of Recursive loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36267322/

相关文章:

ios - NSManagedObject 子类实现具有所需 init 的协议(protocol)的 Swift 链接器错误

ios - EXC_BAD_ACCESS objective-c block

ios - remoteControlReceived(带有事件 : UIEvent?)未触发

swift 错误。使用未声明的类型 String

ios - 段错误 11 - 桥接头

ios - 删除导航按钮

ios - 委托(delegate)/协议(protocol)将数据从一个 View Controller 传递到另一个

ios - 是否可以将单例与 ViewController 一起使用?

带有 slider 的 UITableView 单元格 : touch not working correctly swift 2

iphone - iCloud:我可以忽略那些禁用 iCloud 的人吗?