self.variable和_variable的区别,关于KVO
Difference between self.variable and _variable,about KVO
第一张图是用self.name改的,第二张用_name改成change.it应该是一样的结果,但是第二张输出的是nothing.why?
这是代码
#import "ViewController.h"
@interface kvo : NSObject
@property (nonatomic,strong) NSString *name;
@end
@implementation kvo
- (void)change
{
_name = @"b";
}
@end
@interface ViewController ()
@property (nonatomic, strong) kvo *a1;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.a1 = [[kvo alloc] init];
_a1.name = @"a";
[self.a1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
[_a1 change];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"1");
}
变化方法self.name
和_name
的区别
编辑:这与“Objective-C 中的 _variable 和 self.variable 之间的区别是什么?[重复]”不是同一个问题,我知道那是关于 getter 方法和 setter 方法,我的问题是为什么 setter 方法触发 KVO 而 _name = @"b"
不触发 KVO。
只有当您通过 属性 访问实例变量时,您才会收到 KVO 通知。直接设置实例变量不会调用KVO通知。
这里是第一种情况,你通过
设置名字
self.name = @"b";
事实上,这将调用 属性 setter 方法 setName:
,它在内部发送 KVO 通知 didChangeValueForKey
。实际上通知是通过调用 setter 方法触发的..
第二种情况
_name = @"b";
您是直接设置实例变量,没有 属性 setter 方法。所以 KVO 通知不会被触发。
如果你愿意,你可以自己触发通知
[self willChangeValueForKey:@"name"];
_name = @"b";
[self didChangeValueForKey:@"name"];
但我认为不需要,使用 属性 设置变量。这将为您完成一切。
阅读更多关于 KVO notification
为了接收 属性 的键值观察通知,需要三件事:
第 1 步:观察到的 class 必须是符合您希望观察的 属性 的键值观察。
第二步:必须将观察对象注册到被观察对象,方法是addObserver:forKeyPath:options:context:
.
第 3 步: 观察 class 必须实施 observeValueForKeyPath:ofObject:change:context:
。
第一张图是用self.name改的,第二张用_name改成change.it应该是一样的结果,但是第二张输出的是nothing.why?
这是代码
#import "ViewController.h"
@interface kvo : NSObject
@property (nonatomic,strong) NSString *name;
@end
@implementation kvo
- (void)change
{
_name = @"b";
}
@end
@interface ViewController ()
@property (nonatomic, strong) kvo *a1;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.a1 = [[kvo alloc] init];
_a1.name = @"a";
[self.a1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
[_a1 change];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"1");
}
变化方法self.name
和_name
的区别
编辑:这与“Objective-C 中的 _variable 和 self.variable 之间的区别是什么?[重复]”不是同一个问题,我知道那是关于 getter 方法和 setter 方法,我的问题是为什么 setter 方法触发 KVO 而 _name = @"b"
不触发 KVO。
只有当您通过 属性 访问实例变量时,您才会收到 KVO 通知。直接设置实例变量不会调用KVO通知。
这里是第一种情况,你通过
设置名字self.name = @"b";
事实上,这将调用 属性 setter 方法 setName:
,它在内部发送 KVO 通知 didChangeValueForKey
。实际上通知是通过调用 setter 方法触发的..
第二种情况
_name = @"b";
您是直接设置实例变量,没有 属性 setter 方法。所以 KVO 通知不会被触发。
如果你愿意,你可以自己触发通知
[self willChangeValueForKey:@"name"];
_name = @"b";
[self didChangeValueForKey:@"name"];
但我认为不需要,使用 属性 设置变量。这将为您完成一切。
阅读更多关于 KVO notification
为了接收 属性 的键值观察通知,需要三件事:
第 1 步:观察到的 class 必须是符合您希望观察的 属性 的键值观察。
第二步:必须将观察对象注册到被观察对象,方法是addObserver:forKeyPath:options:context:
.
第 3 步: 观察 class 必须实施 observeValueForKeyPath:ofObject:change:context:
。