面试题IOS开发知识点

iOS-100

2020-05-18  本文已影响0人  mpyl
1.Runloop和线程的关系

1、一一对应,主线程的 runloop 已经创建,子线程的必须手动创建。
2、runloop 在在第一次获取时创建,在线程结束时销毁
系统默认注册 5 个 Mode:
kCFRunLoopDefaultMode、UITrackingRunLoopMode、NSRunLoopCommonModes

2.自动释放池什么时候释放?

第一次创建:启动 runloop 时候
最后一次销毁:runloop 退出的时候
其他时候的创建和销毁:当 runloop 即将睡眠时销毁之前的释放池,重新创建一个新的。

3.什么情况下使用 weak 关键字,和 assign 的区别?

1、ARC中,循环引用的地方
2、自定义 IBOutlet 控件属性
区别:weak 非持有关系 必须用于OC对象,assign 用于基本数据类型

4.怎么用 copy 关键字

1、NSString、NSArray、NSDictionary经常使用 copy 关键字,为了确保他们的可变类型之间进行赋值时,对象中字符串值不会随意变动,设置新属性时拷贝一份。
2、block 也使用 copy

5.@property (copy) NSMutableArray *array; 这种写法会出什么问题?

1、添加,删除数组内元素时崩溃,因为 copy 复制了一个不可变的 NSArray
2、默认使用了 atomic 属性 严重影响性能

6.如何让自己的类用 copy 修饰符,即让对象具备拷贝功能

具体步骤:
1、让该类遵从 NSCopying 或 NSMutableCopying 协议
2、实现 NSCopying 协议,该协议只有一个方法:- (id)copyWithZone:(NSZone *)zone;

7.@property 的本质是什么?ivar、setter、getter如何生成并添加到类中的?

本质:实例变量+getter方法+setter方法
在编译期自动生成 getter 和 setter,还自动向类中添加适当类型的实例变量

8.多线程

1、NSThread线程的生命周期:线程任务执行完毕之后被释放。
2、线程安全(加互斥锁):防止多线程抢夺资源造成的数据安全问题,但是耗费 CPU 性能

3、线程间通信

4、GCD(任务、队列)

9.@protocol 和 category 中如何使用@property?

1、在 protocol 中使用 property 只会生成 getter 和 setter 的方法声明,目的是为了遵循该协议的对象实现该属性。
2、category 也只是生成方法声明,如果真要增加属性实现需要借助两个函数:

10.@property 中有哪些属性关键字?

1、原子性:nonatomic 特质
2、读/写权限: readwrite(读写)、readonly(只读)
3、内存管理语义:assign、strong、weak、copy、unsafe_unretained
4、方法名:getter=<name>、setter=<name>

11.weak 属性需要在 delloc 中置 nil 吗?

不需要,ARC会帮我们处理,即使编译器不帮忙,runtime 内部已经实现了

12.@synthesize 和 @dynamic 分别有什么作用?

@property 对应这两个,没写就默认@synthesis var = _var
1、@synthesize 语义就是编译器自动帮你实现 getter、setter
2、@dynamic 就是告诉编译器不要自动生成,自己要手动实现 getter、setter

13.ARC下,不显式指定属性关键字,默认的关键字有哪些?

1、基本数据类型:atomic、readwrite、assign
2、普通 OC 对象:atomic、readwrite、strong

14.用@property 修饰的 NSString(或NSArray、NSDictionary)经常使用 copy 关键字,为什么?换成 strong 会怎样?

1、因为父类指针可以指向子类对象,使用的 copy 的目的是为了对象的属性不受外界影响,不管你传入的是可变还是不可变对象,我本身持有的是一个不可变的副本。
2、copy 和 mutableCopy

15.@synthesize 合成实例变量的规则是什么?

规则:
1、如果指定了成员变量的名称,会生成一个指定名称的成员变量
2、如果这个成员已经存在了就不在生成
3、如果 @synthesize foo;还会生成同名的成员变量,如果 @synthesize foo = _foo; 就不会再生成了。

16.除了自动合成属性实例变量外,@synthesize 还有那些使用场景

1、重写只读属性的 getter 时
2、使用了 @dynamic 时
3、在 @protocol 中定义的所有属性
4、在 category 中定义的所有属性

17.objc 中向一个 nil 发送消息会发送什么?

在 Objective-C 中向 nil 对象发送消息是完全有效的,只是在运行时没有任何作用

18.objc 中向一个对象发送消息 [obj foo] 和 obj_msgSend()函数之间有什么关系

[obj foo];在 objc 动态编译时,每个方法在运行时都会被动态的转为消息发送,即为: objc_msgSend(obj, @selector(foo));

19.什么时候会报 unrecognized selector 的异常?

当调用对象上的某个方法时,而发现对象没有实现这个方法
objc 在向一个对象发送消息时,runtime 库会根据对象的 isa指针找到该对象所属的类,然后在该类的方法列表和其父类方法列表中寻找方法运行,如果在最顶层的父类也没有找到对应方法,程序就会在运行时挂掉并抛出异常 unrecognized selector

20.一个 objc 对象如何进行内存布局?

1、所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中。
2、每一个对象内部都有一个 isa 指针,指向它的类对象
3、类对象中存放着本对象的:

21.一个 objc 对象的 isa 指针指向什么?有什么作用?

指向它的类对象,从而找到对象上的方法

22.runtime 如何通过 selector找到对应的 IMP 地址?

每个类对象都有一个方法列表,方法列表上记录着方法名称、方法实现、参数类型,selector 本质上就是方法名称,通过这个方法名称就可以在方法列表上找到对应的方法实现。

23.使用 runtime Associate 方法关联的对象,需要在主对象 dealloc 的时候释放吗?

无论在 ARC 还是 MRC 下均不需要
被关联的对象在生命周期内要比对象本身释放的晚很多,他们会在 NSObject -dealloc 调用的 objc_dispose() 方法中释放。

24.objc 中的类方法和实例方法有什么本质区别和联系?

1、类方法

2、实例方法

25._objc_msgForward 函数是做什么的,直接调用它会发生什么?

_objc_msgForward 是一个函数指针(和 IMP 类型一样),用于消息转发的:当向一个对象发送一条消息,它并没有实现的时候,_objc_msgForward 就会尝试做消息转发。

26.runtime 如何实现 weak 变量的自动置 nil ?

runtime 对注册的类会进行布局,对于 weak 对象会放入一个 hash 表中。用 weak 指向的对象内存地址作为 key,当此对象的引用计数变为 0 时候会 dealloc,此时用这个 key 在 hash 表找到 weak 对象置 nil。

27.能否向编译后得到的类中增加实例变量?能否在运行时创建的类中添加实例变量?为什么?

1、不能向编译后得到的类中增加实例变量
2、能向运行时创建的类中添加实例变量
3、因为编译后的类已经在 runtime 中注册,实例变量的内存大小已经确定
4、运行时创建的类可以调用 class_addIvar 函数来添加实例变量

28.runloop 和线程有什么关系

runloop 是线程的基础架构部分,每个线程包括程序主线程都有与之对应的 runloop 对象。
1、主线程的 runloop 默认是启动的
2、其他线程的 runloop 需要手动配置和启动
3、当前线程的 runloop 可以NSRunLoop *runloop = [NSRunLoop currentRunLoop];获取

29.runloop 的 mode 作用是什么?

mode 主要是用来指定事件在运行循环中的优先级的,分为:

苹果公开提供的有:

30.以 scheduledTimerWithTimeInterval 的方式触发的 Timer,在滑动页面列表时,timer 会暂停回调,为什么?如何处理?

1、runloop 只能运行在一种 mode 下,NSTimer 在主线程运行,处于的 mode 是 NSDefaultRunLoopMode,滑动页面是 需要切换到 UITrackingRunLoopMode 保证滑动流畅,这就导致 NSTimer 不被继续调度。
2、可以讲 timer 添加到 NSRunLoopCommonModes 来解决问题

31.猜想 runloop 内部是如何实现的?

一般来讲,一个线程只执行一个任务,执行完成后线程就会退出。如果需要一个机制,让线程随时处理任务但并不退出,通常的代码逻辑就是 do while 循环,只要传递的消息不为 nil,就一直循环下去。

32.objc 使用什么机制管理对象内存?

通过 retainCount 机制来决定对象是否需要释放。每次 runloop 的时候,都会检查对象的 retainCount,为0的话说明没地方使用需要使用个对象了,可以释放了

33.ARC 通过什么方式帮助开发者管理内存?

主要在编译期和运行期两部分共同帮助开发者管理内存
1、编译期,ARC 用的是更底层的 C接口实现的 retain、release、autorelease
2、ARC 也包含运行期组件,这个地方做的优化比较复杂,但也不能忽略

34.BAD_ACCESS 在什么情况下出现?

访问了野指针,

35.使用 block 时,什么情况会出现循环引用,如何解决?

一个对象强引用了 block,block 又强引用了对象,就会发生循环引用。
解决方法就是使用 __weak 或者 __block 修饰符修饰之后再在 block 中使用。

36.在 block 内如何修改 block 外部变量?

block 不允许修改外部变量的值(栈中指针的内存地址),__block只要观察到该变量被 block 所持有,就将“外部变量” 栈中内存地址放到堆中,block 内部变量会被 copy 到堆区,进而在 block 内部可以修改外部变量的值。

37.苹果是如何实现 autoreleasepool 的?

autoreleasepool 是以一个队列数组的方式实现,主要通过下列3个函数:

38.不手动指定 autoreleasepool 的情况下,一个 autorelease 对象什么时候释放?

分两种情况:手动干预释放时机、系统自动去释放
1、手动干预释放时机:当前作用域大括号结束时释放
2、系统自动去释放:autorelease 对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前 runloop 迭代结束时释放。

39.使用系统的某些 block API 时,是否也要考虑循环引用?

UIView 的 block版本写动画时不需要考虑,因为 循环引用是双向的强引用,而他们是单向强引用。
GCD 和 NSNotificationCenter 时需要小心,比如 GCD 内部引用了 self

40. GCD 的队列(dispatch_queue_t)分哪两种类型?

1、串行队列( Serial Dispatch Queue)
2、并行队列(Concurrent Dispatch Queue)

41.如何用 GCD 同步若干个异步操作?

异步加载多张图片,然后在都下载完成后合成一张整图
使用 Dispatch Group 追加 block 到 Dispatch Group queue 中
,这些 block 如果都执行完毕,就会执行 Main Dispatch Queue 中的 结果处理的block

dispatch_queue_t queue  = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{   /*加载图片1*/ });
dispatch_group_async(group, queue, ^{   /*加载图片2*/);
dispatch_group_async(group, queue, ^{   /*加载图片3*/});    
dispatch_group_notify(group,    dispatch_get_main_queue(), ^{                               
      // 合并图片
});
42.dispatch_barrier_async 的作用是什么?

在并行队列中,barrier 能够保持某些任务的顺序,避免数据竞争等问题。
注意:barrier 只能搭配自定义并行队列,不能使用 global_queue,否则 dispatch_barrier_async 和 dispatch_async 作用一样。

43.苹果为何废弃 dispatch_get_current_queue?

dispatch_get_current_queue 容易造成死锁

44.addObserver:forKeyPath:options:context:各个参数的作用分别是什么?observer 需要实现哪个方法才能获得 KVO 回调?
// 添加键值观察
/*
1.观察者,负者监听事件的对象
2.观察的属性
3.观察的选项
4.上下文
*/
[self.person addObserver:self 
  forKeyPath:@"name" 
  options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 
  context:@"Person Name"];

observer 中需要实现一下方法:

// 所有的 kvo 监听到事件都会调用此方法
/*
1.观察的属性
2.观察的选项
3.change 属性变化字典(新 / 旧)
4.上下文,与监听的时候传递的一致
*/
- (void)observeValueForKeyPath:(NSString *)keyPath 
    ofObject:(id)object 
    change:(NSDictionary *)change 
    context:(void *)context;
 
45.如何手动触发一个 value 的 kvo?
46.如果一个类有成员变量 NSString *_foo,调用 setValue:forKey: 时,可以以 foo 还是 _foo 作为 key ?

都可以

47.KVC 的 keyPath 中集合运算符如何使用?

1、必须在集合对象上或普通对象的集合属性上
2、简单集合运算符有:@avg、@min、@max、@sum
3、格式:@"@sum.age" 或者 @"集合属性.@max.age"

48.KVC 和 KVO 的 keyPath 一定是属性吗?
49.如何关闭默认的 KVO 的默认实现,并进入自定义的 KVO 实现?

利用 runtime 动态创建类、实现 KVO

50.苹果用什么方式实现对一个对象的KVO?

Apple 使用了 isa 混写(isa-swizzling)来实现 KVO

51.IBOutlet 连出来的视图属性为什么可以被设置成 weak?

因为有外链那么视图在 xib 或 storyboard 中肯定存在,视图已经对它有一个强引用了。

52.IB 中的 User Defined Runtime Attributes 如何使用?

它能够通过 KVC 的方式配置一些你在 interface builder 中不能配置的属性。通过他可以编写更轻量级的 viewController

53.如何调试 BAD_ACCESS 错误?
54.lldb(gdb)常用的调试命令?
55.iOS 容易引起“循环引用”的几种场景

最简单的理解:对象A持有对象B,对象B又持有对象A,就会造成循环引用
1、parent-child 相互持有、委托模式
2、block:隐式(间接)循环引用,A 持有 B,B 持有 block。那么在 block 中调用 A 的 self 会造成间接循环引用。显式循环引用,编译器会报警告,在 block 中引用 self 的时候最好使用 weak-strong dance 技术
3、NSTimer:它会持有对象,所以删除对象前要执行 [time invalidate]
4、把 self 加入到 Array 中,也会造成循环引用。
5、使用类别添加属性:给一个类A动态添加属性P,P中又引用类A,容易造成循环引用

56.类方法 load 和 initialize 的区别

iOS 会在运行期提前并且自动调用这两个方法。

que +(void)load +(void)initialize
执行时机 在程序运行后立即执行 在类的方法第一次被调时执行
是否沿用父类的方法
类别中的定义 全都执行,但后于类中的方法 覆盖类中的方法,只执行一个

当类对象被引入项目时,runtime 会向每一个类对象发送 load 消息。它会在被引入时仅调用一次,顺序是父类优先于子类,子类优先于类别, 而且 load 方法不会被类自动继承

57.HTTP 和 HTTPS
http 与 https
网络分层

区别:
1、HTTPS 是加密传输协议,需要 SSL证书;HTTP 是明文传输协议,不需要
2、HTTPS 的标准端口443,HTTP 的标准端口80
3、HTTPS 基于传输层,HTTP 基于应用层

58.常见的 Exception Type

1、EXC_BAD_ACCESS
访问了不该访问的内存导致

2、EXC_BAD_INSTRUCTION
此类异常通常是线程执行非法指令导致的
3、EXC_ARITHMETIC
除零错误会抛出此类异常

59.Category 和 Extension

Category 为原始类添加方法,注意不要去重写已经存在的方法
Extension 管理类的私有方法

60.响应者链(respond chain)
响应者链

如上图,响应者链有以下特点:

事件的链有两条:

61.UITableView 优化

1、重用 cell
2、缓存行高
3、加载网络数据,下载图片,使用异步加载,并缓存
4、使用局部刷新,尽量不要使用 reloadData
5、渲染,尽量少用或不用透明图层
6、少用 addSubView 给 Cell动态添加 子View,初始化直接设置好,用 hidden 控制显隐
7、使用异步加载 web 内容,缓存请求结果
8、按需加载 cell,cell 滚动很快时,只加载范围内的 cell
9、遇到复杂界面,像朋友圈涉及图文混排,需要异步绘制

62.离屏渲染(OffScreen-Renderd)

引发离屏渲染的情况和操作:

优化方案:

63.UIView 和 CALayer

联系:

区别:

64.TCP 和 UDP

TCP:传输控制协议,提供的是面向连接、可靠的字节流服务。
UDP:用户数据包协议,是面向数据报的运输层协议。
tcp协议和udp协议的差别:

TCP 的三次握手:

65.socket 和 http

socket连接和http连接的区别:
http 是基于 socket 之上的,socket 是一套完成 tcp,udp 协议的接口。
HTTP协议:简单对象访问协议,对应于应用层,HTTP协议是基于TCP连接的。
TCP协议:对应于传输层
IP协议:对应于网络层
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
Socket是对 TCP/IP协议的封装,Socket 本身并不是协议,而是一个调用接口,通过Socket 我们才能使用 TCP/IP 协议。
http连接:短连接,请求一次完成响应后会主动释放连接即断开
Socket连接:长连接,理论上客户端与服务器一旦建立连接将不会主动断开。但由于各种因素可能会断开: 服务器或主机挂了、网络故障、防火墙切断等,所以需要发送心跳消息。

66.远程推送 APNS

远程推送的基本过程:
1、客户端的 app 用 UDID 和 bundleID 向 apns服务器请求 device Token
2、app 获得到 device Token 后上传到公司服务器
3、需要推送通知时,将 推送内容和device Token一起发送给 apns服务器
4、apns 再将推送内容推送到相应的客户端app上

67.iOS 应用程序生命周期
iOS 程序启动原理(过程)
AppDelegate 执行顺序

1、应用程序的状态

状态 注释 说明
Not running 未运行 程序没有启动
Inactive 未激活 程序在前台运行,但未接收事件
Active 激活 程序在前台运行且接收到了事件
Backgroud 后台 程序在后台运行且能执行代码
Suspended 挂起 程序在后台不能执行代码

2、UIApplicationMain

UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
/*
  argc:系统或者用户传入的参数个数
  argv:系统或用户传入的实际参数
  argc、argv:直接传递给 UIApplicationMain 进行相关处理即可。
  principalClassName:指定应用程序类名(app的象征)
  delegateClassName:创建并设置 UIApplicationMain 对象的代理,指定应用程序的代理类
  接着会建立应用的 Main runloop, 处理与用户交互产生的事件
*/
68.View 视图生命周期
阶段 方法调用
视图创建 viewDidLoad()
视图即将可见 viewWillAppear()
视图已经可见 viewDidAppear()
视图即将不可见 viewWillDisappear()
视图已经不可见 viewDidDisappear()
系统低内存 didReceiveMemory() 和 viewDidUnload()
69.autorelease pool(事件循环)

1、autorelease 的原理是什么?
autorelease 实际上只是把 release 的调用延迟了,系统只是把 autorelease 对象放入了当前 autorelease pool 中,当 pool 在释放时,会通知 pool 内所有对象调用 release。
2、autorelease 的对象何时释放?

3、NSAutoreleasePool 是什么?
NSAutoreleasePool 实际上是一个对象引用计数自动处理器,在官方文档被称为一个类。
每一个 autoreleasepool 只对应一个线程,每个线程都会维护自己的 autorelease pool 堆栈。
4、NSAutoreleasePool 和 autoreleasepool 的区别?

pool 作用时间 ARC
NSAutoreleasePool 作用于运行时 不可用
autoreleasepool 作用于编译时 @autoreleasepool

5、autorelease 作用:

6、@autoreleasepool
自己开启一个线程,需要创建自己的自动释放池块。当你的应用或者线程长时间存活,并可能产生大量的自动释放对象,此时应该手动创建自动释放池块。
在遇到需要大量创建对象的地方使用 autoreleasepool 可以加速对象的释放。

70.view layout

相关方法:

- (CGSize)sizeThatFits:(CGSize)size 
- (void)sizeToFit   
——————- 
- (void)layoutSubviews  
- (void)layoutIfNeeded  
- (void)setNeedsLayout  
——————– 
- (void)setNeedsDisplay 
- (void)drawRect

layoutSubviews 在以下情况会被调用:

layoutSubviews 调用时机
1 addSubview 时
2 设置 view 的 Frame 时
3 滚动 UIScrollView 时
4 旋转 Screen会触发父View上的layoutSubviews
5 改变一个UIView大小时也会触发父View的

刷新子对象布局:

刷新子对象布局 做什么
layoutSubviews 默认什么都不做,需要子类进行重写
setNeedsLayout 标记为需要重新布局,异步调用layoutIfNeeded,不立即刷新
layoutIfNeeded 如果有需要刷新的标记,立即调用 layoutSubviews 刷新布局

重绘:

重绘 作用
drawRect:(CGRect)rect: 重写此方法,执行重绘任务
setNeedsDisplay 标记为需要重绘,异步调用drawRect
setNeedsDisplayInRect:(CGRect)invalidRect 标记为需要局部重绘
sizeToFit 会自动调用 sizeThatFits
sizeThatFits 传入的参数是 receiver 当前的 size
layoutSubviews 对 subviews 重新布局,优先于 drawRect
drawRect 是对 receiver 的重绘,能获得 context
setNeedsDisplay 该方法在调用时,会自动调用 drawRect 来画图。
总结 说明
当需要刷新布局时 用 setNeedsLayOut 方法
当需要重新绘画时 调用 setNeedsDisplay 方法
71.应用程序的架构MVC、MVVM

MVC
遵循 Model-View-Controller 的架构

MVC 负责
Model 存储数据和处理业务数据
View 显示数据和用户交互
Controller 协调 Model 和 View 协作

他们的通讯规则如下:


Controller 能访问 Model 和 View,Model 和 View 不能互相访问
当 View 与用户交互产生事件时,使用 Target-Action 方式来处理
View 通过 delegate 和 data source 让 Controller 处理复杂UI逻辑和数据源
当 Model 有数据更新时,通过 Notification 或 KVO 通知 Controller 更新 View

MVVM
MVVM 就是在 MVC 的基础上分离出业务处理的逻辑到 ViewModel 层

MVVM 负责
Model API请求的原始数据,数据持久化
View 视图展示,由 viewController 来控制
viewModel 负责网络请求、业务处理和数据转化

简单来说,就是 API 请求玩数据之后,解析成 Model,之后在 viewModel 中转换成能够直接被视图层使用的数据,交付给前段。
经过 viewModel 转化的数据由 viewModel 保存,与数据相关的处理都将在 viewModel 中进行。viewModel 返回给 view层。
view层是由 Controller 控制的。view层只做展示,不做业务处理。view层的数据由 viewModel 提供。


MVVM
MVVM Application layer
MVVM
72.FMDB、SQLite

FMDatabaseQueue 用于在多线程执行多个查询和更新,它是线程安全的。
FMDatabase 这个类是线程不安全的,如果在多个线程中同时使用一个 FMDatabase 实例,会造成数据混乱等问题。

操作 语法
增表 create table t_student (id integer, name text, age inetger, score real);
删表 drop table t_student;
插入数据 insert into t_student (name, age) values ('mj', 10);
更新数据 update t_student set name = ‘jack’, age = 20;
删除数据 delete from t_student;
73.简述内存分区情况
分区 情况
代码区 存放函数二进制代码
数据区 存放全局变量、静态变量、常量
堆区 通过malloc或new动态申请,需要手动释放
栈区 存放局部变量、函数参数,函数模块内申请,函数结束时自动释放
74.各属性作用
属性 作用
readwrite 可读可写,需要生成 getter、setter 方法
readonly 只读,只生成 getter,不会生成 setter,不希望属性在类外部被更改
assign 赋值,setter 方法将传入的参数赋值给实例变量;仅设置变量时, assign 用于基本数据类型
retain 表示持有特性,setter 将传入的参数先保留,再赋值,传入参数的引用计数会加1
copy 表示赋值特性,setter 方法将传入的对象复制一份
nonatomic 非原子操作,决定编译器生成的 getter setter 是否是原子操作
atomic 原子操作,表示多线程安全,耗费资源,一般用 nonatomic
75.简述 Notification、KVC、KVO、delegate 的区别
方式 说明
Notification 观察者模式,发送者和接受者的关系是间接的,多对多的
delegate 发送者和接受者的关系是直接的,一对一的
KVO 一对多,观察者模式,键值观察机制,提供了观察某一属性变化的方法,极大地简化代码
KVC 键值编码,一个对象在调用 setValue
KVC 一个对象在调用 setValue
1 检查是否存在相应 key 的 set 方法,存在就调用 set 方法
2 set 方法不存在,就查找 _key 的成员变量是否存在,存在就直接赋值
3 如果 _key 没有找到,就查找相同名称的 key,存在就赋值
4 如果都没有找到,就调用 valueForUndefinedKey 和 setValue:forUndefinedKey
区别 区别
1 delegate 的效率比 NOtification 高
2 delegate 比 Notification 更直接,需要关注返回值,常常带有 should 关键字
3 Notification 不关注结果,常常带有 did 关键字
4 两个模块之间的联系不是很紧密,就用 Notification 传值,比如多线程之间的传值
5 KVO容易实现两个对象的同步,比如 Model 和 View 的同步
76. id 和 nil 代表什么?
77.nil、Nil、Null、NSNull

OC 中

区别 区别
Null 是宏,是对于 C 语言指针而使用的,表示空指针
nil 是宏,是对于 OC 中的对象而使用的, 表示对象为空
Nil 是宏,是对于OC 中的类而使用的,表示类指向空
NSNull 是类类型,是用于表示空的占位对象,与 JS 或服务端的 null 类似
78.向一个 nil 对象发送消息会发送什么?
返回类型 发送 nil 消息的返回值
对象 0(nil)
指针 指针大小小于等于 float,double 时,返回0
结构体 0,结构体中的各个字段也是0
79.self. 和 self-> 的区别
80.如何访问并修改一个类的私有属性?
81.如何为 class 定义一个对外只读,对内可读写的属性?

在头文件 .h 中将属性定义为 readonly,在 .m 中重新将属性定义为 readwrite

82.OC 中 meta_class 指的是什么?

meta-class 是 class 对象的类,为这个 class 存储类方法,当向一个类发送信息时,就去这个类的 meta-class 中查找那个消息,

83.NSString 用 copy 和 strong 的区别

用 copy 会判断是不是不可变字符串:

类型 是否分配
是不可变字符串 不分配空间
是可变字符串 分配空间

如果程序中用到的 NSString 特别多,这样的判断会很耗费性能,所以选择用 strong 修饰不可变字符串

84.创建一个对象的步骤

1、开辟内存空间
2、初始化参数
3、返回内存地址值

85.setter 和 getter
86.id 和 instancetype 是什么?有什么区别?
87.内存管理

ARC 所做的是在代码编译期自动在合适的位置插入 release 或 autorelease,只要没有强指针指向对象,对象就会被释放。ARC 中不能手动使用 NSZone,也不能调用父类的 dealloc。
1、调用对象的 release 方法会销毁对象吗?
不会,调用 release 只是将对象的引用计数-1,当对象的引用计数=0时,调用对象的 delloc 方法才能释放内存。
2、objc 通过什么机制管理内存?

3、内存管理的范围
管理所有继承自 NSObject 的对象,对基本数据类型无效。是因为对象和其他基本数据类型在系统中的存储空间不一样,其他局部变量主要存储在栈区,对象主要存储在堆中。代码块结束。栈自动清空,指向对象的指针也被回收,没有指针指向的对象依然存在于堆中造成内存泄漏
4、内存管理研究的对象

操作 引用计数
alloc̵、allocWithZone̵、new 引用计数 +1
retain 手动为该对象引用计数+1
copy 深拷贝对象引用计数为1,浅拷贝引用计数+1
release 手动为该对象引用计数-1
autorelease 放入自动释放池,池子释放时,给对象引用计数-1
autorelease 多次调用对象的 autorelease 方法会导致:野指针异常
88.KVC 的底层实现

当一个对象在调用 setValue 时,方法内部会做以下操作:

步骤 操作
1 检查是否存在相应 key 的 set 方法,存在就调用 set 方法
2 如果 set 方法不存在,就查找 _key 的成员变量是否存在,存在就直接赋值
3 如果 _key 没有找到,就查找相同名称的 key,存在就赋值
4 如果都没有找到,就调用valueForUndefinedKeysetValue:forUndefinedKey
89.block 的内存管理

无论 ARC 还是 MRC,只要 block 没有访问外部变量,block 就始终在全局区

90.app 的启动过程,从 main 说起

app 启动分两类: 有 storyboard 、无storyboard
有 storyboard 情况下:
1、main 函数
2、UIApplicationMain

3、根据 info.plist 加载 Main. storyboard

无 storyboard 情况下:
1、main 函数
2、UIApplicationMain

3、delegate 对象开始处理(监听)系统事件

91.tableView 的 cell 中如何嵌套 collectionView?

用自定义的继承自 UITableViewCell 的类,在 initWithFrame 中初始化自定义的继承自 UICollectionView 的类。

92.awakeFromNib 和 viewDidLoad 的区别

awakeFromNib:通过 .nib 文件创建的 view 对象会执行 awakeFromNib
viewDidLoad:当 view 被加载到内存就会执行,不过通过 nib 还是代码形式

93.常见的 Crash 场景
94.AFN 断点续传
95.客户端的缓存机制

缓存分为:内存数据缓存,数据库缓存、文件缓存

96.数据存储方式

4种数据持久化:属性列表(plist)、对象归档、SQLite、Core Data
NSUserDefaults 用于存储配置信息
使用 keychain 存储用户的敏感信息,如 token,需要导入 Security 框架
使用NSUserDefaults 时,如何处理布尔的默认值?

if ([[NSUserDefaults standardUserDefaults] objectForKey:@"key"] == nil) {
    NSLog(@"没有设置过");    
}
97.App 需要加载超大量的数据时,给服务器发送请求,但服务器卡住了,如何解决?
98.网络图片处理时如何避免相同的网络地址重复请求?

利用字典(图片地址为 key,下载操作为 value)

99.NSOperation、GCD、NSThread 的区别

NSOperation 和 GCD 的区别:
GCD:

NSOperation:

GCD 和 NSThread 的区别:

为什么要取消/恢复队列?

100.是否可以把比较耗时的操作放在 NSNotificationCenter 中?
上一篇下一篇

猜你喜欢

热点阅读