Autolayout和Frame
Autolayout的约束最后都是系统最终转化成frame来进行布局的,对与一个View来说,最终确定其中心点位置和View的宽高。当Autolayout和Frame设置上产生冲突的时候,则会以Autolayout的设置为准。
- (void)setNeedsLayout;
- (void)layoutIfNeeded;
- (void)layoutSubviews;
setNeedsLayout方法标记当前view是需要重新布局的,在下一次runloop中,进行重新布局。如果说想在当前runloop中立刻更新布局,则通过调用layoutIfNeeded方法可以实现,此时系统会调用layoutSubviews。在layoutSubviews方法中,可以自己定义新的view或者改变子view的布局。
App启动过程优化
①解析Info.plist
加载相关信息,例如闪屏
沙箱建立、权限检查
②Mach-O加载
如果是胖二进制文件,寻找合适当前CPU架构的部分
加载所有依赖的Mach-O文件(递归调用Mach-O加载的方法)
定位内部、外部指针引用,例如字符串、函数等
执行声明为__attribute__((constructor))的C函数
加载类扩展(Category)中的方法
C++静态对象加载、调用ObjC的 +load 函数
③程序执行
调用main()
调用UIApplicationMain()
调用applicationWillFinishLaunching
换成另一个说法就是:
App开始启动后,系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接器dyld,dyld是一个专门用来加载动态链接库的库。 执行从dyld开始,dyld从可执行文件的依赖开始, 递归加载所有的依赖动态链接库。
动态链接库包括:iOS 中用到的所有系统 framework,加载OC runtime方法的libobjc,系统级别的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)。
https://blog.csdn.net/olsQ93038o99S/article/details/81518485
weak和assign的区别
weak
只可以修饰对象。
weak 不会产生野指针问题,因为weak修饰的对象释放后(引用计数器值为0)自动被置为nil,之后再向该对象发送消息也不会崩溃。
assign
可以修饰对象和基本数据类型。
如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会被自动置空,此时向对象发送消息会崩溃。
assig适用于基本数据类型int float struct等类型,会被放入栈中,先进后出。
weak适用适用于 delegate ,不会导致野指针,也不会造成循环引用
iOS响应链和事件传递
UIResponder 响应者对象。只有继承UIResponder的类,才能处理事件。
UIApplication,UIView,UIViewController都是继承自UIResponder类,可以响应和处理事件。CALayer不是UIResponder的子类,无法处理事件。
事件的分发和传递
1.当iOS程序中发生触摸事件后,系统会将事件加入到UIApplication管理的任务队列中
2.UIApplication将处于任务队列最前端的事件向下分发,即UIWindow。
3.UIWindow将事件向下分发,即UIView。
4.UIView首先看自己是否能处理事件,触摸点是否在自己身上。如果能,则继续寻找子视图。
5.遍历子空间,重复以上两步。
6.如果没有找到,那么自己就是事件的处理者。
7.如果自己不能处理,那么不做任何处理。
其中UIView不接受事件处理的情况有:
1)alpha <0.01 2)userInteractionEnabled = NO 3)hidden = YES
怎样寻找最合适的View
// 此方法返回的View是本次点击事件需要的最佳
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
// 判断触摸点是否在视图内
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
使用场景:
1、扩大按钮的点击范围
UIButton重写 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event 方法
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
CGRect bounds = self.bounds;
bounds = CGRectInset(bounds, -10, -10);
// CGRectContainsPoint 判断点是否在矩形内
return CGRectContainsPoint(bounds, point);
}
2.不规则按钮的点击区域
// // 改变图片的点击范围
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// 控件范围宽度多40,高度20
CGRect bounds = CGRectInset(self.bounds, -20, -20);
NSLog(@"point = %@",NSStringFromCGPoint(point));
UIBezierPath *path1 = [UIBezierPath bezierPathWithRect:CGRectMake(-20, 0, 40, 120)];
UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:CGRectMake(self.frame.size.width - 20, 0, 40, 120)];
if (([path1 containsPoint:point] || [path2 containsPoint:point])&& CGRectContainsPoint(bounds, point)){
//如果在path区域内,返回YES
return YES;
}
return NO;
}
Http 和 Https 的区别
HTTPS 是以安全为目标的HTTP通道,在HTTP的基础上加入了SSL层。
HTTPS协议的主要作用是:1.建立一个信息安全通道,来保证数据传输的安全;2、确认网址的真实性。
主要区别:
1.HTTPS协议需要到 ca 申请证书,并需要一定的费用;
2.http是超文本呢传输协议,信息是明文传输, https则是具有安全性的ssl加密传输协议;
3.http用的端口是80 https用的端口是443;
4.http连接是简单,无状态的, https协议是由SSL+HTTP协议构成的可进行加密传输、身份认证的网络协议;
HTTPS的工作原理:
说明:非对称加密算法RSA 是内容加密的一种算法,它有两个秘钥:公钥和私钥。公钥是公开的钥匙,所有人都可以知道;私钥是私密的,只有持有者知道。通过公钥加密的内容,只能通过私钥解密。非对称加密算法的安全性很高,但是计算量庞大,比较消耗性能。
1)客户端发起 https 请求
客户端连接到服务器端的443端口上,客户端会发送一个密文族给服务端;
2)服务端配置公钥和私钥,并传输证书(公钥)
服务端配置一套证书,包含公钥和私钥,传输的公钥中包含很多信息,如证书的颁发机构、过期时间等等;
3)客户端解析证书,并传送加密信息
客户端的TLS,验证公式的相关信息,如果没有问题,生成随机数,并使用该证书对该随机值进行加密,目的是让服务端得到这个随机值;
4)服务端利用私钥解密信息
服务端利用私钥解密,得到随机数,完成非对称加密的过程,实现了身份认证和密钥协商。然后把该内容通过该值进行对称加密;
5)传输加密后的信息,客户端解密信息
服务端用随机值加密后的信息,可以在客户端用公钥被还原。
TCP和UDP
TCP 可靠、稳定,面向连接。会有三次握手来建立连接
UDP 快。无状态的传输协议。 适用于一次只传送少量数据、对可靠性不高的应用场景。
UIViewController的生命周期
详细地址:https://blog.csdn.net/abap_brave/article/details/80148781
1.init 里不要出现创建view的代码。都是关键数据的初始化;
2.loadView 初始化关键点额View,加载视图
awakeFromNib: 从xib或storyboard中加载UIViewController将要被激活时调用
3.ViewDidLoad
4.viewWillAppear 视图即将显示时调用
5.viewWillLayoutSubviews: 视图将要布局其子视图时被调用
viewDidLaySubviews: 视图布局完成其子视图时被调用
6.viewDidAppear
7.viewWillDisppear
8.viewDidDisapper
9.dealloc 被释放
其他
viewWillUnload 内存警告,释放 view
viewDidUnload 内存警告,释放 view
GET和POST
get 方式,APP会把http header 和 data 一并发送出去,服务器返回 200;
post 方式, 浏览器先发送header, 服务器相应 100 continue ,浏览器再发送 data,服务器响应 200 ;
GET 请求有长度显示1024, POST没有长度限制;
GET参数通过URL传递, POST放在Request Body 中;
GET在浏览器中可以回退,POST会重新进行请求
深拷贝和浅拷贝
浅拷贝:对内存地址的复制 深拷贝:拷贝对象的具体内容
是否开启新的内存地址 、 是否影响内存地址的引用计数
不可变类型(NSString,NSArray,NSDictionary) copy都是浅拷贝
mutableCopy都是深拷贝
可变类型(NSMutableString,NSMutableArray) copy都是深拷贝
mutableCopy都是深拷贝
设计模式
1.MVC 模式
2.MVVM模式
由MVP发展过来的,Model - View - ViewModel ,即 模式——视图——视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。
在MVVM的框架下视图和模型是不能直接通信的,之间通过ViewModel来进行通信,ViewModel通常要实现一个observer观察者,当数据发生变化,viewModel能监听到数据的变化,然后通知到对应的视图做自动更新,当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。
3.单例模式
确认一个类全局只创建一次,只有一份实例,用户进行资源共享控制
4.代理模式
当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。
5.观察者模式KVO
察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。
6.工厂模式
KVC 和KVO
KVC key-value-coding 键值编码。
可以允许开发者通过key 直接访问对象的属性,或者给对象的属性赋值,而不需要调用明确的存取方法,利用 runtime 运行时动态的访问和修改对象的属性。
KVO key-value-Observer 观察者模式
步骤:
1.当类A的对象第一次被观察的时候,系统会在运行期动态创建原类的派生类,
2.在派生类中重写原类中被观察属性的 setter 方法,派生类在被重写的setter方法中实现通知机制
3.派生重写class方法,将自己伪装成原类,派生类还会重写dealloc方法释放资源
4.系统会将所有指向原类对象的isa指针指向派生类的对象
Delegate ,通知 和 Block 的使用场景
delegate
控制器的反向传值 或者 传递 一个事件。
block
写法简练,
1、使用block需要注意防止循环应用,使用weakSelf,
2、Block类型属性使用 copy 修饰
3、block 在堆中,想改变block 里面变量的值,需要加参数 __block
Notification通知
一对多, 需要先注册通知,发送通知,处理通知
OC 的内存管理
https://www.cnblogs.com/wendingding/p/3704739.html
1、谁创建,谁释放: (1)如果你使用alloc,new , copy 来创建了一个对象,那么必须调用release 或者 autorelease 方法 (2)不是你创建的对象就不用你去负责
2、谁ratain ,谁release
3、dealloc 方法前面,一定要写明 【super dealloc】
4、@property 默认生成setter 和 getter 方法,
5、autorelease 会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子中所有的对象做一次release 。
排序方法
1.快排排序
通过一趟排序将要排序的数据分割成两部分,其中一部分的所有数据比另一部分的所有数据都要小,然后按此方法对这两部分数据分别进行快速排序,整个过程可以递归进行,以达到整个数据变成有序序列。
2.冒泡排序
懒加载
用到时再记载,而且只加载一次
本质上是: 重写 get 方法时,先判断对象当前是否为空,为空的话再去实例化对象.
好处:1、代码可读性强,不必将所有代码都写到viewDidLoad 2、每个控件分别负责格子的getter方法 3、对系统的内存占用率减小
属性关键字 atomic、nonatomic、readonly、readwrite、assign、retain、copy
1.readwrite 可读可写特性,需要生成 getter 和 setter 方法;
2.readonly 只读特性.只会生成 getter 方法,不会生成 setter 方法,不希望在类外部改变属性;
3.assign 赋值特性.assign用于基本数据类型. 当修饰的对象释放后,指针不会被自动置空,此时向对象发送信息会崩溃.
4.retain
5.copy 拷贝特性. 修饰可变类型是深拷贝, 修饰不可变类型是浅拷贝. 常用语block
6.nonatomic非原子操作。
Runtime
运行时机制。
OC在三种层面上与 Runtime 系统进行交互:
1.通过 OC 源代码
2.通过 Foundation框架的 NSObject 类定义的方法
(1) -isKindOfClass: 和 -isMemberOfClass: 方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者父类或者当前类的成员变量);
(2) -respondsToSelector: 检查对象能否响应指定的消息;
(3) -methodForSelector: 返回指定方法实现的地址。
3.通过对Runtime库函数的直接调用
(1)Swizzling
+ (void)load {
[super load];
Method fromMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
Method toMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(swizzling_ObjectAtIndex:)); method_exchangeImplementations(fromMethod, toMethod);}
(2) NScoding 通过objv_ivar_list 获取成员列表,进行归档;
其他
objc_class 在运行时中关联了 objc_ivar_list (成员列表) objc_method_list (方法列表)
IMP(指针,指向方法的实现地址)
RunLoop 和线程的关系
1 每条线程都有唯一的一个RunLoop对象与之对应;
2 主线程的 Runloop 是自动创建并启动;
3 子线程的 Runloop 需要手动开启;
4 RunLoop是用来管理线程的,当线程的Runloop 被开启后,线程会在执行完任务之后进入休眠状态,有任务后就会被唤醒去执行任务;
CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
RunLoop 的几种模式
Runloop一共5种模式。
1.NSDefaultRunLoopMode //默认的
2.UITrackingRunLoopMode //UI模式(苹果为了用户体验,所以这个优先级较高),比如当滑动UIScrollView的时候,runloop会切到这个模式下,当滑动事件结束时,runloop会切到NSDefaultRunLoopMode
3.NSRunLoopCommonModes 占位模式,相当于 NSDefaultRunLoopMode + UITrackingRunLoopMode
描述 iOS 程序的运行流程
https://www.jianshu.com/p/a0b9ce0497f9
1 main函数执行前:加载dylb 、初始化依赖库、初始化 runtime 、回调runtime
2 main 函数执行后: 调用UIApplicationMain函数, 开启主线程runloop监听系统事件 , 通知Appdelegate , 设置 rootViewController , 调用 self.window makeKeyAndVisable显示窗口
堆和栈的区别
栈区: 由编译器自动分配释放,速度很快 在内存中是连续的区域
堆去:由程序员分配释放,速度较慢 在内存中不连续,通过指针连接起来
全局去(静态区):存放全局变量和静态变量,结束后由系统释放。
文字常量区
程序代码区
多线程
NSThread
NSOperation
GCD (重点)
Block
block本质是异步执行的代码块。block作为对象的属性,使用copy 从栈区拷贝到堆去,拥有该block的所有权,避免提前释放。
使用方法:1. 声明 block 2.定义类的 Block 属性 3.实现block 4.赋值调用 block方法
AFNetworking 底层原理分析
1 NSURLSession:网络通信模块(核心模块) 对应 AFNetworking中的AFURLSessionManager和对HTTP协议进行特化处理的AFHTTPSessionManager,AFHTTPSessionManager是继承于AFURLSessionmanager的
2 Security:网络通讯安全策略模块 对应 AFSecurityPolicy
3 Reachability:网络状态监听模块 对应AFNetworkReachabilityManager
4 Seriaalization:网络通信信息序列化、反序列化模块 对应 AFURLResponseSerialization
5 UIKit:对于IOSUIKit的扩展库
SDWebImageView 原理
苹果内购流程
1、遵循苹果内购协议,填写银行卡和公司信息
2、创建项目的内购条目
3、添加沙盒测试账号
4、进入支付界面,调用内购
1)从后台获取最新的商品信息列表;
2)创建订单,后台返回订单号;
3)APP向苹果发送购买请求,返回支付结果
4)监听购买结果
5)交易结束后,APP从沙盒中获取购买凭据,发送给后台,后台去app store上验证支付信息,返回APP最终的支付结果,刷新道具最新数据;
C , C++, OC 混用
.m 可以识别 C 和 OC;
.mm 可以识别 C C++ 和 OC;
.cpp 只能识别 C 和 C++
Runtime 的消息转发机制
objc_msgSend(structobjc_super *_Nonnullsuper,SEL_Nonnullop, ...)
https://ke.qq.com/course/356310
1.动态方法解析 (resolveInstanceMethod)
2.快速转发 (forwardTargetForSelector)
3.慢速转发
- methodSignatureForSelector
- forwardInvocation
4.避免崩溃的方法 - (void)doesNotRecognizeSelector:(SEL)aSelector