kvo在key被释放时会暴雪天气造成菜价上涨什么问题如何解决

KVO的概述与使用 - 简书
下载简书移动应用
写了5752字,被69人关注,获得了73个喜欢
KVO的概述与使用
今天终于开始写我的第一个简书,哈哈,目前自己iOS开发也两年了,也是时候分享一下经验了。好吧,废话不多说,开始第一个技术分享:什么是KVO?KVO是Key-Value-Observing的缩写,通过KVO这种机制对象可以通过它得到其他对象的某个属性的变更通知。这种机制在MVC模式下显得更为重要,KVO可以让视图对象经过控制器观察模型对象的变更从而做出更新等操作。KVO这一机制是基于NSKeyValueObserving协议的,Cocoa通过这个协议为所有遵循协议的对象提供了自动观察属性变化的能力。在NSObject中已经为我们实现了这一协议,所以我们不必去实现这个协议。为什么要使用KVO?有的朋友可能会有疑问,为什么要使用KVO呢?KVO能实现的我使用Setter方法同样能实现啊。其实不然KVO存在还是有它的价值的,那么接下来我们看看一下KVO的独特价值吧:1.我们创建一两个setter方法感觉没什么,但是如果要观察的属性非常多,那么还能一一重写setter方法来实现吗?想必大家心里已有了答案,但是利用KVO则能很好的解决上述问题。2.我们自定义的类是很容易改写setter方法的,但是如果你是用一个已经编译好了的类库时要监控其中一个属性时怎么办?难道还要去重写setter方法?如果使用KVO则很轻松解决问题。3.使用KVO能够方便的记录变化前的值和变化后的值,不适用KVO你还要自己来解决这些问题。4.KVO让你的代码看起来更加简洁清晰易于维护。KVO的使用那么我们怎么来使用kvo呢,其实只要记住KVO的三部曲就好了1&注册.指定被观察者的属性 (也就是说你要观察谁?观察谁的哪个属性的变化?)2&实现回调方法
(当你要监听的属性的值被改变了,那么就要在回调的方法里面做你想要做的事情,例如更新UI什么的)3&移除观察者 (增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者)代码示例(以下就是用kvo做的一个小小的Demo)首先我们要新建一个数据模型(以数据模型作为被观察者)KvoModel.h文件#import@interface KvoModel : NSObject@property (nonatomic, strong) NSString
*@property (nonatomic, assign) NSI@end#import "ViewController.h"#import "KvoModel.h"@interface ViewController ()@property (weak, nonatomic) UILabel *labelT@property (strong, nonatomic) KvoModel *@end@implementation ViewController//移除观察- (void)dealloc {[self.model removeObserver:self forKeyPath:@"age"];}- (void)buttonPressed {self.model.age += 5;}- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.KvoModel *model = [[KvoModel alloc]init];self.model =[self.model setValue:@"小崔" forKey:@"name"];[self.model setValue:@10 forKey:@"age"];//创建控件[self setUpSubView];//注册,指定被观察者的属性,[self.model addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];self.labelText.text = [NSString stringWithFormat:@"%ld岁",(long)self.model.age];}//实现回调方法- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {self.labelText.text = [NSString stringWithFormat:@"%@
%ld岁", self.model.name,self.model.age];NSLog(@"keyPath ====%@
id =======%@
dict =========%@ ", keyPath, object, change);}//创建按钮和label- (void)setUpSubView {UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];[btn setFrame:CGRectMake(120, 200, 100, 35)];[btn setBackgroundColor:[UIColor lightGrayColor]];[btn setTitle:@"增加5岁" forState:UIControlStateNormal];[btn addTarget:self action:@selector(buttonPressed)forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];UILabel *labelText = [[UILabel alloc]initWithFrame:CGRectMake(30, 50, 300, 30)];self.labelText = labelTself.labelText.text = [NSString stringWithFormat:@"%@现在的年龄是: %ld", self.model.name, (long)self.model.age];[self.view addSubview:self.labelText];}@end好了,不足之处,希望大家多多指教!
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
希望一起加油,编辑器不对,这样不好看
被以下专题收入,发现更多相似内容:
非常棒的专题!每天都会收录精华文章,欢迎投稿,一起分享学习的喜悦。
· 1447人关注
iOS进阶相关
· 140人关注
欢迎投稿,稿子有质量要求哦。
有想管理这个专题的私聊我哦 @敖老黑
· 53人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:kvo在key被释放时会造成什么问题如何解决_百度知道
kvo在key被释放时会造成什么问题如何解决
提问者采纳
本文来源于:cocoachina KVO(Key Value Observing),是观察者模式在Foundation中的实现。 KVO的原理 简而言之就是: 1、当一个object有观察者时,动态创建这个object的类的子类 2、对于每个被观察的property,重俯唬碘舅鄢矫碉蝎冬莽写其set方法 3、在重写的set方法...
来自团队:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁13473人阅读
KVO(NSKeyValueObserving 的简称)、KVC(NSKeyValueCoding 的简称)
在很多时候接触到很多地方都有对 KVC,KVO 的描述,但是都是一笔带过。只知道这是Object-C提供的一个不错的机制,可以很好的减少代码。
首先我们先了解下 KVO 的机制,KVO:当指定的对象的属性被修改了,允许对象接收到通知的机制。每当在类中定义一个监听
如: [self addObserver:self forKeyPath:@&items& options:0 context:contexStr];
当然你还可以监听其他对象的属性变化,如:[person addObserver:money forKeyPath:@&account& options:0 context:contexStr];
只要当前类中 items 这个属性发生的变化都会触发到以下的方法
- (void)observeValueForKeyPath:(NSString *)keyPath
  ofObject:(id)object
  change:(NSDictionary *)change
  context:(void *)context
KVO 的优点:
当有属性改变,KVO 会提供自动的消息通知。这样开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知。
这是 KVO 机制提供的最大的优点。因为这个方案已经被明确定义,获得框架级支持,可以方便地采用。
开发人员不需要添加任何代码,不需要设计自己的观察者模型,直接可以在工程里使用。
其次,KVO 的架构非常的强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值。
KVC 的实现分析
KVC 运用了一个 isa-swizzling 技术。
isa-swizzling 就是类型混合指针机制。KVC 主要通过 isa-swizzling,来实现其内部查找定位的。
isa 指针,就是 is a kind of 的意思,指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针和其它数据。
如下 KVC 的代码:
[person setValue:@&personName& forKey:@&name&];
就会被编译器处理成:
SEL sel = sel_get_uid(&setValue:forKey:&);
IMP method = objc_msg_lookup (person-&isa,sel);
method(person,sel,@&personName&,@&name&);
SEL数据类型:它是编译器运行Objective-C里的方法的环境参数。
IMP数据类型:他其实就是一个编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型。
KVC在调用方法setValue的时候
(1)首先根据方法名找到运行方法的时候所需要的环境参数。
(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。
(3)再直接查找得来的具体的方法实现。
这样的话前面介绍的KVO实现就好理解了
当一个对象注册了一个观察者,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。
所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。
这样只有当我们调用KVC去访问key值的时候KVO才会起作用。所以肯定确定的是,KVO是基于KVC实现的。
下面实例演示一下:
@implementation Person
@synthesize name,//属性name将被监视
-(void)changeName
directly&;
@implementation PersonMonitor
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
&&& if([keyPath isEqual:@&name&])
&&&&&&& NSLog(@&change happen,old:%@ new:%@&,[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);
//测试代码
Person *p =[[Person alloc] init];//监视对象
PersonMonitor *pm= [[PersonMonitor alloc]init];
[p addObserver:pm forKeyPath:@&name& options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil];
//测试前的数据
NSLog(@&p.name is );
//通过setvalue 的方法,PersonMonitor的监视将被调用
[p setValue:@&name kvc& forKey:@&name&];
//查看设置后的值
NSLog(@&p name get by kvc is
valueForKey:@&name&]);
//效果和通过setValue 是一致的
change by .name=&;
//通过person自己的函数来更改 name
[p changeName];&
//最后一次修改是直接修改,所以没法产生通知。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:174653次
积分:2034
积分:2034
排名:第13219名
原创:33篇
转载:32篇
评论:14条
(1)(1)(1)(1)(1)(1)(1)(4)(1)(1)(2)(1)(3)(3)(15)(18)(1)(1)(6)(2)如何理解 Objective-C编程的KVO 原理_百度知道
如何理解 Objective-C编程的KVO 原理
提问者采纳
是观察者模式在Foundation中的实现;name&quot, - (BOOL)_isKVOA ) &#47, NSStringFromSelector(_cmd));%@&quot, - (id)name ) &#47, copy) NSString *__NSArrayI 0x8d55870&__NSArrayI 0x8e9aa00&gt,一目了然。  KVO的原理  简而言之就是:(NSString *)key {
NSLog(@&quot.class Sark (lldb) po object_getClass(sark) Sark
/ breakpoint 1 (lldb) po sark:self forKeyP breakpoint 3 (lldb) po [object_getClass(sark) instanceMethods] & breakpoint 3 断住后分别使用- class和object_getClass()打出sark对象的Class和真实的Class  &#47:通知观察者  4,删除重写的方法  5;( - (void)setName:(Protocol *)proto,因为这个方法返回的是这个对象的isa指针,这里请出一个NSObject的扩展NSObject+DLIntrospection:key];
+ (NSArray *)&#47:  1;( - (void)setN }
- (void)didChangeValueForK &#47:最主要的重写方法;
[super willChangeValueForKey, NSStringFromSelector(_cmd)):(id)arg0 ;萨萨萨&quot:  &#47、- dealloc做清理犯罪现场工作  4、- class隐藏自己必备啊,判断这个类有没被KVO动态生成子类  接下来验证一下KVO重写set方法后是否调用了- willChangeValueForKey,返回原来类的class  3;&#47,它封装了打印一个类的方法;name&quot,重写其set方法  3,而且为了隐藏这个行为; + (NSArray *)classMethods,NSKVONotifying_Sark重写了- class方法返回之前的类,简单验证下。  @interface NSObject (DLIntrospection) + (NSArray *)( - (void)setN + (NSArray *)properties,这个指针指向的一定是个这个对象的类对象  然后来偷窥一下这个动态类实现的方法、当一个object有观察者时;、属性; breakpoint 3 (lldb) po sark、当一个property没有观察者时; + (NSDictionary *)descriptionForP&#47.class Sark (lldb) po object_getClass(sark) Sark 上面的结果说明.cxx_destruct,set值时调用通知函数  2;&#47,当然这个和KVO没啥关系了;%@&quot,动态创建这个object的类的子类  2;&#47:(NSString *)key {
NSLog(@& breakpoint 2 sark:nil]、对于每个被观察的property, - (void)/ breakpoint 2 (lldb) po [object_getClass(sark) instanceMethods] &lt:self forKeyPath: NSObject @property (nonatomic:  @implementation Sark
- (void)willChangeValueForKey,删除动态创建的子类  空说无凭、在重写的set方法中调用- willChangeValueForKey:  最直接的验证方法就是在Sark类中重写这两个方法.cxx_destruct:和- didChangeValueForK + (NSArray *)instanceVariables:(id)arg0 , - (id)name )  大概就是说arc下这个方法在所有dealloc调用完成后负责释放所有的变量:(id)arg0 ;&#47、- setName、- _isKVOA这就是内部使用的标示了:cocoachina  KVO(Key Value Observing)、当没有observer观察任何一个property时。  @interface Sark 本文来源于;/ @end
@implementation Sark @end  Sark *sark = [Sark new], - (class) [sark removeO, - (void)。  从上面breakpoint2的打印可以看出:  1,动态类重写了4个方法; breakpoint 2 (lldb) po sark,就好像什么也没发生过一样:和- didChangeValueForK
[super didChangeValueForK]; breakpoint 1 [sark addO__NSArrayI 0x8e9cff0&gt.class Sark (lldb) po object_getClass(sark) NSKVONotifying_Sark
&#47,framework使用runtime动态创建了一个Sark类的子类NSKVONotifying_S&#47, - (void),在sark对象被观察时; breakpoint 1 (lldb) po [object_getClass(sark) instanceMethods] & @end  然后继续在刚才的断点处调试:@&quot.name = @&
+ (NSString *)parentClassH + (NSArray *)instanceMethods、协议等常用调试方法:key]; /; &#47,回到正题:@&quot:NSKeyValueObservingOptionNew context。但是使用object_getClass()时就暴露了
来自团队:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁IOS开发之----KVO的使用
上篇我们讲到了KVC,这篇我们学习KVO,全名为:Key Value Observing,直译为:基于键值的观察者。
那它有什么用呢?KVO主要用于视图交互方面,比如界面的某些数据变化了,界面的显示也跟着需要变化,那就要建立数据和界面的关联。
ObjC中提供的KVO就是解决这种问题的。以下用显示页面观察学生的课程名称变化的例子来说明KVO的使用。
学生类命名为:Student,页面类是:PageView.
上图来自苹果官网,图中的BankObject好比PageView,PersonObject好比Student,
PageView观察Student的变化。
1、添加Student学生类。
类中有name,和课程名称courseName,添加一个可以改变课程名称的方法changeCourseName。一会用来做对比,看直接改变课程名称时会不会有回调。
实现文件.m
实现类把方法实现了。
2、页面类实现
init初始化时,向student实例添加观察者,在释放的时候移除观察者。
3、实现观察
在main函数中
新建一个student的实例,设置他的课程是数学课,然后创建页面类的时候,用student初始化。这是页面类已经观察着学生的课程了。
再给课程设置新的值为化学课。这时候运行打印结果:
16:29:21.561
objectiveC[]&初始值:数学课
16:29:21.565 objectiveC[] PageView课程被改变了
16:29:21.566 objectiveC[] PageView新课程是:化学课老课程是:数学课
可以看到Pageview类中的回调被调用,Pageview接收到学生课程数据更新的信息。
4、直接改变课程信息对比
直接调用changeCourseName方法改变课程,打印结果:
16:32:06.230
objectiveC[]&初始值:数学课
16:32:06.237 objectiveC[] PageView课程被改变了
16:32:06.238 objectiveC[] PageView新课程是:化学课老课程是:数学课
16:32:06.239
objectiveC[]&直接改变的课程为:英语课
可以看到,这时Pageview的回调没被调用到。说明只有通过键值编码(KVC)改变的值,才会回调观察者注册的方法。
这里是苹果官网的关于KVO的文档,英文好的朋友可以看看:
/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/-BCICJDHA
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 kvo释放 的文章

 

随机推荐