一、Autolayout的生命周期
1.app启动后,Runloop监听约束的变化,增删查改等~
2.在接受到布局变化后Layout Engine根据约束重新布局,将需要更新的布局进行标记(对其父视图调用setNeedsLayout方法),之后便进入延迟布局阶段(Deffered Layout Pass)。
注意:
在进入延迟布局阶段之前,Layout Engine已经将更新的约束计算完毕并将视图的新frame求出。但并不在此时更新视图。
3.延迟布局阶段:此阶段的主要作用是将错误位置的视图重新定位(Reposition misplaced views)。其在视图层级中执行,分为两步:
a.更新约束:从下往上(子视图到父视图),依次遍历视图层级,调用View的updateConstraints方法(或ViewController的updateViewConstraints方法)来更新约束(你可以在此覆盖本方法来设置自定义约束,且在此设置时,执行效率最高。记得最后调用父类实现)。
b.给视图及子视图重新设定位置(给view的frame赋值):从上到下依次调用View的layoutSubViews方法(或ViewController的viewLayoutSubViews方法),从Layout Engine中取出预算好的frame进行赋值(你可以覆盖此方法实现自定义布局,不过此刻不是稳态,需要在适合时候调用父类实现)。
延迟布局阶段的触发条件
setNeedsUpdateConstraints
下一次loop执行updateConstraints
updateConstraintsIfNeeded
立即执行updateConstraints
setNeedsLayout
下一次loop执行layoutSubViews
layoutIfNeeded
立即执行layoutSubViews
setNeedDisplay
下一次loop执行draw
二、weak和assgin
weak比assign多了一个功能就是当属性所指向的对象消失的时候(也就是内存引用计数为0)会自动赋值为nil,这样再向weak修饰的属性发送消息就不会导致野指针操作crash
在ARC模式下编程时,指针变量一定要用weak修饰,只有基本数据类型和结构体需要用assgin,例如delegate,一定要用weak修饰。
三、delegate和block的区别
delegate
block会将代码和变量copy一份到栈,内存会爆增
delegate用weak只会创建指针指向原来的函数,内存不会暴增
四、为什么声明NSString/NSArray/NSDictionary时需要使用copy
当他们指向他们的可变修改的子类时,用copy不会改变其类型,用strong会使其变为可变对象
copyString = mutableString ,strongString = mutableString ;
copyString 仍为NSString类型, strongString变为为NSMutableString
五、类目和扩展
扩展一般写在.m文件里,用来增加私有的属性和方法
类目一般会写在一个新文件里,用来增加共有的方法和属性
扩展的方法必须实现
六、iOS各系统的简单差别
iOS9
默认不允许http请求
iOS11
新增StoryBoard的safeAre插件,自适应屏幕
七、block
防止循环引用,用weak
修改变量,unsafe
八、tableview的优化
减少xib和sb的使用,减少xml文件的encode,uncode
缓存高度,减少运算
九、runtime
系统首先找到消息的接收对象,然后通过对象的isa找到它的类。
在它的类中查找method_list,是否有selector方法。
没有则查找父类的method_list。
找到对应的method,执行它的IMP。
转发IMP的return值。
十、堆栈静态存储区
静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。
十一、Draw 和layout
ayoutSubviews方便数据计算,drawRect方便视图重绘。
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews。
2、addSubview会触发layoutSubviews。
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews事件。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。 7、直接调用setLayoutSubviews。 ? drawRect在以下情况下会被调用:
?
1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView,?Controller->viewDidLoad?两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View?draw的时候需要用到某些变量 值).
2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
以上1,2;而3,4不提倡 ? drawRect方法使用注意点:
?
1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay?或 者?setNeedsDisplayInRect,让系统自动调该方法。
2、若使用calayer绘图,只能在drawInContext:?中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来调用setNeedsDisplay实时刷新屏幕
网友评论