1. 属性
在开发过程中经常要用到定义属性,@property和@synthesize是经常用到的属性, property在.h文件中作声明,@synthesize在.m文件中用于实现 // Student.h // property // // Created by Rio.King on 13-8-25. // Copyright (c) 2013年 Rio.King. All rights reserved. // #import <Foundation/Foundation.h> @interface Student : NSObject { int age; int no; } //当编译器遇到@property时,会自动展开成getter和setter的声明 @property int age; @property int no; @end Student.m // // Student.m // property // // Created by Rio.King on 13-8-25. // Copyright (c) 2013年 Rio.King. All rights reserved. // #import "Student.h" @implementation Student //@synthesize 会自动生成getter和setter的实现 //@synthesize 默认会去访问age,no,height同名的变量,, //如果找不到同名的变量,会在内部自动生成一个私有同名变量age,no,height,, //因此Student.h 中的这几个变量也可以省略不写。 @synthesize age,no; @end 说明:在xcode4.5以后 可以省略@synthesize ,编译器会自动帮你加上getter 和 setter 方法的实现,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做 _age的私有成员变量. 而我在实际开发使用上的经验是 尽量使用”点语法”,可读性更强.涉及setter getter 初始化时候我才会使用_age. 例如: #pragma mark - getter and setter //当有实例方法中调用 “self.titleLab”就会自动调用以下 setter getter 方法 (UILabel *)titleLab { if(!_titleLab){ UILabel * titleLab = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.view.width, HF_BUTTON_HOME_TEST_HEIGHT)]; titleLab.textAlignment = NSTextAlignmentCenter ; titleLab.text = @"选择生日"; titleLab.font = HF_TITLE_BOLD_FONT ; [self.view addSubview:titleLab]; _titleLab = titleLab; } return _titleLab; }
2, 认识几个关键字 (1)atomic:原子操作(线程安全) (原子性 是指事物的一个完整操作,操作成功就提交,反之就回滚.原子操作 指的是具有原子性的操作) OC属性设置里面默认是atomic 原子属性,意思是 setter/getter函数就是一个原子操作,如果多线程操作 setter 那么 相当于 在函数头尾加了锁 防止资源竞争造成的死锁.(不会出现某一个线程执行完setter所有语句之前,另一个线程就开始执行setter) (2)nonatomic:非原子操作(线程不安全) 一般不需要多线程支持的时候 就用 nonatomic.这样并发访问的效率就会比较高.如果 一个属性要在多线程中使用,那么 就该用原子属性的atomic. 但是 在开发iOS程序时应该使用nonatomic属性,因为atomic属性会严重影响性能, 我们一般在使用nonatomic过程中加锁之类的方法做到数据同步. 通常说nonatomic 是提高在非多线程应用中的读写效率 如果问 这俩谁是线程安全的,原子性安全 所以是atomic更安全 @property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var; 区别 使用@synthesize,编译器会确实的产生getter和setter方法,而@dynamic仅仅是告诉编译器这两个方法在运行期会有的,无需产生警告。 (3)synthesize 会自动生成getter和setter的实现 如果不实现setter和getter方法,编译器将会自动在生产setter和getter方法 (4) dynamic 就是要来告诉编译器,代码中用@dynamic修饰的属性,其getter和setter方法会在程序运行的时候或者用其他方式动态绑定,以便让编译器通过编译。其主要的作用就是用在NSManageObject对象的属性声明上,由于此类对象的属性一般是从Core Data的属性中生成的,Core Data框架会在程序运行的时候为此类属性生成getter和Setter方法。 假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var =someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。这个 时候 自己要写实例方法 进行getter 读取 或者 setter 进行赋值(注意防止方法自己调用自己 造成死循环) 正确使用举例: #pragma mark - getter and setter - (UILabel *)noteLabel { if (!_noteLabel) {//_noteLabel在这里是私有创建, 在@dynamic 里不会自己生成 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 64.0 + 22.0, SCREEN_WIDTH - 100, 40.0)]; [label setTextAlignment:NSTextAlignmentCenter]; [label setFont:[UIFont boldSystemFontOfSize:16.0]]; [label setTextColor:[UIColor grayColor]]; [label setText:self.noteText]; [label setNumberOfLines:0]; [label setLineBreakMode:NSLineBreakByWordWrapping]; _noteLabel = label; } return _noteLabel; } (4)assign : 简单赋值操作,不更改索引计数 对基本数据类型 (例如NSInteger,CGFloat)和C数据类型(int, float, double, char, 等) 适用简单数据类型 (5)strong :我习惯叫它”强引用(apple说是strong reference)”(书上管它叫 拥有关系(owning relationship)) 当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当retainCount=0时,该对象才会被销毁。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用) 一个对象只有在它的所有强引用都被释放后才能被回收. (6)weak :”弱引用”(非拥有关系 nonowning relationship) 当它的生存周期到了时就会被销毁,弱引用在可能会出现循环引用的情况下是必不可少的. strong VS weak 强引用持有对象 弱引用 不持有 当弱引用指向一个强引用所持有的对象时,当强引用赋值为nil 弱引用自动被赋值nil 如果弱引用被赋值为nil 强引用依旧持有原来的对象 strong,weak, unsafe_unretained往往都是用来声明属性的,如果想声明临时变量就得用__strong, __weak, __unsafe_unretained, __autoreleasing, 其用法与上面介绍的类似。 (7)retain :手动释放内存时候使用,相当于ARC中的strong (8)copy :(浅拷贝,指针拷贝)a 和 b 指向同一个对象 共用同一块内存 (9)mutable:(深拷贝,内容拷贝) 做”影子数据”时候使用 是完全新的一个对象 举例:1 NSString *string = @"origion"; NSString *stringCopy = [string copy]; NSMutableString *stringMCopy = [string mutableCopy]; [stringMCopy appendString:@"!!"]; //内存 NSLog(@" string:%p stringCopy:%p stringMCopy:%p ",string,stringCopy,stringMCopy); //对象 NSLog(@" string:%@ stringCopy:%@ stringMCopy:%@ ”,string,stringCopy,stringMCopy); 2016-02-16 17:35:04.284 dailylife[1665:183019] string:0x10d58a4d0 stringCopy:0x10d58a4d0 //copy -> 和string 共用同一块内存地址 (同一个指针) stringMCopy:0x7f92e47375d0 //multableCopy 新的一块内存指针 2016-02-16 17:35:21.479 dailylife[1665:183019] string:origion stringCopy:origion // copy -> 同一个对象 stringMCopy:origion!! //multableCopy 一个新对象 举例2 NSMutableString *string = [NSMutableString stringWithString: @"origion"]; NSString *stringCopy = [string copy]; NSMutableString *mStringCopy = [string copy]; NSMutableString *stringMCopy = [string mutableCopy]; //[mStringCopy appendString:@“mm"];//error 可变字符串应该使用”可变拷贝”multableCopy 才可使用 这类方法 [string appendString:@" origion!"]; [stringMCopy appendString:@"!!"]; //内存 NSLog(@" string:%p stringCopy:%p mStringCopy :%p stringMCopy:%p ",string,stringCopy,mStringCopy,stringMCopy); //对象 NSLog(@" string:%@ stringCopy:%@ mStringCopy:%@ stringMCopy:%@ ”,string,stringCopy,mStringCopy,stringMCopy); 2016-02-16 17:54:46.019 dailylife[2039:201349] string:0x7ff993f71800 stringCopy:0x7ff993f71860 mStringCopy :0x7ff993f71880 stringMCopy:0x7ff993f718a0 //四个不同对象不同指针 2016-02-16 17:54:48.107 dailylife[2039:201349] string:origion origion! stringCopy:origion mStringCopy:origion stringMCopy:origion!! //四个不同对象不同指针