由于未捕获的异常 'NSRangeException' 而终止应用程序,原因:“无法删除观察者 - ios
Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer - ios
我正在使用 swift 开发 ios 应用程序。我正在使用 xcode7.0.1。与表视图控制器。我想在单击行时展开并在再次单击时折叠。我正在学习 gitHub 的教程。现在我面临错误 Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer
for the key path "frame" from <X.expandTips 0x145d8d20> because it is not registered as an observer.'
我希望以下代码行会导致问题。
我的 UITableViewCell class 代码:
func checkHeight(){
expandaple_view.hidden = (frame.size.height < expandTips.expandedHeight)
}
func WatchFrameChanges() {
addObserver(self , forKeyPath: "frame", options: .New, context: nil )
checkHeight()
}
func ignoreFrameChanges(){
removeObserver(self, forKeyPath: "frame")
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "frame"{
checkHeight()
}
}
在我的 TableViewController 代码中:
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
(cell as! expandTips) . WatchFrameChanges()
}
override func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
(cell as! expandTips) . ignoreFrameChanges()
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if (indexPath == selectedIndexPath ){
return expandTips.expandedHeight
}else {
return expandTips.defaultHeight
}
}
我是 ios 的新手。我希望这一定是简单的问题。请有人帮我解决这个问题。
我不知道这里post需要什么细节。如果我想添加更多详细信息,请发表评论。
如果没有注册观察者,删除 KVO 观察者会引发异常。
遗憾的是,无法检查观察者是否已注册。一个众所周知的解决方法是像这样捕获异常 (Objective-C):
@try {
[object removeObserver:self forKeyPath:NSStringFromSelector(@selector(isFinished))];
} @catch (NSException * __unused exception) {}
要在 Swift 中执行此操作,您必须使用 Swift 2.1,因为它不支持 try {} catch {}
。你可以在 2.1 here.
中看到它是如何工作的
更正: 尽管 Swift 2 引入了自己的错误处理约定,使用 do/try/catch
关键字,但这些与它们在Objective-C,而且(从 Swift 2.1 和 Xcode 7.1 开始)在 Swift 中仍然没有办法处理从系统库抛出的 NSExceptions,除了写 Objective-C 代码到 @catch
他们,然后从 Swift.
调用该代码
您可以阅读有关 KVO 的更多信息 here,其中还有一个关于安全退订的部分提到了这个不幸的设计。
从@Leandros 的评论中我找到了解决方案。仅使用布尔变量跟踪观察者。
使用下面的代码,我找到了解决方案:
var frameAdded = false
func checkHeight(){
expanding_view.hidden = (frame.size.height < expandTips.expandedHeight)
}
func WatchFrameChanges() {
if(!frameAdded){
addObserver(self , forKeyPath: "frame", options: .New, context: nil )
frameAdded = true
}
}
func ignoreFrameChanges() {
if(frameAdded){
removeObserver(self, forKeyPath: "frame")
frameAdded = false
}
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "frame"{
checkHeight()
}
}
deinit {
print("deinit called");
ignoreFrameChanges()
}
我正在使用 swift 开发 ios 应用程序。我正在使用 xcode7.0.1。与表视图控制器。我想在单击行时展开并在再次单击时折叠。我正在学习 gitHub 的教程。现在我面临错误 Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer
for the key path "frame" from <X.expandTips 0x145d8d20> because it is not registered as an observer.'
我希望以下代码行会导致问题。
我的 UITableViewCell class 代码:
func checkHeight(){
expandaple_view.hidden = (frame.size.height < expandTips.expandedHeight)
}
func WatchFrameChanges() {
addObserver(self , forKeyPath: "frame", options: .New, context: nil )
checkHeight()
}
func ignoreFrameChanges(){
removeObserver(self, forKeyPath: "frame")
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "frame"{
checkHeight()
}
}
在我的 TableViewController 代码中:
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
(cell as! expandTips) . WatchFrameChanges()
}
override func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
(cell as! expandTips) . ignoreFrameChanges()
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if (indexPath == selectedIndexPath ){
return expandTips.expandedHeight
}else {
return expandTips.defaultHeight
}
}
我是 ios 的新手。我希望这一定是简单的问题。请有人帮我解决这个问题。
我不知道这里post需要什么细节。如果我想添加更多详细信息,请发表评论。
如果没有注册观察者,删除 KVO 观察者会引发异常。
遗憾的是,无法检查观察者是否已注册。一个众所周知的解决方法是像这样捕获异常 (Objective-C):
@try {
[object removeObserver:self forKeyPath:NSStringFromSelector(@selector(isFinished))];
} @catch (NSException * __unused exception) {}
要在 Swift 中执行此操作,您必须使用 Swift 2.1,因为它不支持 try {} catch {}
。你可以在 2.1 here.
更正: 尽管 Swift 2 引入了自己的错误处理约定,使用 do/try/catch
关键字,但这些与它们在Objective-C,而且(从 Swift 2.1 和 Xcode 7.1 开始)在 Swift 中仍然没有办法处理从系统库抛出的 NSExceptions,除了写 Objective-C 代码到 @catch
他们,然后从 Swift.
您可以阅读有关 KVO 的更多信息 here,其中还有一个关于安全退订的部分提到了这个不幸的设计。
从@Leandros 的评论中我找到了解决方案。仅使用布尔变量跟踪观察者。
使用下面的代码,我找到了解决方案:
var frameAdded = false
func checkHeight(){
expanding_view.hidden = (frame.size.height < expandTips.expandedHeight)
}
func WatchFrameChanges() {
if(!frameAdded){
addObserver(self , forKeyPath: "frame", options: .New, context: nil )
frameAdded = true
}
}
func ignoreFrameChanges() {
if(frameAdded){
removeObserver(self, forKeyPath: "frame")
frameAdded = false
}
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "frame"{
checkHeight()
}
}
deinit {
print("deinit called");
ignoreFrameChanges()
}