iOS 面试准备(一)

268 阅读6分钟

一 `weak和assign的区别?

什么情况下使用weak?

1.在ARC情况下,在有可能出现引用循环的情况下,往往要通过让其中一端使用weak来解决,比如delegate;
2.比如自身已经对其强引用的情况下,没有必要再次强引用,此时使用weak,如storyboard添加控件使用IBoutlet

weakassign的区别?

1.在ARC中weak和assign都弱引用声明关系,表示非拥有关系;
2.weak声明的对象在被释放之后,释放的时候把指针自动置为nil,再次调用该对象或者像该对象发消息,不会因为野指针造成crash;
3.assign可以用于非OC对象,修饰基本数据类型和结构体,weak只能用于修饰OC对象;

二`copy和strong的问题?

为什么NSString/NSArray/NSDictionarycopy关键字,如果用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,给关联对象指定非原子的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.ExtensionCategory的一个特例,类扩展与分类的相比只是少了分类名称,没有.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