swift setter 导致 exc_bad_access
swift setter causing exc_bad_access
下面有一个简单的class
import Foundation
public class UsefulClass: NSObject{
var test:NSNumber{
get{return self.test}
set{
println(newValue)
self.test = newValue
}
}
override init() {
super.init()
self.test = 5;
}
}
我在这里初始化它
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var testClass = UsefulClass()
}
}
但它导致 xcode 打印出 200 个 5,然后由于 EXC_BAD_ACCESS code = 2 而崩溃。为什么会这样?
Swift 变量默认为合成属性。
在大多数情况下这就足够了(建议选择 Swift 类型)
var test: Int
override init() {
super.init()
test = 5
}
如果您需要在设置变量后执行某些操作,请使用
var test: Int {
didSet{
println("\(oldValue) - \(newValue)")
}
}
您的代码通过调用 setter 永久设置变量,该 setter 调用 setter ……
@vadian 在他的回答中提供了解决方案,应该可以解决您的问题。让我解释一下发生了什么。
您创建了一个计算 属性,即没有变量支持的 属性,getter 和 setter 都进行了一些处理,通常在另一个存储属性,以便分别return一个值并设置一个新值。
这是你计算出来的 属性:
var test: NSNumber {
get { return self.test }
set {
println(newValue)
self.test = newValue
}
}
查看 getter 实现:
return self.test
它有什么作用?它读取当前实例的 test
属性,然后 returns 它。哪个是test
属性?就是这个:
var test: NSNumber {
get { return self.test }
set {
println(newValue)
self.test = newValue
}
}
是的,一样属性。你的getter所做的就是递归地无限期地调用自己,直到在运行时发生崩溃。
同样的规则适用于 setter:
self.test = newValue
它不断调用自身,直到应用程序崩溃。
这是一个无限循环;您的 setter 正在递归调用自身。
var test: NSNumber {
set {
test = newValue
}
}
这编译得很好,Objective-C 程序员可能期望没有循环,因为设置 "backing ivar" 例如 _test
而不是重新调用 setter 方法.
但是 属性-支持实例变量 _ivars
不存在于计算属性的 Swift 中,除非您自己创建它们。
下面有一个简单的class
import Foundation
public class UsefulClass: NSObject{
var test:NSNumber{
get{return self.test}
set{
println(newValue)
self.test = newValue
}
}
override init() {
super.init()
self.test = 5;
}
}
我在这里初始化它
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var testClass = UsefulClass()
}
}
但它导致 xcode 打印出 200 个 5,然后由于 EXC_BAD_ACCESS code = 2 而崩溃。为什么会这样?
Swift 变量默认为合成属性。 在大多数情况下这就足够了(建议选择 Swift 类型)
var test: Int
override init() {
super.init()
test = 5
}
如果您需要在设置变量后执行某些操作,请使用
var test: Int {
didSet{
println("\(oldValue) - \(newValue)")
}
}
您的代码通过调用 setter 永久设置变量,该 setter 调用 setter ……
@vadian 在他的回答中提供了解决方案,应该可以解决您的问题。让我解释一下发生了什么。
您创建了一个计算 属性,即没有变量支持的 属性,getter 和 setter 都进行了一些处理,通常在另一个存储属性,以便分别return一个值并设置一个新值。
这是你计算出来的 属性:
var test: NSNumber {
get { return self.test }
set {
println(newValue)
self.test = newValue
}
}
查看 getter 实现:
return self.test
它有什么作用?它读取当前实例的 test
属性,然后 returns 它。哪个是test
属性?就是这个:
var test: NSNumber {
get { return self.test }
set {
println(newValue)
self.test = newValue
}
}
是的,一样属性。你的getter所做的就是递归地无限期地调用自己,直到在运行时发生崩溃。
同样的规则适用于 setter:
self.test = newValue
它不断调用自身,直到应用程序崩溃。
这是一个无限循环;您的 setter 正在递归调用自身。
var test: NSNumber {
set {
test = newValue
}
}
这编译得很好,Objective-C 程序员可能期望没有循环,因为设置 "backing ivar" 例如 _test
而不是重新调用 setter 方法.
但是 属性-支持实例变量 _ivars
不存在于计算属性的 Swift 中,除非您自己创建它们。