一 `weak和assign的区别?
什么情况下使用weak?
1.在ARC情况下,在有可能出现引用循环的情况下,往往要通过让其中一端使用weak来解决,比如delegate;
2.比如自身已经对其强引用的情况下,没有必要再次强引用,此时使用weak,如storyboard添加控件使用IBoutlet
weak和assign的区别?
1.在ARC中weak和assign都弱引用声明关系,表示非拥有关系;
2.weak声明的对象在被释放之后,释放的时候把指针自动置为nil,再次调用该对象或者像该对象发消息,不会因为野指针造成crash;
3.assign可以用于非OC对象,修饰基本数据类型和结构体,weak只能用于修饰OC对象;
二`copy和strong的问题?
为什么NSString/NSArray/NSDictionary用copy关键字,如果用strong关键字会有什么问题?
1.使用copy是因为NSString,NSArray,NSDictionary有起对应的NSMutableXX类型,使用copy关键字是为了保证所修饰的对象
不受外界所影响,使用copy所修饰的对象,无论外界给我传递一个可变/不可变对象,我本身持有的是不可变对象;
2.如果我们使用strong关键字,当外界传递一个可变对象时,我们所持有的就说一个可变对象,外界修改该可变对象时,我们所持有的
对象也随之改变,导致数据的不安全.
三`copy和mutableCopy的区别?深拷贝和浅拷贝?
对非集合对象进行copy和mutableCopy
1.对非集合不可变对象进行copy是指针拷贝,只拷贝指针,浅拷贝;
2.对非集合不可变对象进行mutableCopy是内容拷贝,深拷贝;
3.对非集合可变对象进行copy是内容拷贝,深拷贝;返回immutable对象,不可调用可变方法;
4.对非集合可变对象进行mutableCopy是内容拷贝,深拷贝;
对集合对象进行copy和mutableCopy
1.对集合不可变对象进行copy是指针拷贝,只拷贝指针,浅拷贝;
2.对集合不可变对象进行mutableCopy是内容拷贝,深拷贝;
3.对集合可变对象进行copy是内容拷贝,深拷贝;返回immutable对象,不可调用可变方法;
4.对集合可变对象进行mutableCopy是内容拷贝,深拷贝;
四`OC里面有哪些属性关键字?分别用于什么情况?
原子性 nonatomic
读写权限 readonly / readwrite
内存管理 copy / strong / weak / assign / unsafe_unretained
五`如何让自己的类用copy修饰符?
需要遵守NSCopying协议,如果包含可变对象版本需要遵守NSMutableCopying协议,实现对应的协议方法
1.NSCopying
- (id)copyWithZone:(NSZone *)zone;
2.NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
六`@Property的本质是什么?ivar,getter,setter是如何生成并添加到这个类的?
@Property = ivar + getter + setter;
属性Property有两大概念即: ivar(实例变量),存取方法(access method = getter + setter)
ivar + getter + setter 自动合成;
完成属性定义后,编译器会自动编写访问这些属性所需要的方法,此过程叫着自动合成(autosynthesis),除
了生成方法代码setter/getter之外,编译器还需要像类里添加适当类型的实例变量,并且在属性前面添加
_最为实例变量名称,也可以在类的实现代码通过@synthesize语法里指定实例变量名称
@implementation Person
@synthesize firstName = _firstName;
@end
当添加一个属性的时候,系统会在ivar_list中添加一个成员变量,在method_list中添加对应属性的setter和getter方法
七`@Protocol,Category(类目)和Extension(扩展)的区别?
Category 分类
1.分类是用于给原有类添加方法的,因为分类的结构体指针中,没有属性列表,只有属性方法列表.所以原
则上"只能添加方法,不能添加属性(成员变量),实际上可以通过runtime添加属性"
2.分类中可以写@Property,但不会生成setter/getter方法,也不会生成实现私有的成员变量;
3.可以访问原有类.h文件中的所有属性;
4.如果分类中有和原有类同名的方法,会优先调用分类中的方法,就是忽略原有类的方法,同名方法调用优先
级"分类>本类>分类",因此在开发过程中尽量不要覆盖原有类方法;
5.如果多个分类中都有和原有类同名方法,那么调用该方法的时候该执行谁由编译器决定,编译器会执行最后一个参与编译的分类方法;
如何在分类中添加属性?
1.在一个类中声明@Property编译器会自动帮我们生成_成员变量和setter/getter方法,但是分类指针结构
体中没有属性列表所以在分类中声明@Property无法生成_成员变量和setter/getter,只要不调用在分类中
声明的属性就不会报错;
2.手动添加setter/getter来避免崩溃,完成调用,由于OC是动态语言,方法真正实现是通过runtime实现的;
objc_setAssociatedObject(
"<#id _Nonnull object#>", 添加属性的主题"self";
"<#const void * _Nonnull key#>", key值;
"<#id _Nullable value#>", 属性名称;
"<#objc_AssociationPolicy policy#>", 保存类型)
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, assign,给关联对象指定弱引用;
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, nonation&retain|strong,给关联对象非原子的强引用;
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, nonation©,给关联对象指定非原子的copy特性;
OBJC_ASSOCIATION_RETAIN = 01401, retain|strong,给关联对象指定原子强引用
OBJC_ASSOCIATION_COPY = 01403 copy,给关联对象指定原子的copy特性;
};
-------------------------------------------------------------------------------------------
#import <objc/runtime.h>
// 定义一个key值
struct const NSString *categoryKey = @"categoryKey";
key的值也可以使用@selector(name)
@implementation Programmer (Category)
// 运行时实现setter方法
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, &categoryKey, name, OBJC_ASSOCIATION_COPY);
}
//运行时实现getter方法
- (NSString *)name {
return objc_getAssociatedObject(self, &categoryKey);
}
@end
------------------------------------------------------------------------------------------
问题解决
需要注意的是以上代码只是手动实现了setter/getter方法,只能self.name调用,当调用
'_成员变量'即:'_name'时任然报错.
Extension 扩展
1.Extension是Category的一个特例,类扩展与分类的相比只是少了分类名称,没有.m实现文件,所以称之为"匿名分类";
2.为一个类添加额外的变量,属性和方法;
@interface xxx ()
xx私有属性
xx私有方法,需要在本类.m中实现,否则提示警告"Method definition for xxx not found"
@end
Category(分类)和Extension(扩展)的区别?
1.Category分类原则上只能添加方法,通过runtime手动实现setter/getter方法可以添加属性,是能用.语法调用不能_属性调用;
2.Extension扩展可以添加属性,方法和实例变量;
3.扩展中添加方法没有在本类.m中实现编译器会报警告,而分类中不会,因为扩展是编译过程中添加到类中,而分类是运行时添加到类中;
4.类扩展没有.m文件,添加的方法必须依托本类实现;
@Protocol和Category中如何使用@Property?
Category添加@Property:
Category可以声明属性但是不能生成setter/getter,需要通过runtime手动添加setter/getter实现@Property效果
@Protocol添加@Property:
在协议中使用属性,只会生成setter&getter的方法声明,在遵守该协议的类中,需要手动添加实例变量,并且需要实现
setter&getter方法
@interface XXX () <XXXDelegate> {
NSString *_xxx;
}
@end
@implementation XXX
1.自动实现
@synthesize xxx;
2.手动实现
- (void)setXXX:(NSString *)xxx {
_xxx = xxx;
}
- (NSString *)xxx {
return _xxx;
}
@end
八`循环引用是什么?如何避免?
1.子类父类
2.Block
3.Delegate
@property (nontomic, weak) id <XxxDelegate> xXXDelegate;
4.NSTimer