ui相关
uitableviewcell复用机制
比如tableview向上滚动,当顶部的cell划出屏幕,cell就会被加入复用池,当顶部的cell要出现在屏幕上的时候,调用cell的dequeueReusableCellWithIdentifier方法,去复用池拿一个cell,如果能拿到就使用这个cell,如果返回nil,就创建一个新cell使用uiview calayer区别
uiview提供内容,负责处理触摸事件,参与响应链
calayer负责显示内容,动画触摸事件传递机制&响应
找到hittestview
UIWindow->subView
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (self.userInteractionEnabled == NO || self.alpha < 0.01 || self.hidden == YES)
{
return nil;
}
if ([self pointInside:point withEvent:event])
{
__block UIView *hitView;
[self.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CGPoint covertPoint = [self convertPoint:point toView:obj];
hitView = [obj hitTest:covertPoint withEvent:event];
*stop = YES;
}];
if (hitView) {
return hitView;
}
return self;
}
return nil;
}
事件响应链
subview -> superview -> ViewController.view -> ViewController -> UIWindow -> UIApplication
事件按照上面的链条传递,如果到UIApplication还没有被处理就被丢弃
UI卡顿掉帧的原因&优化的方案
在1/60 s内cpu和gpu没有准备好一帧的画面,会造成卡顿
cpu:预排版(布局计算,文本计算),预渲染(图片的解压缩)
gpu:避免离屏渲染,避免半透明图层的混合图片的解压缩
从网络下载的,硬盘读取的jpg/png格式的图片都是压缩过的,需要解压缩,直接调用imageView.image = myImage,系统会自动解压缩,在主线程进行,解压缩操作耗时,可以把解压缩放到子线程进行,通过CGBitmapContextCreate等api创建解压缩后的image称为位图,优化卡顿离屏渲染
gpu在当前屏幕缓冲区以外新开辟一个屏幕缓冲区进行渲染操作
圆角(markToBounds),阴影(shadow),蒙版(mask),光栅化会引起gpu的离屏渲染
要尽量避免gpu的离屏渲染,离屏渲染会创建新的缓冲区,上下文切换,会增加gpu渲染的时间,可能引起cpu+gpu在1/60 s内不能绘制一帧图像,引起卡顿
oc语言相关
- 怎样为catogory添加成员变量
使用关联对象 - catogory和extension的区别
系统类可以添加catogory,不能添加extension - 代理和通知的区别
通知是使用观察者模式实现的,代理使用的是代理模式实现的
通知是一对多,代理是一对一 - kvo是什么
kvo是系统对观察者模式的一个实现
oc使用了isa-swizzing实现了kvo -
kvo的怎样使用isa-swizzing
https://www.jianshu.com/p/4258fa569fc6
-
kvc - (id)valueForKey:(NSString *)key 调用流程
-
kvc - (void)setValue:(id)value forKey:(NSString *)key 调用流程
- assign,weak区别
assign能修饰基本类型和对象,weak只能修饰对象
assign指向的对象被释放后,指针仍然指向原内存地址,weak指向的对象被释放后,指针被置为nil -
copy关键字
runtime
https://www.jianshu.com/p/b3c2eaa8eca2
- 类对象和元类对象的区别
类对象存储实例方法,元对象存储类方法
对象的isa指针指向类对象,类对象的isa指针指向元类对象 -
对象,类对象,元类对象图示
-
oc的消息传递机制
-
消息转发图示
- dynamic
属性的getter,setter方法由用户自己实现 - runtime如何通过sel找到对应的imp
消息的传递机制 - 内存的管理方案
oc使用散列表来管理内存,散列表分为引用计数表,弱引用表 - mrc和arc的区别
mrc是手动管理内存,arc是编译器帮你管理内存 - 什么是自动释放池
是以栈为节点,通过双向链表组合而成
是和线程一一对应的
runloop Entry时调用_objc_autoreleasePoolPush创建自动释放池
runloop BeforeWaiting调用_objc_autoreleasePoolPop(), _objc_autoreleasePoolPush,释放旧的池并创建新的池
AutoreleasePool多层嵌套就是多次插入哨兵对象,一次AutoreleasePoolPage:: pop()就是从栈顶到哨兵的位置的所有对象发送一次release消息
在for循环alloc图片等内存消耗较大的场景需要手动插入AutoreleasePool -
[obj autorelease]图示
-
AutoreleasePoolPage图示
- 怎么避免循环引用
__weak 对象释放后,指针变为nil
__unsafe__unretain 对象释放后,指针变为悬垂指针
block
- block是什么
block是将函数及其上下文封装起来的对象 - block的变量截获是怎样的
对基本类型的局部变量截获其值
对对象类型的局部变量连同所有权修饰符一起截获
全局变量,静态局部变量不截获 - __block
__block可以用于解决block内部无法修改局部变量值的问题
编译器会将__block变量包装成一个结构体 - block的copy操作
StackBlock执行copy,copy到堆上
GlobalBlock执行copy,什么也不做
MallocBlock执行copy,增加引用计数
多线程
https://www.jianshu.com/p/2d57c72016c6
用gcd实现多读单写
dispatch_barrier_async(concurrent_queue,^{//写操作})使用gcd实现这个需求,a,b,c三个并发任务,完成后执行任务d
dispatch_group_async 把并发任务添加到组里面
dispatch_group_notify 组内的并发任务全部完成会调用NSOperation,NSOperationQueue优缺点
添加任务依赖
[NSOperation addDependency]
任务执行状态控制
[NSOperation cancel],NSOperationQueue.suspended
设置最大并发量
[NSOperationQueue maxConcurrentOperationCount]iOS中都有哪些锁
@synchronized
atomic
OSSpinLock
NSRecurSiveLock
NSLock
dispatch_semaphore_t自旋锁,互斥锁的区别
自旋锁,和互斥锁类似,都是为了保证线程安全的锁。但二者的区别是不一样的,对于互斥锁,当一个线程获得这个锁之后,其他想要获得此锁的线程将会被阻塞,直到该锁被释放。但自旋锁不一样,当一个线程获得锁之后,其他线程将会一直循环在哪里查看是否该锁被释放。所以,此锁比较适用于锁的持有者保存时间较短的情况下信号量
dispatch_semaphore_create 创建一个信号量,初始值传0,一般用来做线程同步
dispatch_semaphore_wait 使信号量-1,如果信号量小于0,函数等待信号出现才返回
dispatch_semaphore_signal 使信号量+1,如果之前的信号量小于0,唤醒dispatch_semaphore_wait
runloop
https://www.jianshu.com/p/d260d18dd551
https://www.jianshu.com/p/db4f58149790
- 什么是runloop
runloop是内部维护的消息循环来管理消息的一个对象,没有消息的时候休眠避免资源占用(用户态切换到内核态),有消息处理的时候被唤醒(内核态切换到用户态) - runloop和线程有什么关系
一一对应 -
NSRunLoop的Mode
- NSRunLoopCommonModes
不是实际存在的一种mode
是同步source,timer,observer到多个modes的一种技术方案 -
RunLoop的消息循环
-
实现一个常驻线程
网络
- tcp的特点
面向连接,可靠传输,流量控制,拥堵控制 - tcp为啥是三次握手
https://www.zhihu.com/question/24853633 - tcp为啥是四次挥手
tcp是全双工,比如先关闭客户端到服务器的通道,再关闭服务器到客户端的通道,每次一端的关闭都需要另一端的确认,所以需要四次挥手 - get post区别
get的数据拼在url后面,post的参数放在body里面
get的数据长度有限制,post没有 - http的特点
无状态 -
https
https = http + ssl/tls
-
DNS解析
-
cookie & session
设计模式
- 设计原则
1.单一职责原则
2.开闭原则
对修改关闭,对扩展开放
3.接口隔离原则
使用多个专门的协议,而不是一个庞大的协议
4.依赖倒置原则
抽象不应依赖具体实现,具体实现依赖抽象
5.里氏替换原则
父类可以被子类替换,原有功能不受影响 - 桥接模式
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化,采用组合的方式实现,例如BaseA,BaseB(均为抽象类), BaseB是BaseA的一个变量,BaseA,BaseB通过各自的子类实现 - 单例模式
+ (instancetype)sharedInstance {
static id _instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[SomeClass alloc] init];
});
return _instance;
}
- 责任链模式
- 代理模式
- 通知模式
-
适配器模式