iOS 常见面试题总结

1. 空指针、野指针以及僵尸对象的理解,如何避免野指针错误。
解答:内存被释放的对象为僵尸对象(不能再使用的对象)。指向僵尸对象(不可用内存)的指针为野指针,给野指针发送消息会报EXC_BAD_ACCESS错吴。没有指向任何存储空间的指针为空指针,里面存的是nil,给空指针发送消息不会报错。一般在对象被销毁后,将指针对象的指针变为空指针来避免野指针错误。

2. nil、Nil、NULL、NSNULL的含义和区别?
解答:nil代表OC中对象的空指针、Nil代表OC中类的空指针、NULL代表C类型的空指针、NSNull基本数据类型的空指针。

//定义某一实例对象为空值
NSObject *obj;
if (nil == obj) {
    NSLog(@"obj is nil");
} else {
    NSLog(@"obj is not nil");
}

//定义某一个类为空
Class someClass = Nil;  
Class anotherClass = [NSString class];

//NULL是无类型的,只是一个宏,它代表为空。用于c语言的各种数据类型的指针为空
int *pointerToInt = NULL;
char *pointerToChar = NULL;
struct TreeNode *rootNode = NULL;

//集合对象无法包含 nil 作为其具体值,如NSArray、NSSet和NSDictionary。相应地,nil值用一个特定的对象 NSNull 来表示。NSNull 提供了一个单一实例用于表示集合对象属性中的的nil值。
NSDictionary *dic = @{@"testNull": [NSNull null]};
NSLog(@"%@", dic);

3. 在block内如何修改block外部变量?
解答:block可以直接修改全局变量,包括static修饰过的静态变量,因为全局变量内存是存放在堆中。不能直接修改局部变量,需要在局部变量前加标识位__block修饰,局部变量内存是存放在栈中的,__block就把内存由栈区放在堆区。

4.使用block时什么情况会发生引用循环,如何解决?
解答:当我们再代码中声明block时,声明的对象都会以copy的形式持有block,而block对于它内部的对象也会进行强引用,从而导致了循环引用。

self -> block -> self/实例变量
局部变量 -> block -> 局部变量
实例变量 -> block -> 实例变量

在使用block进行回调时,出现这样的情况是难免的,有时候可能还会在block内部强引用多个实例变量和self,解决的办法是一样的,即在block的内部使用弱引用修饰符__weak。

__weak typeof(self) weakSelf = self;

引深问题1:是不是所有的block中,使用self都会导致循环引用?
解答:并不是。使用系统自带的block不会引起循环引用。举个例子,使用系统自带的UIView动画block,block里直接使用self,控制器是能够被销毁的。说明没有造成循环引用。 原因是UIView的调用的是类方法,当前控制器不可能强引用一个类 ,所以循环无法形成, 动画block不会造成循环引用的原因。

5.block什么时候需要构造循环引用?有没有这样一个需求场景,block 会产生循环引用,但是业务又需要你不能使用 weak self? 如果有,请举一个例子并且解释这种情况下如何解决循环引用问题。
解答:需要不使用 weak self 的场景是,你需要构造一个循环引用,以便保证引用双方都存在。比如你有一个后台的任务,希望任务执行完后,通知另外一个实例。在我们开源的 AFN 网络库的源码中,就有这样的场景。
在 AFN3之前库中,我们的每一个网络请求 API 会持有回调的 block,回调的 block 会持有 self,而如果 self 也持有网络请求 API 的话,我们就构造了一个循环引用。虽然我们构造出了循环引用,但是因为在网络请求结束时,网络请求 API 会主动释放对 block 的持有,因此,整个循环链条被解开,循环引用就被打破了,所以不会有内存泄漏问题。代码其实很简单,如下所示:

block = nil;

总结来说,解决循环引用问题主要有两个办法:
第一个办法是「事前避免」,我们在会产生循环引用的地方使用 weak 弱引用,以避免产生循环引用。
第二个办法是「事后补救」,我们明确知道会存在循环引用,但是我们在合理的位置主动断开环中的一个引用,使得对象得以回收。

5.instancetype与id的区别?
解答:instancetype和id都表示未知类型的对象,本质也是指向一个对象。
(1)id在编译的时候不能判断对象的真实类型,instancetype在编译的时候可以判断对象的真实类型。
(2)id和instancetype除了一个在编译时不知道真实类型, 一个在编译时知道真实类型以外, 还有一个区别id可以用来定义变量,可以作为返回值,可以作为形参。而instancetype只能用于作为作为返回值。
(3)如果init方法的返回值是instancetype, 那么将返回值赋值给一个其它的对象会报一个警告, 如果init方法的返回值是id,那么将init返回的对象地址赋值给其它对象是不会报错的,自定义构造方法时,返回值尽量使用instancetype, 不要使用id。

6.Objective-C有GC(垃圾回收机制)吗?
解答:OC是支持垃圾回收机制的(Garbage collection简称GC)。macOS开发中是支持的,18.8之后弃用了GC。iOS开发中是不支持的。iOS开发只支持手动内存管理(MRC)和ARC,ARC是iOS5之后推出的新技术,它与GC的机制是不同的。


引深问题1:Objective-C回收机制的特点和区别与GC?
解答:ARC 的特点是自动引用技术简化了内存管理的难度,我们在编写代码时, 不需要向对象发送release或者autorelease方法,也可以不调用delloc方法,编译器会在合适的位置自动给用户生成release消息(autorelease)。
区别:ARC介于自动垃圾回收(GC)和手动内存管理(MRC)之间。就像垃圾回收,ARC让程序员不再需要书写retain/release/autorelease语句。但它又不同于垃圾回收,ARC无法处理retaincycles。在ARC里,如果两个对象互相强引用(strong references)将导致它们永远不会被释放,甚至没有任何对象引用它们。因此,尽管ARC能免去程序员大部分内存管理问题,但仍然要程序员自己避免retaincycles或手动打断对象之间的retain循环。

7.Objective-C是如何实现内存管理的?autorealease pool自动释放池是什么?autorelease的对象是在什么时候被release的?autorelease和release有什么区别?
  内存管理主要有三种方式ARC(自动引用计数)、MRR(手动内存计数)、内存池(自动释放池)。
  引用计数(Reference Count)是一个简单而有效的管理对象生命周期的方式,一般概念是:当创建一个新的对象时,初始的引用计数为1。为保证对象的存在,每当创建一个引用到该对象时,通过给对象发送retain消息,为引用计数加1;当不再需要对象时,通过给对象发送release消息,为引用计数减1;当对象的引用计数为0时,系统就知道这个对象不再使用了,通过给对象发送dealloc消息,销毁对象并回收内存。一般在retain方法之后,引用计数通常也被称为保留计数(retain count)。
  手动管理内存,即MRR(manual retain-release),是基于引用计数来实现的,通过自己跟踪对象来明确管理内存。它与ARC之间的唯一区别是:在MRR中,对象的保留和释放都是由我们手动处理,而在ARC中是自动处理的。
  自动释放池(autorealease pool):是一种半自动内存管理方式,具有延时释放的特性。即当我们创建了一个对象,并把他加入到了自动释放池中时,他不会立即被释放,会等到一次runloop结束或者作用域超出{}或者超出[pool release]之后再被释放。

8.在一个对象释放前,如果他被加到了notificationCenter 中,不在notificationcenter中remove这个对象可能会出现什么问题?
解答:对象被release,会导致出现野指针错误。

9.为什么很多内置类如UITableView的delegate属性都是assign而不是retain ?
  如果是retain会引起循环引用。
  所有的引用计数系统,都存在循环引用的问题。例如下面的引用关系:对象a创建并引用了对象b,对象b创建并引用了对象c,对象c创建并引用了对象b.这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b。所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用,通过其他规则来维护引用关系。
  比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。

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

推荐阅读更多精彩内容

  • 1.objective-c常见面试题:1、**OC **语言的基本特点OC 语言是 C 语言的一个超集,只是在 C...
    LZM轮回阅读 955评论 0 3
  • 最近由于换工作的原因,需要参加面试,然后就到处收集了一些当下的面试题供自己复习使用。下面就分享出来,希望能够帮到你...
    wuyukobe阅读 2,107评论 3 26
  • 把网上的一些结合自己面试时遇到的面试题总结了一下,以后有新的还会再加进来。 1. OC 的理解与特性 OC 作为一...
    AlaricMurray阅读 2,520评论 0 20
  • 1.堆和栈的区别 管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容...
    顺义coder阅读 282评论 0 0
  • BAD_ACCESS在什么情况下出现? 访问了野指针,比如对一个已经释放的对象执行了release、访问已经释放对...
    sunnyxg0812阅读 1,651评论 0 2