assign和weak
我们都知道,assign用来修饰基本数据类型,weak用来修饰OC对象。
其实照理,assign也能修饰OC对象,但是assign修饰的对象在该对象释放后,其指针依然存在,不会被置为nil——这就造成了一个很严重的问题:出现了野指针。当访问这个野指针时,指向了原地址,而原地址有两种情况:
第一种情况:原地址没有改变,代码运行通过,但很有可能有逻辑bug。
第二种情况:原地址已经改变,结果不可预测,多数崩溃,也有可能出现其他莫名错误。
但是用weak来修饰的话,对象释放的时候会把指针置为nil,从而避免了野指针的出现。
那又有个疑问出现了,凭什么基本数据类型就可以使用assign。这就要扯到堆和栈的问题了,基本数据类型会被分配到栈空间,而栈空间是由系统自动管理分配和释放的,就不会造成野指针的问题。
NSString到底使用Copy还是使用Strong属性
1) 当原字符串是NSString时,字符串是不可变的,不管是Strong还是Copy属性的对象,都是指向原对象,Copy操作只是做了次浅拷贝。
2) 当原字符串是NSMutableString时,Strong属性只是增加了原字符串的引用计数,而Copy属性则是对原字符串做了次深拷贝,产生一个新的对象,且Copy属性对象指向这个新的对象,且这个Copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。
一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。
图像显示原理
1.CPU:输出位图
2.GPU :图层渲染,纹理合成
3.把结果放到帧缓冲区(frame buffer)中
4.再由视频控制器根据vsync信号在指定时间之前去提取帧缓冲区的屏幕显示内容
5.显示到屏幕上
UI卡顿掉帧原因
iOS设备的硬件时钟会发出Vsync(垂直同步信号),然后App的CPU会去计算屏幕要显示的内容,之后将计算好的内容提交到GPU去渲染。随后,GPU将渲染结果提交到帧缓冲区,等到下一个VSync到来时将缓冲区的帧显示到屏幕上。也就是说,一帧的显示是由CPU和GPU共同决定的。
一般来说,页面滑动流畅是60fps,也就是1s有60帧更新,即每隔16.7ms就要产生一帧画面,而如果CPU和GPU加起来的处理时间超过了16.7ms,就会造成掉帧甚至卡顿。
KVC和KVO
KVC也就是key-value-coding,即键值编码,通常是用来给某一个对象的属性进行赋值。
1,对私有变量进行赋值
2,字典转模型
KVO,即key-value-observing,利用一个key来找到某个属性并监听其值得改变。其实这也是一种典型的观察者模式。
简单的说,kvo的用法非常简单。
1,添加观察者
2,在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject)
3,移除观察者
KVO的底层实现
当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。
如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?
想让自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying 与 NSMutableCopying 协议。
实现 NSCopying 协议。该协议只有一个方法:- (id)copyWithZone:(NSZone *)zone;。
实现 NSMutableCopying 协议。该协议只有一个方法:- (id)mutableCopyWithZone:(nullable NSZone *)zone;
聊聊OC的反射机制
反射机制主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。这种动态获取信息以及动态调用对象方法的功能称为语言的反射机制。
实际应用中:
// SEL和字符串转换
NSStringFromSelector、NSSelectorFromString
// Class和字符串转换
NSStringFromClass、NSClassFromString
// Protocol和字符串转换
NSStringFromProtocol、NSProtocolFromString
常用判断方法
iOS中的野指针、僵尸对象、空指针
野指针和空指针是不一样的,空指针没有储存任何的内存地址,而野指针指向的一块内存地址,但是该内存不可用。换句话说,野指针指向的对象已经被释放了。
在OC中,对象被释放后所占用的内存在没有被复写(重新分配给其他对象)前称为僵尸对象,这是野指针是可以访问该内存的,因为对象的数据还在,所以程序不会报错。但是该内存一旦重新分配给其他对象就会出现问题。
nil:OC中的对象的空指针
Nil:OC中类的空指针
NULL:C类型的空指针
NSNull:数值类的空对象
NSNotification 同步、异步
NSNotification 发通知的操作是同步的,并且通知处理是在发通知的那个线程
事件传递
事件传递规则:事件的传递是从父view传到子view的,所以如果父控件接受不到触摸事件,那么子控件就不可能接收到触摸事件。其流程大致如下。
当用户触摸屏幕后,系统会将该触摸事件加入到一个由UIApplication管理的队列事件中。
UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)。
主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。
响应机制
如果当前的响应控件不处理事件,那么该事件沿着响应链向上传递,如果响应该事件,则消费该事件,停止在响应链上传递。如果响应链传到UIApplication还没被处理就丢弃。它与查找最合适View的方向相反
网友评论