Ios 为什么在页面视图控制器中使用KVO进行观察时应用程序崩溃?如何使KVO生效?
当在我的页面视图控制器的子内容视图控制器的滚动视图中使用拖动时,我试图使用KVO观察更新更改,但当应用程序启动时,它崩溃了,显示: “由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因是:“KVOPageVC.ContentViewController类的一个实例0x7ff003d3f5b0被释放,而键值观察者仍在向其注册。” 下面是我的代码和屏幕截图: 应用程序屏幕截图 代码 PageViewController.swiftIos 为什么在页面视图控制器中使用KVO进行观察时应用程序崩溃?如何使KVO生效?,ios,swift,uipageviewcontroller,key-value-observing,uicontainerview,Ios,Swift,Uipageviewcontroller,Key Value Observing,Uicontainerview,当在我的页面视图控制器的子内容视图控制器的滚动视图中使用拖动时,我试图使用KVO观察更新更改,但当应用程序启动时,它崩溃了,显示: “由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因是:“KVOPageVC.ContentViewController类的一个实例0x7ff003d3f5b0被释放,而键值观察者仍在向其注册。” 下面是我的代码和屏幕截图: 应用程序屏幕截图 代码 PageViewController.swift 导入UIKi
导入UIKit
类PageViewController:UIPageViewController{
var pageLabels:Array=[“第一页”、“第二页”、“第三页”]
重写func viewDidLoad(){
super.viewDidLoad()
数据源=self
self.setViewController([contentViewForPage(0)],方向:。正向,动画:true,完成:nil)
}
func contentViewForPage(索引:Int)->ContentViewController{
让contentVC=storyboard!。实例化eviewcontrollerwhiteIdentifier(“contentVC”)为!ContentViewController
contentVC.pageIndex=索引
contentVC.label=页面标签[索引]
返回内容VC
}
}
扩展PageViewController:UIPageViewController数据源{
func pageViewController(pageViewController:UIPageViewController,viewController预览控制器viewController:UIViewController)->UIViewController{
将vc=viewController设为!ContentViewController
var index=vc.pageIndex作为Int
如果索引=0 | |索引=NSNotFound{
归零
}
索引-=1
返回contentViewForPage(索引)
}
func pageViewController(pageViewController:UIPageViewController,viewControllerAfterViewController:UIViewController)->UIViewController{
将vc=viewController设为!ContentViewController
var index=vc.pageIndex作为Int
如果索引==NSNotFound{
归零
}
指数+=1
如果索引==self.pageLabels.count{
归零
}
返回contentViewForPage(索引)
}
}
ObeserverViewController.swift
它是嵌入在“内容视图控制器”的“容器视图”中的“视图控制器”,当用户拖动并释放下面的滚动条时,我希望表情脸被文本“待通知!”所取代。
导入UIKit
类ObeserverViewController:UIViewController{
@iblabel:UILabel!//当用户拖动滚动视图并释放时,我希望它的值会相应地改变。
var contentVC:ContentViewController!//保存对象的变量
重写func viewDidLoad(){
super.viewDidLoad()
}
覆盖功能视图将出现(动画:Bool){
超级。视图将显示(动画)
self.contentVC=self.storyboard!。实例化eviewcontrollerwhiteIdentifier(“contentVC”)
self.contentVC.addObserver(self,forKeyPath:“changingLabel”,选项:[],上下文:nil)
}
覆盖功能视图将消失(动画:Bool){
超级。视图将消失(动画)
self.contentVC.removeObserver(self,forKeyPath:“changingLabel”)
}
重写func observeValueForKeyPath(键路径:String?,对象对象的类型:AnyObject?,更改:[String:AnyObject]?,上下文:UnsafeMutablePointer){
如果keyPath==“更改标签”{
notifyLabel.text=“待通知!”
}
}
脱硝{
self.contentVC.removeObserver(self,forKeyPath:“changingLabel”)
}
}
ContentViewController.swift
页面视图控制器的子视图控制器,共3页。它包括一个滚动视图和一个容器视图(嵌入式ObeserverViewController)
导入UIKit
类ContentViewController:UIViewController{
变量标签:字符串!
var pageIndex:Int!
动态变量changingLabel:String=“”
@IBVAR弱内容标签:UILabel!
@iBCROLLVIEW:UIScrollView!
@ibvar-contentView:UIView!
@IBOutlet弱var containerView:UIView!
重写func viewDidLoad(){
super.viewDidLoad()
contentLabel.text=标签
self.scrollView.delegate=self
self.contentView.backgroundColor=UIColor.greenColor()
}
}
扩展ContentViewController:UIScrollViewDelegate{
func ScrollViewDiEndDraging(scrollView:UIScrollView,将减速减速:Bool){
如果scrollView.contentOffset.y<-50{
如果contentView.backgroundColor==UIColor.greenColor(){
contentView.backgroundColor=UIColor.yellowColor()
self.setValue(“哈”,forKey:“changingLabel”)
}否则{
contentView.backgroundColor=UIColor.greenColor()
self.setValue(“哇”,forKey:“changingLabel”)
}
}
}
}
我的问题是:
当我在另一个控制器中拖动并释放滚动视图时,如何使一个控制器中的表情标签文本收到更改通知?
提前非常感谢 首先,将观察者添加到一个对象,然后从另一个对象移除。当您调用
InstanceViewController…
时,它将为您创建传递的视图控制器标识符的新对象。而不是通过KVO对其更改进行签名。但是在viewwilldisapear
中,您得到的不是在viewWillAppear
中装箱的相同对象,而是装箱新对象(它与在viewWillAppear
中创建的对象无关)。而您从它的通知中辞职,仍然是因为它不是您之前创建并向他(使用KVO)签名的同一个对象,这样的辞职不会产生所需的结果。您需要做的是将首先创建的对象保存到某个变量中,然后在需要时放弃该变量
其次,您不仅需要在viewwilldisapear
方法中删除观察者,还需要在
deinit {
// perform the deinitialization
}
然后,您将确信,如果您的对象被删除,那么它也将从通知中退出
哟
import UIKit
class ObeserverViewController: UIViewController {
@IBOutlet weak var notifyLabel: UILabel!// when the user drag the scroll view and release, i hope its value will be changed accordingly.
var contentVC: ContentViewController! //the variable to hold the object
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.contentVC = self.storyboard!.instantiateViewControllerWithIdentifier("ContentVC")
self.contentVC.addObserver(self, forKeyPath: "changingLabel", options: [], context: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.contentVC.removeObserver(self, forKeyPath: "changingLabel")
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "changingLabel" {
notifyLabel.text = "to be notified!"
}
}
deinit {
self.contentVC.removeObserver(self, forKeyPath: "changingLabel")
}
}
import UIKit
class ContentViewController: UIViewController {
var label: String!
var pageIndex: Int!
dynamic var changingLabel: String = ""
@IBOutlet weak var contentLabel: UILabel!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
contentLabel.text = label
self.scrollView.delegate = self
self.contentView.backgroundColor = UIColor.greenColor()
}
}
extension ContentViewController: UIScrollViewDelegate {
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if scrollView.contentOffset.y < -50 {
if contentView.backgroundColor == UIColor.greenColor() {
contentView.backgroundColor = UIColor.yellowColor()
self.setValue("hah", forKey: "changingLabel")
} else {
contentView.backgroundColor = UIColor.greenColor()
self.setValue("wow", forKey: "changingLabel")
}
}
}
}
deinit {
// perform the deinitialization
}