iOS之《Effective Objective-C 2.0》读书笔记(6)

来源:互联网 发布:java专业技能怎么写 编辑:程序博客网 时间:2024/05/29 18:13

第六条:理解“属性”这一概念

1.@property

(1)编译器遇到关键字@property会自动为这个属性添加setter/getter方法,避免了每次手动添加的麻烦。
(2)编译器就会为我们自动生成对应的实例变量_myTitle:

 @property (copy, nonatomic) NSString *myTitle;//声明属性

2.使用@property时相关的关键字

(1)atomic 和 nonatomic

1)atomic:表示对对象的操作属于原子操作,支持多线程,使用atomic比nonatomic更耗费系统资源。(2nonatomic 表示访问器的访问不是原子操作,不支持多线程访问安全,但是访问性能高。(3)原因:在多线程的下对对象的访问都需要先上锁访问后再解锁,保证不会同时有几个操作针对同一个对象,所以多线程访问的情况下,会耗费资源,降低性能

(2)retain,assign和copy

1assign:只可以对基本数据类型(如CGFloatNSInteger,Bool,int,代理对象)等使用。该方式会对对象直接赋值而不会进行retain操作(2)retain :使对象的应用计数增加一(3)copy :表示重新建立一个新的计数为1的对象,然后释放掉旧的值(4)原因:retain是对指针的拷贝,copy是对内容的拷贝     比如:NSString 对象的地址为0x100,其内容为“string”,如果使用copy到另外一个NSString对象,则会生成另外一个地址为0x110的对象,只不过内容仍然是‘string“。如果使用retain到另外一个NSString对象,则该对象的地址仍然为0x100,只不过该对象的计数变为2.

(3)strong 和 weak

1strong 强引用,strong修饰的属性一般不会自动释放。默认的所有实例变量和局部变量都是strong指针。   eg1: @property (nonatomic, strong) NSArray *dataList;@property (nonatomic, strong) UILabel *label;   eg2: 使用懒加载定义控件的时候,一般也用strong   eg3:addSubView 默认对其 subView 进行了强引用(2weak 弱引用,主要用于防止循环引用   eg1: 使用 sb 或者 xib 给控件拖线的时候: @property (weak, nonatomic) IBOutlet UILabel *label;   eg2: delegate模式,你的ViewController通过strong指针(self.view)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController。

3.@synthesize

(1)@synthesize的使用有很悠久的历史了,此处不研究,只是说明@synthesize现在的具体应用
(2)@synthesize的作用:就是让student = ?中的后者这个变量来“代替”属性,从而可以通过操作变量来进行属性的操作

// 在 .h文件@property (copy, nonatomic) NSString *student;// 在.m文件@synthesize   student  =  student //可以直接使用student,而非self.student// 默认情况下:@synthesize   student  =  _student  //使用self.student

(3)两者的区别:

a:添加:@synthesize   student  =  student:属性本身的引用计数是不会增加的,因为没有经过调用setter方法或者是getter方法b:使用self.student这种操作方式的话,实质上是通过setter或者是getter方法进行操作,引用计数会随着不同的操作而改变

4.@dynamic:(参考)

(1)@dynamic的作用:禁止编译器为@property产生setter和getter方法

// .h文件@property(nonatomic,copy)NSString *name;// .m文件@dynamic name;// 赋值name = @"zhangsan";   // 报错:Use of undeclared identifier "name"

(2)两种办法手动实现setter和getter方法:
,,,,,,,,,,方法一:自己提供setter和getter方法,将编译器自动生成的setter和getter方法手动再写一遍

  1》需要在类中显式提供实例变量,因为@dynamic不能像@synthesize那样向实现文件(.m)提供实例变量   // .h文件  {         NSString *_name;    }  @property(nonatomic,copy)NSString *name;  2》手动写setter和getter方法  // .m文件  @dynamic name;- (void) setName:(NSString *)name{    if (_name != name) {        _name = [name copy];    }}- (NSString *) name{    return _name;}

………方法二:在运行时决定setter和getter对应实现的C函数,使用了NSObject提供的resolveInstanceMethod:方法:

  1》需要显式声明实例变量而且访问级别是@public,为了隐藏该实例变量,将声明放在扩展(extension)中   // .h文件@property(nonatomic,copy)NSString *name;  2》手动写setter和getter方法  // .m文件   {          @public     NSString *_name;    }    @dynamic name;+ (BOOL) resolveInstanceMethod:(SEL)sel  {      // Capture setName: and name method      if (sel == @selector(setName:)) {          class_addMethod([self class], sel, (IMP)setName, "v@:@");          return YES;      }      else if (sel == @selector(name)) {          class_addMethod([self class], sel, (IMP)getName, "@@:");          return YES;      }      return [super resolveInstanceMethod:sel];  }  

5.set,get 方法

(1)set,get方法的书写

// set方法的书写:-(void)setAge:(int)age{    self.age = age;//不能这样写,因为赋值号左边的self.age实际上是 [self setAge:age]的简写,会调用set方法    _age = age;//要这样写}// get方法的书写:-(int)age{    return _age;}

(2)set,get方法的使用:set是给属性赋值的,get是取得属性值的,不一定同时存在。

// set方法的使用   [student setAge:12];// get方法的使用   NSLog(@"%@",[student age]);

(3)定义属性时需要注意的:

   @property (nonatomic, strong) NSString *age;//这个就是会自动生成get、set方法,()里省略了readwrite    @property (nonatomic, strong, readonly) NSString *age;//这个就是只有get方法,不能set 
阅读全文
0 0