一、KVC

键-值编码(Key - Value Coding, KVC)是通过变量名的读取和设置变量值的一种方法,将字符串的变量名作为key来引用。NSObject定义了两个方法(KVC方法)用于变量值得读取和设置:setValue:forKey; valueForKey:forKey;

  1. @interface Student:NSObject{
  2. NSString *firstName;
  3. }
  4.  
  5. Student *s = [[Student alloc] init];
  6.  
  7. //设置变量值
  8. [s setValue:@"Larry" forKey:@"firstName"];
  9. //读取变量值
  10. NSString *name = [s valueForKey:@"firstName"];

注:KVC两个方法操作的都是对象,如变量类型是int等标量,必须转换为对象。例如int类型转换为NSNumber类型 [NSNumber numberWithInt: 5]

二、accessor

accessor 类似于C#里的使用属性读取和设置变量值。objective-c里accessor读取和设置方法的写法是有规定的,如@interface定义了NSString *name变量,则accessor的方法要定义为-(NSString *)name; 和 -(void)setName:(NSString *)value; 即读取方法的名称和变量名相同,返回类型为变量类型;写方法名称为“set变量名”(变量名第一个字母大写)带一个和变量相同类型的参数。

  1. //头文件
  2. @interface AccessorDemo:NSObject{
  3. NSString *name;
  4. }
  5.  
  6. -(NSString *)name;
  7. -(void)setName:(NSString *)value;
  8.  
  9. @end;
  10.  
  11. //实现文件
  12. #impot AccessorDemo.h
  13.  
  14. @implementation AccessorDemo
  15.  
  16. -(NSString *)name{
  17. return name;
  18. }
  19.  
  20. -(void)setName:(NSString *)value{
  21. name = value;
  22. }
  23.  
  24. @end;

三、KVC和accessor的关系

如果定义了accessor方法,则KVC的setValue方法调用accessor的写方法,KVC的valueForKey方法调用accessor的读方法。

例如下面的代码:

  1. //
  2. // KvcFunAppDelegate.h
  3. // KvcFun
  4. //
  5. // Created by apple on 13-7-12.
  6. // Copyright (c) 2013年 FDStudio. All rights reserved.
  7. //
  8.  
  9. #import <Cocoa/Cocoa.h>
  10.  
  11. @interface KvcFunAppDelegate : NSObject <NSApplicationDelegate>{
  12. int fido;
  13. }
  14.  
  15. -(int)fido;
  16. -(void)setFido:(int)x;
  17.  
  18. @property (assign) IBOutlet NSWindow *window;
  19.  
  20. @end
  1. //
  2. // KvcFunAppDelegate.m
  3. // KvcFun
  4. // Created by apple on 13-7-12.
  5. // Copyright (c) 2013年 FDStudio. All rights reserved.
  6. //
  7.  
  8. #import "KvcFunAppDelegate.h"
  9.  
  10. @implementation KvcFunAppDelegate
  11.  
  12. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
  13. {
  14. // Insert code here to initialize your application
  15. }
  16.  
  17. -(id)init{
  18. self = [super init];
  19. if(self){
  20. [self setValue:[NSNumber numberWithInt:] forKey:@"fido"]; //KVC(Key-Value Coding)只能处理对象,所以要将int转换为NSNumber
  21. NSNumber *n = [self valueForKey: @"fido"];
  22. NSLog(@"fido = %@", n);
  23. }
  24. return self;
  25. }
  26.  
  27. -(int)fido{
  28. NSLog(@"-fido is return %d", fido);
  29. return fido;
  30. }
  31.  
  32. -(void)setFido:(int)x{
  33. NSLog(@"-setFido is called with %d", x);
  34. fido = x;
  35. }
  36. @end

四、点标记方法

类型于C#里“对象.属性"的写法,以简化accessor的调用。正常的objective-c的accessor调用方法类似于value = [object name] [object setName: @"李四"]的写法。而点标记方法的写法为 value = object.name 和 object.name = @"李四"。但某些人不建议用,为什么应该是仁者见仁智者见智了。

五、Properties

properties提供了一个方法来减少写accessor的代码量。property的声明语法为 @property (attritbutes) type name; 其中type为变量类型 name为变量名称。实现文件中的写法为@synthesize name;如果property名字和成员变量名称不一样,如xcode的习惯写法为成员变量加下划线前缀,则用@synthesize name = 成员变量名称。

attributes属性可包括readwrite 和 readonly两种,默认是readwrite。设置为readonly则没有setter方法。为描述setter方法如何工作,属性包括下面的一种:assign、strong、weak、copy。

  • assign(默认) 创建一个赋值语句,常用于标量变量,而非指针类型的变量。
  • strong 说明property是强引用类型
  • weak 说明property是弱引用类型
  • copy 创建新值得复制,常用于字符串和其他mutable子类型情况下。

strong 和 weak 区别不好理解,最好看看objective-c的retain引用计数部分作为基础。看了http://mobile.51cto.com/iphone-386301.htm的文章有点明白了。

定义为strong变量,如果有其它变量引用了strong变量则其引用计数+1,weak变量引用计数则不+1;仔细看下面的代码和输出结果就明白了。

1.强引用

  1. //头文件内容
  2. @property (strong) NSString *string1;
  3. @property (strong) NSString *string2;
  4.  
  5. //实现文件内容
  6. @synthesize string1;
  7. @synthesize string2;

下面代码测试输出结果

  1. self.string1 =[[NSStringalloc] initWithUTF8String:"string1"];
  1. self.string2 = self.string1;
  2. self.string1 = nil;
  3.  
  4. NSLog(@"String 2 = %@", self.string2);

输出结果为

2.弱引用

如果将string1 或者 string2任何一个指定为weak,则输出下面的结果

即声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。

注:string1的复制必须用[[NSStringalloc] initWithUTF8String:"string1"],否则weak的运行结果和strong相同。如string1 = @“string1”这样赋值就不行,weak和strong的结果一样,具体为什么没搞明白呢,求高手指点!

 六、绑定和键-值观察KVO

Cocoa中许多控件对象都使用绑定,当开发者绑定一个键到控件的一个属性时,显示视图将自动让它们同步。例如一个滑动条的Value和一个整形键值fido绑定。滑动条使用valueForKey来获取初值(触发了accessor的fido方法),当移动滑动条时调用setValue来更新fido的值(触发了accessor的setFido方法)。

如果直接改变成员变量的值,就不会通知观察者(滑动条)键值已经改变,视图也就不能同步了。需要显式的通知观察者,改变成员变量前调用willChangeValueForKey方法,改变变量后调用didChangeValueForKey方法。例如:

  1. [self willChangeValueForKey:@"fido"];
  2. fido++;
  3. [self didChangeValueForKey:@"fido"];

另两张手动改变变量值,同步观察者的方法为使用KVC方法或accessor方法。

  1. NSNumber *n = [self valueForKey:@"fido"];
  2. NSNumber *newValue = [NSNumber numberWithInt: [n intValue] + ];
  3. [self setValue:newValue forKey:@"fido"];
  1. [self setFido:[self fido] + ];

实例练习:

1.新建一个窗体应用程序,名称和类前缀都为KvcFun。

2.窗体上添加一个水平滑动条、一个lable、3个按钮。

3.KvcFunAppDelegate.h中添加int _fido变量,用于记录滑动条的值,然后建立@property (assing) fido;属性。KvcFunAppDelegate.m添加property的实现

@synthesize fido = _fido;。

4.绑定控件的属性,将滑动条和Label的value属性绑定到fido键。

5.设置滑动条的初始值

  1. -(id)init{
  2. self = [super init];
  3. if(self){
  4. [self setFido: ];
  5. }
  6. return self;
  7. }

6.添加三个按钮的IBAction方法

(1)手动方法将滑动条的值加1

  1. - (IBAction)handIncementFido:(id)sender {
  2. [self willChangeValueForKey:@"fido"];
  3. _fido++;
  4. [self didChangeValueForKey:@"fido"];
  5. }

(2)KVC方法将滑动条的值加1

  1. - (IBAction)kvcIncementFido:(id)sender {
  2. NSNumber *n = [self valueForKey: @"fido"];
  3. NSNumber *newVal = [NSNumber numberWithInt:[n intValue] + ];
  4. [self setValue:newVal forKey:@"fido"];
  5. }

(1)accessor方法将滑动条的值加1

  1. - (IBAction)incrementFido:(id)sender {
  2. [self setFido: [self fido] + ];
  3. }

7.运行测试效果,点我下载源代码

七、键路径

未理解,to-do this :(

《苹果开发之Cocoa编程》键-值编码和键-值观察的更多相关文章

  1. 《苹果开发之Cocoa编程》挑战1 创建委托 练习

    <苹果开发之Cocoa编程>第4版 P87 新建一个单窗口应用程序,设置某对象为窗口的委托,当用户调整窗口尺寸时,确保窗口高度为宽度的2倍. 需要实现的委托方法为:-(NSSize)win ...

  2. 《苹果开发之Cocoa编程》挑战2 创建一个数据源 练习

    <苹果开发之Cocoa编程>第4版 P87 创建一个to-do list应用程序,在文本框中输入任务.当用户单击Add按钮时,添加字符串到一个变长队列,新任务就出现在list的末尾. 关键 ...

  3. 苹果开发之COCOA编程(第三版)下半部分

    第十八章:Image和鼠标事件 1.NSResponderNSView继承自NSResponder类.所有的事件处理方法都定义在NSResponder类中.NSResponder申明了如下方法:- ( ...

  4. 苹果开发之COCOA编程(第三版)上半部分

    第一章:什么是Cocoa 1.1 历史简介 1.2 开发工具:Xcode.Interface Builder(一个GUI构建工具).在它们内部,使用gcc为编译器来编译代码,并使用gdb来查找错误 1 ...

  5. IOS开发之Cocoa编程—— NSUndoManager

    在Cocoa中使用NSUndoManager可以很方便的完成撤销操作.NSUndoManager会记录下修改.撤销操作的消息.这个机制使用两个NSInvocation对象栈. NSInvocation ...

  6. 苹果开发之App签名

    如果你的Apple ID账号(可使用邮箱来注册)为Apple developer类型的话,登录之后是看不到Certificates, Indentifiers & Profiles信息的 Ap ...

  7. iOS项目开发之Socket编程

    有一段时间没有认真总结和写博客了 前段时间找工作.进入工作阶段.比较少静下来认真总结,现在静下心来总结一下最近的一些心得 前言 AsyncSocket介绍 AsyncSocket详解 AsyncSoc ...

  8. Unity3D游戏开发之C#编程中常见数据结构的比较

    一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...

  9. 答题小程序开发之socket编程 微信小程序答题 直播答题开发 直播弹幕使用web socket编程

    最近有一个项目很火,那就是直播答题的,接到公司的这个任务,开发直播答题的聊天室功能.在线的人相互聊天.之前做过类似的,当时都是使用的ajax轮询的,这种非常的耗费服务器.所以这次就开始使用socket ...

随机推荐

  1. matlab:clear,close,clc

    clear 删除工作空间中的项目,释放系统内存 语法: clear clear name clear name1 name2 name3... clear global name clear -reg ...

  2. SharePoint 2013 Nintex Workflow 工作流帮助(十二)

    博客地址 http://blog.csdn.net/foxdave 工作流动作 31. Create task(User interaction分组,企业版才有) 该操作用于在Microsoft Ex ...

  3. 50元制作PS2键盘无线监控装置

    0×00    什么是Arduino  Arduino实际上就是一种开发板,将微控制器和必需的元件集成在一块电路板上,扩展出完善的接口和针脚,就可以接上各种各样的传感器,完成你心中的设计,你也可以把它 ...

  4. MSDN在线

    https://msdn.microsoft.com/zh-cn/library/aa139615.aspx

  5. 升级IOS 9 和 XCode 7 引起的问题

    问题一: 升级xcode 7最低的系统配置要求 升级了ios9 后使用 xcode 6.1 已经不能用了,必须升级 xcode 7才行,原先的系统是OSX 10.10.1 版本.而xcode 7.0 ...

  6. swift初识

    介绍: Swift是苹果2014年推出的全新编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程不仅保留了Objc很多语言特性,他也借鉴了多种现代化语言的特点,在其 ...

  7. MooFest_二维树状数组

    Description Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a s ...

  8. X86平台乱序执行简要分析(翻译为主)

    多处理器使用松散的内存模型可能会非常混乱,写操作可能会无序,读操作可能会返回不是我们想要的值,为了解决这些问题,我们需要使用内存栅栏(memory fences),或者说内存屏障(memory bar ...

  9. 程序退出异常_DebugHeapDelete和std::numpunct

    前几天程序新加一个功能之后,其中用到了boost的lexical_cast<float>,发现在关闭命令行窗口的时候,程序报错,是程序退出清理时候报的错误. 一开始以为是程序新增的功能有问 ...

  10. MySQL 获得当前日期时间(以及时间的转换)

    1.1 获得当前日期+时间(date + time)函数:now() 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数: current_timestamp()   curr ...