
使用atomic一定是线程安全的吗?
不是,atomic仅针对于getter和setter方法调用的时候,此时atomic的内部实现是给当前方法增加了一个同步锁@synchronized,只能保证setter和getter是线程安全的,但是一个线程可能对属性的操作还可能是别的,不如NSMutableArray的元素增删改等等,此时线程就是非安全的了。所以一般锁需要在应用层面进行处理,而不要完全依赖系统实现。
NSString copy 和 NSString mutableCopy 的区别
copy创建不可变副本,mutableCopy创建可变副本
NSString NSArray的copy和mutableCopy
这个写法会出什么问题: @property (copy) NSMutableArray *array;
当使用一个NSMutableArray给其赋值的时候,相当于[array copy],此时拷贝出来的对象是一个不可变数组,所以最好写成strong,手动调用mutableCopy,由于这里使用的是copy,所以得到的实际是NSArray类型,它是不可变的,若在使用中使用了增删改方法会crash;
没有指明nonatomic,因此就是atomic原子操作,会影响性能。该属性使用了同步锁,会在创建时生成一些额外的代码用于编写多线程程序,这会带来性能问题,通过声明nonatomic可以节省这些不必要的额外开销,因为就算使用了automic也不能保证绝对的线程安全,对于要绝对保证线程安全的操作,我们还需要使用更加高级的方式来处理,NSSpinLock 或 @syncronized等
@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的
@property 的本质
@property = ivar + getter + setter;
“属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter)。
ivar、getter、setter 是如何生成并添加到这个类中的?
自动合成( autosynthesis)
完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译 器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。在前例中,会生成两个实例变量,其名称分别为 _firstName与 _lastName。也可以在类的实现代码里通过@synthesize语法来指定实例变量的名字.
@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的?
@protocol 和 category 中如何使用 @property?
protocol中的property
在protocol中添加property时,其实就是声明了 getter 和 setter 方法,在实现这个protocol协议的类中,我们要自己手动添加实例变量,并且需要实现setter/getter方法
category中的property
在category中添加property时, 在@implentation添加 getter 和 setter方法时, 由于category不能添加实例变量
#import "Student.h"
@interface Student (PrimarySchool)
@property (nonatomic, copy) NSString *name;
@end
1.使用临时全局变量来替代成员变量
#import "Student+PrimarySchool.h"
static NSString *_name;
@implementation Student (PrimarySchool)
- (void)setName:(NSString *)name {
_name = name;
}
- (NSString *)name {
return _name;
}
@end
2.使用runtime 关联对象 实现成员变量
#import "Student+PrimarySchool.h"
#import <objc/runtime.h>
@implementation Student (PrimarySchool)
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self,@selector(name),name,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name {
return objc_getAssociatedObject(self, @selector(name));;
}
@end