Day2
属性
类似java中的Lombok下的@Data注解(但是也有不一样的,@Data不仅生成get/set函数,同时也会生成多个构造函数。而OC中的属性只会生成get/set)。
使用方法就是通过@property对于属性进行声明。eg.
@interface interfaceA:NSObject{
float attributeA; //似乎可以缺省
float attributeB;
}
@property float attributeA;
@property float attributeB;
@end
@implementation interfaceAImpl
@synthesize attributeA; //编译器会自动生成-setAttributeA和-attributeA方法的预编译代码
@synthesize attributeB;
//...other method
@end
@property的参数
一共有四组参数:
-
与多线程相关的参数。
atomic、nonatomic。
atomic:会加上安全锁。(sync)
nonatomic:没有安全锁,不安全,但是效率会较高。
-
与生成的setter方法相关的参数。
assign、retain。
assign:默认值,生成的setter方法实现就是直接赋值。
retain:生成的setter方法就是标准的MRC内存管理代码。注意,不会在dealloc中生成release的代码,所以还是需要手动添加。
-
与生成只读,读写相关的参数。
readonly、readwrite。
readwrite:默认值。代表同时生成get函数和set函数。
readonly:只会生成getter,而不会生成setter。
-
与生成的getter、setter方法名字相关的参数。
getter、setter。
默认情况下,@property生成的getter和setter方法的名字都是最标准的名字。
getter = getter方法的函数名。用来指定@property生成的getter方法的名字。
setter = setter方法的函数名。用来指定@property生成的setter方法的名字。但是需要注意,setter方法是需要参数的,后面需要加上一个冒号。
点表达式
如果其出现在“=”左边,则是调用相应变量的set方法。如果其出现在“=”右边,则是调用该变量的get方法。
classA.attributeA=20f; //[classA setAttributeA:20f];
classA.attributeB=40f; //[classA setAttributeB:20f];
属性修饰
需要将所有的属性特性显式的声明出来,特性的顺序为atomicity(nonatomic,atomic)、storage(weak,strong,assign)、rw(readonly,readwrite);并且NSString需要使用copy的属性特性而非strong。
类别
这部分是OC中新加的内容,需要之后抽时间进一步认真学习。现在只是了解,并未完全熟悉。
使用时机:
- 无法(不允许)修改主类,但是需要对主类中的方法进行一次拓展,添加方法,这时可以通过类别向主类添加一个方法而不用改变主类。
- 将一个大型的类分为多个类别,通过这种方法可以把不同类的方法放入不同的类别,从而将类的实现写入多个 .m的实现文件中,从而便于开发。
- **类别中的方法可以只声明,不实现。**可以作为非正式协议来使用。
使用方法:
新建类别文件的命名:“原类名 + 类别名”。
@interface NSString(categoryA,categoryB)
//注意,只能定义方法。
@end
@implemenation NSString(categoryA,categoryB)
//方法的实现
@end
不足:
- 只能添加方法,不能添加变量。
- 当类别中的方法和主类中的方法同名,类别中的方法优先级更高。
类拓展
类拓展是类别的一种特殊形式。
使用方法:
@interface 主类类名()//不需要类别名
@end
拓展类通常定义在主类的.m文件中,而在.m文件中实现。
内存管理的原则
-
有对象的创建,就要一个release。
-
retain和release的次数要匹配。
-
谁用谁retain。谁不用谁release。
谁负责retain,谁就负责release。
-
多一个用的时候才retain,少一个的时候才release。
-
在方法中不能随意进行retain。
野指针/僵尸对象
野指针:指针指向的对象已经被回收了。
僵尸对象:一个已经被释放的对象,其内存空间还没有被分配给别人。
检测僵尸对象功能不打开。消耗性能较高。
当一个指针成为野指针之后,将其值赋为nil。
当属性是一个OC对象的时候
第一步,将原本指向的对象进行release,然后再将新传入的对象进行retain。PS. 在新旧对象是同一个对象的时候,什么都不能做。
再赋值。而当前对象销毁的时候,则需要在dealloc中进行release。
当一个对象为nil的时候,调用方法函数不会有任何反应。
- (void)setCar:(Car *)car{
if(_car != _car){
[_car release];
_car = [car retain];
}
}
-(void)dealloc{
[_car release];
[super dealloc];
}