iOS面试题总结(一)

1.为什么不能给类别category 添加成员变量?extension呢?

2.isKindOfClass: 和 -isMemberOfClas区别?

3.weak的实现原理

4.理解 [self class] 与 [super class] ?

5.ios中的内存管理机制

6.Block如何访问外部变量? 下划线__block的作用? 如何防止循环引用?

7.Block循环引用问题
(1).为什么Msonry不会循环引用?
(2).weakSelf、strongSelf结合使用

8.深拷贝与浅拷贝

9.KVO实现原理

10.Runtime的原理及实际使用场景

讲解

1.为什么不能给类别category 添加成员变量?extension呢?
分类并不会改变原有类的内存分布的情况,它是在运行期间决定的,此时内存的分布已经确定,若此时再添加实例会改变内存的分布情况,这对编译性语言是灾难,是不允许的。
category 是基于运行时的:

typedef struct category_t {
const char *name; //类的名字
classref_t cls; //类
struct method_list_t *instanceMethods; //category中所有给类添加的实例方法的列表
struct method_list_t *classMethods; //category中所有添加的类方法的列表
struct protocol_list_t *protocols; //category实现的所有协议的列表
struct property_list_t *instanceProperties; //category中添加的所有属性
} category_t;

结构体中并没有成员变量这个list,所以无法在category添加成员变量,添加属性是可以的,但是不会生成添加属性的getter和setter方法,所以,尽管添加了属性,也无法使用点语法调用getter和setter方法,但你可以使用运行时实现关联对象并可以引用。

反观扩展(extension),作用是为一个已知的类添加一些私有的信息,必须有这个类的源码,才能扩展,它是在编译器生效的,所以能直接为类添加属性或者实例变量。

category跟extension最大的区别在于生效时间不一样,category在运行时生效,而extension在编译时生效

2.isKindOfClass: 和 -isMemberOfClas区别?
isKindOfClass来确定一个对象是否是一个类的成员,或者是派生自该类的成员。一个实例对象的类对象或类对象的元类是否与当前类相等,或派生自当前类)
isMemberOfClass只能确定一个对象是否是当前类的成员。(一个实例对象的类对象或类对象的元类是否与当前类相等
详解
类方法+ (BOOL)isKindOfClass:(Class)cls
元类 --> 根元类 --> 根类 --> nil 与 传入类的对比
这里会先取类对象的isa (self->ISA()),类对象的isa指向的是元类,判断元类是否与cls相等,而且这里是一个for循环,不相等的话会往元类的父类(tcls = tcls->superclass)循环去查找对比。
实例方法- (BOOL)isKindOfClass:(Class)cls
对象的类 --> 父类 --> 根类 --> nil 与 传入类的对比
这里是先取实例对象的isa ([self class]),也就是类对象,判断类对象与cls是否相等,不相等的话会往类对象的父类(tcls = tcls->superclass)循环去查找对比。

类方法+ (BOOL)isMemberOfClass:(Class)cls
类的元类 与 传入类 对比
判断的是类对象的isa(即元类)是否等于cls。
实例方法- (BOOL)isMemberOfClass:(Class)cls
对象的父类 与 传入类 对比
判断的是实例对象调用class方法的返回值(也就是类对象)是否与cls相等。
iOS 捋清楚 isKindOfClass 与 isMemberOfClass
iOS 底层原理探索之 isKindOfClass & isMemberOfClass

3.weak的实现原理

weak是Runtime维护了一个hash(哈希)表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。

对象准备释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。

        A.x = B;
 __weak B.y = A;

当A释放时,会根据A的地址获取所有弱引用它的指针的地址(如B.y),把它置为nil。
4.理解 [self class] 与 [super class] ?

我们知道实际上在iOS中,对方法的调用是通过发送消息来完成的。也就是说使用 [self class] 时,会使用obj_msgSend(id theReceiver, SEL selector, ...)函数向Receiver来发送消息。而使用 [super class] 时,会使用obj_msgsendSuper(...)函数向Receiver来发送消息。
————————————————

@implementation Son : Father 
- (id)init 
{ 
self = [super init]; 
if (self) { 
NSLog(@”%@”, NSStringFromClass([self class])); 
NSLog(@”%@”, NSStringFromClass([super class])); 
} 
return self; 
} 
@end

上边代码会输出什么,为什么
简单来说,self和super都是指向当前实例的,不同的是,[self class]会在当前类的方法列表中去找class这个方法,[super class]会直接开始在当前类的父类中去找calss这个方法,两者在找不到的时候,都会继续向祖先类查询class方法,最终到NSObject类。那么问题来了,由于我们在Father和Son中都没有去重写class这个方法,最终自然都会去执行NSObject中的class方法,结果也自然应该是一样的。
至于为什么是Son,我们可以看看NSObject中class的实现:

-(Class)class { 
return object_getClass(self); 
}

5.ios中的内存管理机制
为了管理所有对象的引用计数和weak指针,苹果创建了一个全局的SideTables,虽然名字后面有个"s"不过他其实是一个全局的Hash表,里面的内容装的都是SideTable结构体而已。它使用对象的内存地址当它的key。管理引用计数和weak指针就靠它了。

图片.png

6.Block如何访问外部变量? 下划线__block修饰auto变量的作用? 如何防止循环引用?
auto变量含义:离开作用域(大括号),会自动释放的变量

  • block在访问auto变量(局部变量)时,block内部会捕获到外部变量的值,后面修改外部auto变量的值,block内部的值不会随着改变而改变

  • block在访问static变量(局部变量)时,block内部会捕获到外部变量的地址值,所以后面修改外部static变量值的时候,通过地址访问到的是最新修改后的值。

  • 当auto变量加了__block修饰,编译器会将__block变量包装成一个对象,会捕获到block内部,并进行指针传递,所以能够修改其值(类似于访问static变量)。

另外,静态变量、全局变量和全局静态变量,传入的就是地址值,可以直接被block修改

  • 为了避免循环引用,最好的是对block内部引用的self对象进行弱引用。一般使用一个弱指针来指向该对象,然后在block内使用该弱引用指针来进行操作,这样就避免了block对该对象的强引用。

7.Block循环引用问题
(1).为什么Msonry不会循环引用?
查看masonry源码可以看到究竟:msonry中设置布局的方法中的block对象并没有被View所引用,而是直接在方法内部同步执行,执行完以后block将释放,其中捕捉的外部变量的引用计数也将还原到之前。
(2).weakSelf、strongSelf结合使用
使用weakSelf结合strongSelf的情况下,能够避免循环引用,也不会造成提前释放导致block内部代码无效(野指针问题)

_person1 = [[Person alloc] init];
_person2 = [[Person alloc] init];
_person2.name = @"张三";
__weak __typeof(self) weakSelf = self;
_person1.block = ^{
    __typeof(&*weakSelf) strongSelf = weakSelf;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"%@",strongSelf.person2.name);
    });
};

8.深拷贝与浅拷贝
浅拷贝就是拷贝之后,并没有真正的复制,而是复制对象和原对象都指向同一个地址
深拷贝是真正的复制了一份,复制的对象只想新的地址

9.KVO实现原理
当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制。
当观察对象A时,KVO机制动态创建一个新的名为NSKVONotifying_A的新类,该类集成字对象A的本类,且KVO为NSKVONotifying_A重写观察属性的setter方法,setter方法会负责在调用元setter方法之前和之后,通知所有观察对象属性值的更改情况。
被观察属性发生改变之前,willChangeValueForkey:被调用,通知系统该keyPath的属性值即将变更;当改变发生后,didChangeValueForkey:被调用,通知系统该keyPath的属性值已经变更;之后,observeValueForKey:ofObject:context:也会被调用。且重写观察属性的setter方法这种继承方式的注入是在运行时而不是编译时实现的。

10.Runtime的原理及实际使用场景
主动使用
1.字典转模型
2.给分类属性添加get,set方法
3.方法交换swizzling
4.设置UITextField占位文字的颜色
···

隐式调用
1.KVO与KVC的实现。
2.内存管理,weak表的维护。
···

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352