天天看点

OC-属性

在开始讲解之前,我们先创建一个Student类,它的成员变量
@interface Student : NSObject
{
    NSString * _name;//姓名
    NSInteger _age;//年龄
    NSString * _code;//身份证号
}
@end
           
然后我们写一下每个成员变量的setter,getter方法,大家会发现仅仅只是三个,大家有没有觉得它很长,很多,非常的繁琐,万一以后还有很多个成员变量,那不是感觉都快疯了。
那如何来解决这个问题呢,OC为你提供了----属性

属性的核心就是让我们摆脱脱繁琐的setter和getter方法的创建,它会自动为我们创建setter,getter方法
           

接下来我们正式开始我们的属性学习啦!

1.属性的声明

属性的声明,需声明在@interface和@end之间,全局变量的下方,与方法的声明类似:
           
OC-属性
[email protected]关键字,声明一个属性;
2.nonatomic关键字,禁止多线程,变量保护,提高性能;
3.strong关键字,指定声明属性的类型,如果为对象类型,一般使用strong,如果是非对象类型,使用assign,更多关于关键字的内容会在后面详细讲解。
           
@property详解
属性:通过属性合成对象指定成员变量的setter和getter方法,简化代码,通过配置属性关键字可以实现具体的内存管理操作
//声明步骤:
ios5 之前:
1.先有声明成员变量,而且必须是要下划线的
2.声明属性
3.合成属性:@synthesize name = _name;


ios5 之后:
声明属性的同时,声明了其对应的成员变量(_name),自动 合成属性实现,推荐还是要写成员变量,苹果推荐这种书写格式
           
属性里面的参数:
第一类 内存管理相关
assign: 缺省值   修饰基本数据类型和delegate对象
retain: 对象类型
copy  :对象类型(遵守<NSCopying>情况下)
第二类: 线程相关
atomic : 关心线程安全  通常用于多线程
nonatomic:不关心线程安全,通常用于单线程中
第三类
readwrite:读写
readonly:只读(只提供getter方法,不提供setter方法)

strong = retain
weak = assign
           
我们根据上面讲的定义属性
//属性关键字  属性配置关键字      属性类型   属性名称
@property (nonatomic, retain, getter=getName) NSString *name;
@property (nonatomic, retain) NSString *code;
@property (nonatomic, assign, readonly) NSInteger age;
           
2.属性的应用
属性应用:点语法
   OC中类的成员变量声明属性后,可以使用点语法访问成员变量
   点语法在‘=’左边是setter方法
   点语法在‘=’右边或者在表达式中是getter方法
   点语法优先级非常高,可以进行自加,自减
     */
           
Student *student1 = [[Student alloc] init];
   [student1 setName:@"lili"];
   student1.name = @"lili";
   NSLog(@"student1 = %@",[student1 name]);
   NSLog(@"student1 = %@",student1.name);

   [student1 setAge: ];
   student1.age = ;

   student1.age = student1.age + ;
   NSLog(@"age = %ld",[student1 age]);
   NSLog(@"age = %ld",++student1.age);
           
3.总结属性关键字
retain:对象使用,持有对象,引用计数+1
 assign:默认属性,简单/复杂数据类型使用,直接赋值,不  做任何内存操作
 nonatomic:非原子性,不保证变量的线程安全
 atomic:默认属性,原子性,保证变量线程安全,会有性能开销
 copy:对象不可变复制,常用于NSString,retain类似,持有对象
 readonly:只读,只生成getter而不会生成setter。按照属性的含义,我们可以将只读属性理解为,只有取值方法的属性
它并非是完全不能设置属性的值,只是不能直接设置,多数情况下是通过设置其他关联属性来设置

 getter = ...:定义getter方法的名称 ,如bool值
 @property (nonatomic, assign, getter=isGood) BOOL good;

 strong:强引用,ARC中使用strong,和retain功能相同
 weak:弱引用,ARC中使用weak
           
不同关键字对于属性的影响主要体现在属性的set方法
- (void)setName:(NSString *)name
{
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}
           
assign属性对应的setter方法如下
- (void)setAge:(NSInteger)age
  {
    _age = age;

   }
           
4.属性关键字的使用
一般情况下,只要是对象类型,都使用strong(后面可能有例外);
只要是非对象类型,都使用assign;


例如:
@interface Person : NSObject
@property ( nonatomic, strong ) NSString *name;//语句中的strong不能省略
@property ( nonatomic, assign ) NSInteger age;//语句中的assign可省略
@end

在Person.m文件中增加上述代码,即可生成一个私有属性,只能在本类中使用。
           
5.属性关键字copy:
我们也会经常见到copy关键字,它的用法比较多样化。我们可以暂时这样理解,当它使用在不可变类型的属性时,等于strong;当它使用在可变类型时,每次赋值都会拷贝一个新的对象。
           
原理就是他的深复制,浅复制
该对象所在的类需遵守<NSCopying>,才可以使用copy
  深复制:内容复制,编译器会开辟新的内存来存储复制对象的数据,复制对象retaincount默认为1,需要手动释放
  浅赋值:指针赋值,只是将对象的引用计数加1,需要手动释放
  copy:不可变复制,若对象是不可变的是浅复制,若对象是可变的,则是深复制,且复制对象不可变
  mutableCopy:可变复制,无论对象可变/不可变都是深复制,复制的对象可变
           
NSString *string = [[NSString alloc] init];
   NSString *string1 = [string copy];
   NSLog(@"string = %p,string1 = %p",string,string1);
   [string release];
   [string1 release];
   //指向地址相同:string = 0x7fff7cfebd00,string1 = 0x7fff7cfebd00


    NSArray *array1 = [[NSArray alloc] initWithObjects:@"1",@"2", nil];
    NSArray *array2 = [array1 copy];
    NSLog(@"%p,%p",array1,array2);
    [array1 release];
    [array2 release];
    //指向地址相同:0x1003007f0,0x1003007f0

    //结论:copy 对于不可变对象,是指针复制,也叫浅复制
    NSMutableString *mutableString = [[NSMutableString alloc] initWithFormat:@"%@",@"22"];
    NSMutableString *mutableString1 = [mutableString copy];
    NSLog(@"%p,%p",mutableString,mutableString1);
    //地址不同:0x100300f40,0x323225
    [mutableString release];
    [mutableString1 release];
    //copy对于可变对象,是内容复制,深复制,但复制过后的新地址中的内容为不可变


    //同理可验证mutableCopy  <NSMutableCopying>
    //结论:对于可变和不可变对象,mutableCopy为深复制(开辟新内存,内容复制),且开辟的新内存中的内容为可变对象
    //实践:
    NSMutableArray * mArray = [@[@"123", @"456"] mutableCopy];
     [mArray removeLastObject];
     NSLog(@"array = %@", mArray);
     [mArray release];