iOS课程观看笔记(二)---OC语言相关
开局一张图围绕着OC语言相关问题大致涉及到图片中所有的内容。分类Category你用分类都做了哪些事情声明私有方法分解体积庞大的类文件把Framework的私有方法公开声明私有方法这个我感觉就是将原来的写在原类中的私有方法在分类中进行声明。比如定义一个分类只有头文件放到对应宿主.m里满足私有方法的声明和使用不暴露具体实现。分类的特点运行时决议指的是在运行时通过runtime将分类里面的内容添加到宿主类里面可以为系统类添加分类分类中都可以添加哪些内容实例方法类方法协议属性只声明了get和set方法并没有实现get和set方法也没有生成实例变量分类的结构具体代码不再具体分析可参考iOS分类Category的本质本文只摘抄部分上文中没有的内容或者比较重要的内容。这里只分析分类中的实例方法。在编译阶段编译器将category里面的内容编译成category_t类型的结构。在运行阶段runtime将每一个分类中的实例方法组成一个数组然后将这些数组再组合到一个大数组中然后从最后一个元素数组类型开始添加到分类的instance_methods数组中再将拼接好的二维数组instance_methods放入宿主类的class_rw_t的methods当中。举个例子假如某个类YZPerson有三个分类YZPersoneat.m、YZPersonrun.m、YZPersonwalk.m首先将每个分类里面的实例方法组合成一个数组然后再将三个分类组合成一个大数组。这样分类中的实例方法列表就是一个二维数组。假如上面三个分类第一个分类里面有2个实例方法第二个分类里面有1个实例方法第三个分类里面有3个实例方法那么该实例方法在分类存储形式如下图中的二维数组类似。以上是将分类合并成一个大数组其顺序是按照编译顺序最先编译的在数组最前面然后再通过一个while循环从数组的最后一个元素(也是数组)开始一个一个添加到分类的instance_methods里面。然后将分类的instance_methods这个二维数组拼接到rw的methods上也就是拼接到原类的methods方法列表中。并且从attachLists方法里面可以看出是将分类实例方法列表插入到宿主类的方法列表的最前面。这样最后编译的分类里面方法最先被调用。属性、协议的添加方法与上面实例方法添加方法类似。分类添加的方法可以“覆盖”原类方法当然不是真的覆盖两个分类里面有一个同名方法最后编译的分类里面的方法被调用。名字相同的分类会引起编译报错关联对象问能否为分类添加成员变量不能问能否为分类添加属性能idobjc_getAssociatedObject(id _Nonnull object,constvoid*_Nonnull key)voidobjc_setAssociatedObject(id _Nonnull object,constvoid*_Nonnull key,id _Nullable value,objc_AssociationPolicy policy)voidobjc_removeAssociatedObjects(id _Nonnull object)问为分类添加的属性被添加到了哪里没有被添加到原宿主类中而是被添加到。。。属性、实例变量、成员变量的区别属性property是指的右property建立的例如property (copy, nonatomic) NSString *postId;property负责三个事情set,get方法的声明set,get方法的实现生成_postId的实例变量成员变量指的是interface{intage;NSObject*obj1;}end大括号中间的内容实例变量ivarinstance variables指的是{}中声明的变量都是实例变量成员变量通常就是实例变量二者基本可以视为同义词。成员变量 实例变量属性property实例变量instance variable / ivar成员变量member variable / data member通常也称 instance variable扩展Extension问一般用扩展做什么声明私有属性声明私有方法声明私有成员变量扩展的特点编译时决议只以声明的形式存在多数情况下存在于宿主类的.m文件中不能为系统类添加扩展代理Delegate代理分三个模块协议、委托、代理协议就是property委托就是协议调用协议方法的地方指定代理代理就是实现协议里面具体方法的地方是一种软件设计模式传递方式一对一代理也可以添加属性MJ说delegate不是代理设计模式NSProxy是代理设计模式于海说delegate是代理设计模式那么delegate是不是代理设计模式呢delegate 在中文 iOS 开发习惯中经常被叫作“代理”但严格按设计模式分类它主要是委托模式不是 GoF 的代理模式。NSProxy 更接近 GoF 代理模式的实现工具。所以 MJ 的说法在严格的设计模式语境下更准确于海的说法符合国内 iOS 开发中的宽泛叫法。问如何实现代理的一对多即同一个代理被多个对象监听方法一将代理设置成数组、集合而不是单单的一个weak属性值类似property(nonatomic,strong)NSMutableArrayidTestSubViewDelegate*__nullable delegates;需要注意的是在消耗的时候要手动销毁delegates-(void)destory{[self.delegates removeAllObjects];self.delegatesnil;}iOS 实现一对多代理方案不过最好使用NSMapTable NSHashTable NSPointerArray这些数据类型因为这几个数据类型里面存放的元素都是weak指针引用的销毁的时候不需要手动销毁iOS开发-NSMapTable NSHashTable NSPointerArray的使用方法二利用消息转发机制iOS:利用消息转发机制实现多播委托通知NSNotification通知是使用观察者模式来实现的用于跨层传递消息的机制传递方式一对多问如何实现通知机制在通知中心有一个Notification_Map字典里面存储着以通知名称为key观察者组成的数组作为valueKVOKVO是Key-value observing的缩写KVO是Objective-C对观察者设计模式的一种实现Apple使用了isa混写isa-swizzling来实现KVOisa混写技术:指的就是将isa指针动态重新指向新的类setter方法重写的方法问通过kvc设置valuekvo能否生效可以KVC改变属性值会进入属性值的setter方法从而触发KVO问通过成员变量直接赋值valuekvo能否生效不可以但可以通过手动修改setter方法触发KVO[self willChangeValueForKey:name];[super setName:name];[self didChangeValueForKey:name];使用setter方法改变值KVO会生效使用setValue:forKey:改变值KVO会生效成员变量直接修改需手动添加某些代码KVO才会生效KVCKVC是Key-value coding的缩写。里面有两个重要的方法-(id)valueForKey:(NSString*)key;-(void)setValue:(nullable id)value forKey:(NSString*)key;问KVC是否有违面向对象思想KVC只要知道某个对象的私有变量名称key可以在外部将其value进行修改也就是有违面向对象思想的。valueForKey:的系统实现流程valueForKey:说白了就是通过一个key找到对应的value找value可以是通过getter方法找也可以通过直接找对应的实例变量也就是一个是方法一个是实例变量两种方法图中Accessor Method is exist?就是通过getter方法找有的话直接调用Instance Var is exist?就是有没有对应的实例变量有的话调用问Accessor Method如何找方法呢通过getKey、key正好是getter方法、isKey三个方法如果有则YES这三个都是方法问(BOOL)accessInstanceVariablesDirectly的作用系统给我们提供了一个方法(BOOL)accessInstanceVariablesDirectly默认是返回YES在返回YES的基础上才会调用Instance Var is exist判断是否存在相应的实例变量或者相似的实例变量如果我们重写该方法使其返回NO那么直接报没有找到对应的值处理不再进行实例变量的判断。问Instance Var is exist?判断规则是什么通过查找是否存在_key、_isKey、key、isKey四个实例变量如果有则YES这四个都是实例变量问如果valueForKey:没有找到对应的value会怎样如果valueForKey:没有找到对应的value会调用valueForUndefinedKey:从而造成崩溃YZPerson*person1[[YZPerson alloc]init];NSLog(person1.age %,[person1 valueForKey:age]);setValue:forKey:的系统实现流程里面的具体方法与流程与valueForKey:类似不再进行具体分析。属性关键字问属性关键字可以分为哪几类读写权限:readonly、readwrite(默认)原子性atomic(默认)、nonatomic引用计数setter\getteratomic可以保证获取和赋值是线程安全的但是并不能保证在使用过程中是线程安全的引用计数retain\strongassign\unsafe_unretainweakcopy问assign和weak的区别有哪些assign可以修饰基本数据类型如int、BOOL等可以修饰对象类型但不改变其引用计数器当使用assign修饰对象在对象释放的时候会产生悬垂指针weak不可以修饰基本数据类型修饰对象类型但不改变其引用计数器当使用weak修饰对象在对象释放的时候会自动置为nil问关于空指针、野指针、悬垂指针的区别空指针指针指向的地址为空的指针野指针指针创建时未初始化。指针变量刚被创建时不会自动成为NULL指针它会随机指向一个内存地址。垂悬指针指针所指向的对象已经被释放或者回收了但是指向该对象的指针没有作任何的修改仍旧指向已经回收的内存地址。更多学习关于悬垂指针按照上面的说法我们之前很多说的野指针错误严格说来并不是野指针错误而是悬垂指针。问浅拷贝、深拷贝浅拷贝并没有新建一块内存浅拷贝对原来的对象引用计数1深拷贝会新建一块内存与原来的内存里面内容一样深拷贝对原来的对象引用计数不变如果赋值过来是NSMutableArraycopy后其实是NSArray如果对其进行添加或者删除操作会造成程序崩溃问为何会做 _obj ! obj 的判断不做可以吗如果不做则先进行[_obj release];也就是原来的对象可能已经被释放掉了。再进行[obj retain]操作会造成程序异常。