MVC,MVP,MVVM
MVC:model和view不能直接通信,只能通过controller
MVP: 增加了present层,present可以直接与model, view, controller通信
MVVM:vm绑定model和view,通过观察者模式监听model的变化改变view的显示,监听view的变化改变model的数值。
UITableView优化
1.cell复用
2.提前计算cell高度
3.减少渲染,圆角(离屏渲染),透明色值
4.减少过度绘制
5.减少cell层级
6.网络请求,图片加载耗时操作放在子线程,不阻塞主线程
7.滑动按需加载
8.数据持久化,fmdb,数据库索引
iOS数据存储方式
NSUserDefaults
归档
本地文件保存
数据库
CoreData
Plist 沙盒
KeyChain(钥匙串)
IOS新特性
IOS 13新特性暗黑模式
IOS 12 ARkit
ViewController生命周期
initWithCoder
awakeFromNib
loadView
viewDidLoad
viewWillAppear
viewDidAppear
viewWillDisapper
viewDidDissapper
delloc
Js和OC的相互调用
js调用oc的三种方式:
根据网页重定向截取字符串通过url scheme判断
替换方法.context[@"copyText"]
oc调用js代码两种方式
通过webVIew调用 webView stringByEvaluatingJavaScriptFromString: 调用
通过JSContext调用[context evaluateScript:];
Category, Extension,Protocal
category动态增加属性objc_setAssociatedObject和objc_getAssociatedObject
添加方法,直接.h,.m添加
extension是匿名的category
protocal目的是改变或传递控制链,对外声明的一个方法列表。
SEL和IMP
SEL : 选择器,类成员方法的指针,是方法编号
IMP:函数指针,指向了实现函数的地址
RAC信号
信号创建流程
创建信号
订阅信号
发送信号
取消订阅
@weakify和WeakSelf区别
@weakify可以多参数使用
引用和指针有什么区别?
本质:引用是别名,指针是地址。
指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变
Runtime运行时机制
类型的判断、类的成员变量、方法的内存地址都是在程序的运行阶段才最终确定,并且还能动态的添加成员变量和方法
Source0 处理应用内事件,触摸,selector等等,source1处理系统事件
通过CFRunloopObserve回调,通知事件结束
RunLoop
RunLoop在循环过程中监听事件,当前线程有任务时,唤醒当前线程去执行任务,任务执行完成以后,使当前线程进入休眠状态。
开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用currentRunLoop方法来创建,它本身是一个懒加载的。在子线程中,如果不主动获取Runloop的话,那么子线程内部是不会创建Runloop的。
RunLoop有五种模式
kCFRunLoopDefaultMode默认模式,主线程使用的runloop
UITrackingRunLoopMode界面跟踪模式,用于 ScrollView 追踪触摸滑动
UIInitializationRunLoopMode启动App时用到,启动后不再使用
GSEventReceiveRunLoopMode接收系统内部事件
kCFRunLoopCommonModes占位runloop
iOS中的多态
子类继承父类,重写父类的方法
消息转发机制
1.动态方法解析 resolveInstanceMethod
2.消息转发重定向 forwardingTargetForSelector
3.生成方法签名 methodSignatureForSelector
4.拿到签名配发消息 forwardInvocation
5.否则抛出异常 doesNotRecognizeSelector
动态添加方法函数:class_addMethod(self,sel,(IMP)test, char *)
多线程
pthread:基于C语言
NSThread:基于OC,面向对象
GCD:基于C
NSOperation:底层是GCD,面相对象
NSOperation
自动管理线程调度,可设置优先级,最大并发数(决定串行还是并行)
NSInvocationOperation 同步顺序执行 NSBlockOperation 同步顺序执行,可以异步操作
GCD
同步异步串行并行
同步 dispatch_sync
按照代码的编写顺序执行
异步 dispatch_async
并发执行,无法确定任务的执行顺序
3.串行队列 DISPATCH_QUEUE_SERIAL
任务按照顺序被调度,前一个任务不执行完毕,队列不会调度,任务只会顺序执行
4.并行队列 DISPATCH_QUEUE_CONCURRENT,只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不会强制来等待上一个任务执行完毕,而是会在有空闲线程时来继续调度下一个任务
dispatch_group处理多个任务,dispatch_barriar,gcd栅栏分隔任务,有序执行。
dispatch_semaphore 信号量,可以限制限制最大并发数。和锁不同,锁会直接锁定,信号量只是阻塞线程,直到任务完成,才会继续进行。
dispatch_semaphore_wait 每执行一次,信号量-1
dispatch_semaphore_signal 释放信号量,信号量为0,释放
iOS中的锁:
死锁是由于两个或以上的线程互相持有对方需要的资源,导致这些线程处于等待状态,无法执行
@synchronized 互斥锁,性能相对差,可用于实现单例@synchronized(self){ }
NSRecursiveLock 递归锁,在同一个线程里做多次调用时用,递归锁会每执行一次lock,必须等到unlock执行完成后才会再次执行lock。
NSConditionLock 条件锁,一个线程可能需要等到其他线程返回结果,才会被启动。unlockWithCondition
pthread_mutex 互斥锁 c++实现的
dispatch_semaphore 信号量实现加锁
IOS架构的思考
灵活,好扩展
逻辑清晰,简单易读,注释明确
故障隔离,不影响主体,解耦
易于集成其他技术栈
事件传递链和事件响应链
事件传递:先有系统截取,然后遍历子view,看是否能接收,一直循环找到最上面的view。
事件响应:从上面响应的事件开始接收,一直向父类查找,看是否能接收响应。
iOS内存管理方式
1.Tagged Pointer(小对象)
用于存放NSNumber这样的类型,指针所指的不是地址,而是真正是值
2.isa指针
创建一个对象,在c中相当于创建一个结构体,我们常用的id就是这个结构体的指针。结构体有个class类型的成员变量isa也是一个结构体指针,指向这个对象的创建的实例变量,实例方法等等
3.散列表(引用计数表、弱引用表)
离屏渲染
使用圆角、阴影和遮罩等需要在屏幕外中的上下文结合,所以产生离屏
手动开启离屏渲染,layer.shouldRasterize = true
APP启动流程2个阶段
冷启动
加载dyld,Apple的动态链接器,存放Mach-O文件(可执行文件,动态库等)
Runtime启动,解析处理可执行文件,并且把(Class,Protocal,SEL,IMP等等)加载到内中
热启动
APP已经在内存中,在后台存活着
性能优化
UIKIT性能优化
通过Instruments-CoreAnimation检测帧率fps,图层混合,离屏渲染等等
CALayer在子线程执行
内存性能优化
通过Instruments-Allocations显示出应用的实际内存占用,并可以按大小进行排序,Memory检测内存泄漏
引起内存过大的原因
图片过大,解决:图片压缩处理
没必要的常驻内存,解决:用完及时应该销毁,比如ActionSheet
数据模型的冗余字段,解决:不使用的,可以删除
内存泄漏,比如block中的引用未释放。解决:__weak,__strong
IOS关键字
assign:assign通常用于修饰数据类型(NSInteger,CGFloat)和C数据类型(int, float, double, char等)使用
weak:弱引用,在引用的对象被释放的时候将该属性置为nil
strong:强引用,声明block时,相当于copy
retain :强引用,声明block时,相当于assign
copy : 分为浅拷贝和深拷贝,NSString、NSArray、NSDictionary经常用copy,NSMutableString、NSMutableArray、NSMutableDictionary用strong
nonatomic : 非原子访问,对属性赋值的时候不加锁,多线程并发访问会提高性能
atomic : 原子访问,线程安全的,在多线程环境下,原子操作是必要的
readonly : 只生成getter方法
readwrite : 产生setter\getter方法
@synthesize,@property已经是默认自动生成setter 方法和 getter 方法
@dynamic不自动生成setter和getter
__block和__weak修饰符的区别
__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,也可以修饰基本数据类型
__weak只能在ARC模式下使用,只能修饰对象(NSString),不能修饰基本数据类型
__block修饰的对象可以在block中被重新赋值被修改,__weak修饰的对象不可以修改
block
(void)(^block)(void) = ^(){ };
block会对内部变量进行retain操作,所以结束完,不会主动释放
block实现
isa指针:指向block的三种类型
Flags:标记,引用计数
FuncPtr:函数指针,指向block执行的代码区域
Reserved:保留变量
Block的三种类型
globalBlock:存储于数据区,全局block,未引用外部变量。
stackBlock:存储于栈区,引用了外部变量,函数返回时候销毁
mallocBlock:存储于堆区,一般copy出来的block会存放于堆区,但是不会引用计数+1
NSInteger与Int的区别
NSInteger是一个封装,它会识别当前操作系统的位数,自动返回最大的类型。
在32位App中,NSInteger是32位整型,在64位App中,NSInteger是64位整型.
==、Equal 和 isEqualToString 的区别
isEqual: 判断两个对象的等同性,判断两个对象的地址和类型,内容是否一致,IsEqual 是 NSObject 的方法
isEqualToString 是 NSString 的方法,因此从继承关系角度来说isEqualToString 是 isEqual 的衍生方法,isEqualToString: 直接判断字符串内容是否相等。
==: 对于基本数据类型, ==运算符比较的是值; 对于对象类型, ==运算符比较的是对象的地址是否相同。
内核态和用户态
内核态:控制硬件资源,提供应用程序运行环境。
用户态:应用程序的活动空间,执行必须依托内核态。
一个进程执行自己的的代码处于用户运行态,此时优先级低,当需要进行系统调用,处于内核态,优先级高。
objc_class 定义
isa指针 :指向类对象所属类型,元类
super_class 指针: 指向父类的指针
ivar_list:成员变量和属性列表
method_list: 方法列表
cache:缓存
protocol_list:协议,对外声明的方法列表
SDWebImage原理
1.创建任务,放在operation里
2.把所有operation放在一个全局字典里
3.操作前先判断,有没有在执行这个任务,如果有就取消
4.调用loadImage,有缓存就加载缓存,没有检查磁盘有没有,如果没有的话网络获取
首先去寻找系统NSCache
系统的NSCache被释放了,就去自己创建的cache表中取
取出后,还要再调用一次NSCache存储,把value存在系统NSCache,方便下次使用
5.完成后,如果不需要其他操作,直接设置image。如果还需要对image进行操作,就回调到block中,让开发者自己处理
6.有内存警告时候,会清理一部分缓存图片
KVC和KVO
KVO 观察者
添加监听,addObserveValueForKeyPath
监听属性变化,observeValueForKeyPath
KVC 键值对编码
KVC改变会触发KVO
AutoReleasePool
当对象调用autorelease()时,会把对象加入到AutoReleasePoolPage的栈中。AutoReleasePool是多个AutoReleasePoolPage(4096个字节)组成的的一个双向链表结构的自动释放池。
简单的流程就是objc_autoReleasePoolPush -> [object autorelease] -> objc_autoReleasePoolPop
我们在使用block时,内部会自动创建一个@autoreleasepool
[pool drain] 和 [pool release] 在arc下是一样的,在非arc时代,drain还是调用GC
其他
RunLoop有一个60fps的回调,即每16.7ms绘制一次屏幕
CADisPlayLink系统定时器,调用频率和设备屏幕刷新频率相同
BAD_ACCESS 访问了已经执行release的对象
NSObject中的description,相当于NSLog(@“%@”,xxx)的前半部分
直播格式flv,hls,rtmp
AVCaptureSession 获取视频输入输出
AVPlayer 播放媒体
AVAudioSession 音频输入输出
po self.view.recursiveDescription查看view层级关系
[self class]和[super class]指向的都是子类型
iOS黑魔法,method_exchangeImplementations交换两个方法,SEL指向对方的IMP
二叉树的遍历,前序根左右,中序左根右,后序左右根
网友评论