继续.....
1.产生原因:如下图所示,对象A和对象B相互引用了对方作为自己的成员变量,只有自己销毁的时候才能将成员变量的引用计数减1。对象A的销毁依赖于对象B的销毁,同时对象B销毁也依赖与对象A的销毁,从而形成循环引用,此时,即使外界没有任何指针访问它,它也无法释放。
2.多个对象间依然会存在循环引用问题,形成一个环,在编程中,形成的环越大越不容易察觉,如下图所示:
1,事先知道存在循环引用的地方,在合理的位置主动断开一个引用,是对象回收;
2.使用弱引用的方法。
1.在一个给定的实体中,同一个属性的所有值具有相同的数据类型。
2.键-值编码技术用于进行这样的查找,它是一种间接访问对象属性的机制。 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。
3.键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。
1.键值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制,非对象类型的变量将被自动封装或者解封成对象,很多情况下会简化程序代码;
2.KVC的缺点:一旦使用 KVC 你的编译器无法检查出错误,即不会对设置的键、键路径进行错误检查,且执行效率要低于合成存取器方法和自定的 setter 和 getter 方法。因为使用 KVC 键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量。
1.键值观察机制是一种能使得对象获取到其他对象属性变化的通知 ,极大的简化了代码。
2.实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修改它的实例变量,这样才能被观察者观察到。
比如我自定义的一个button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil]; #pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay]; }
}
对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。
key
找到value
的原理1.当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]
时,程序会自动试图通过下面几种不同的方式解析这个调用;
2.首先查找对象是否带有 someKey
这个方法,如果没找到,会继续查找对象是否带有someKey
这个实例变量(iVar
),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:
这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException
异常错误。
3.补充:KVC查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。
4.设计valueForUndefinedKey:
方法的主要目的是当你使用-(id)valueForKey
方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。
1.注册观察者(注意:观察者和被观察者不会被保留也不会被释放
)
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context;
2.接收变更通知
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
3.移除对象的观察者身份
- (void)removeObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath;
3.KVO中谁要监听谁注册
,然后对响应进行处理,使得观察者与被观察者完全解耦。KVO只检测类中的属性,并且属性名都是通过NSString来查找,编译器不会检错和补全,全部取决于自己。
1.代理又叫委托,是一种设计模式,代理是对象与对象之间的通信交互,代理解除了对象之间的耦合性。
2.改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。
3.另外一点,代理可以理解为java中的回调监听机制的一种类似。
4.代理的属性常是assign
的原因:防止循环引用,以至对象无法得到正确的释放。
1.代理是一种回调机制,且是一对一的关系,通知是一对多的关系,一个对向所有的观察者提供变更通知;
2.效率:Delegate比NSNOtification高;
3.Delegate和Block一般是一对一的通信;
4.Delegate需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信;
5.Block:更加简洁,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate;
1.可修改不可修改的集合类,就是可动态添加修改和不可动态添加修改。
2.比如NSArray
和NSMutableArray
,前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间.
不需要,静态方法(类方法)创建一个对象时,对象已被放入自动释放池。在自动释放池被释放时,很有可能被销毁。
因为子类的某些实例是继承自父类的,因此需要调用[super dealloc]
方法, 来释放父类拥有的实例,其实也就是子类本身的。一般来说我们优先释放子类拥 有的实例,最后释放父类所拥有的实例。
Cocoa 中提供了一个NSPredicate
的类,该类主要用于指定过滤器的条件, 每一个对象通过谓词进行筛选,判断条件是否匹配。如果需要了解使用方法,请看谓词的具体使用.
1.函数体内static
变量的作用范围为该函数体,不同于auto
变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值.
2.在模块内的 static
全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问.
3.在模块内的static
函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明.
4.在类中的static
成员变量属于整个类所拥有,对类的所有对象只有一份拷贝.
5.self:当前消息的接收者。
6.super:向父类发送消息。
#include
和#import
其效果相同,都是查询类中定义的行为(方法);
#import
不会引起交叉编译,确保头文件只会被导入一次;
@class
的表明,只定 义了类的名称,而具体类的行为是未知的,一般用于.h 文件;
@class
比#import
编译效率更高。
@class
和#import
的主要区别在于解决引用死锁的问题。@public
:对象的实例变量的作用域在任意地方都可以被访问 ;
@protected
:对象的实例变量作用域在本类和子类都可以被访问 ;
@private
:实例变量的作用域只能在本类(自身)中访问 .
任意类型对象,程序运行时才决定对象的类型。
均表示条件的判断,switch语句表达式只能处理的是整型、字符型和枚举类型,而选择流程语句则没有这样的限制。但switch语句比选择流程控制语句效率更高。
1.联系:两者都能检测一个对象是否是某个类的成员
2.区别:isKindOfClass
不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass
只能做到第一点。
3.举例:如 ClassA
派 生 自NSObject
类 , ClassA *a = [ClassA alloc] init]
;,[a isKindOfClass:[NSObject class]]
可以检查出 a 是否是 NSObject
派生类 的成员,但 isMemberOfClass
做不到。
数据存储的核心都是写文件。
1.属性列表:只有NSString、NSArray、NSDictionary、NSData可writeToFile;存储依旧是plist文件。plist文件可以存储的7中数据类型:array、dictionary、string、bool、data、date、number。
2.对象序列化(对象归档):对象序列化通过序列化的形式,键值关系存储到本地,转化成二进制流。通过runtime实现自动化归档/解档,请参考这个文章。实现NSCoding协议必须实现的两个方法:
3.编码(对象序列化):把不能直接存储到plist文件中得到数据,转化为二进制数据,NSData,可以存储到本地;
4.解码(对象反序列化):把二进制数据转化为本来的类型。
5.SQLite 数据库:大量有规律的数据使用数据库。
6.CoreData :通过管理对象进行增、删、查、改操作的。它不是一个数据库,不仅可以使用SQLite数据库来保持数据,也可以使用其他的方式来存储数据。如:XML。
7.CoreData的介绍:
8.CoreData的特征:
1.通过CoreData管理应用程序的数据模型,可以极大程度减少需要编写的代码数量。
2.将对象数据存储在SQLite数据库已获得性能优化。
3.提供NSFetchResultsController类用于管理表视图的数据,即将Core Data的持久化存储在表视图中,并对这些数据进行管理:增删查改。
4.管理undo/redo操纵;
5.检查托管对象的属性值是否正确。
1.NSManageObject:被管理的数据记录Managed Object Model是描述应用程序的数据模型,这个模型包含实体(Entity)、特性(Property)、读取请求(Fetch Request)等。
2.NSManageObjectContext:管理对象上下文,持久性存储模型对象,参与数据对象进行各种操作的全过程,并监测数据对象的变化,以提供对undo/redo的支持及更新绑定到数据的UI。
3.NSPersistentStoreCoordinator:连接数据库的Persistent Store Coordinator相当于数据文件管理器,处理底层的对数据文件的读取和写入,一般我们与这个没有交集。
4.NSManagedObjectModel:被管理的数据模型、数据结构。
5.NSFetchRequest:数据请求;
6.NSEntityDescription:表格实体结构,还需知道.xcdatamodel文件编译后为.momd或者.mom文件。
1.对于KVC和KVO完整且自动化的支持,除了为属性整合KVO和KVC访问方法外,还整合了适当的集合访问方法来处理多值关系;
2.自动验证属性(property)值;
3.支持跟踪修改和撤销操作;
4.关系维护,Core Data管理数据的关系传播,包括维护对象间的一致性;
5.在内存上和界面上分组、过滤、组织数据;
6.自动支持对象存储在外部数据仓库的功能;
7.创建复杂请求:无需动手写SQL语句,在获取请求(fetch request)中关联NSPredicate。NSPreadicate支持基本功能、相关子查询和其他高级的SQL特性。它支持正确的Unicode编码、区域感知查询、排序和正则表达式;
8.延迟操作:Core Data使用懒加载(lazy loading)方式减少内存负载,还支持部分实体化延迟加载和复制对象的数据共享机制;
9.合并策略:Core Data内置版本跟踪和乐观锁(optimistic locking)来支持多用户写入冲突的解决,其中,乐观锁就是对数据冲突进行检测,若冲突就返回冲突的信息;
10.数据迁移:Core Data的Schema Migration工具可以简化应对数据库结构变化的任务,在某些情况允许你执行高效率的数据库原地迁移工作;
11.可选择针对程序Controller层的集成,来支持UI的显示同步Core Data在IPhone OS之上,提供NSFetchedResultsController对象来做相关工作,在Mac OS X上我们用Cocoa提供的绑定(Binding)机制来完成的。
12.只有实现了NSCopying
和NSMutableCopying
协议的类的对象才能被拷贝,分为不可变拷贝和可变拷贝,具体区别戳这;
NSCopying
协议方法
- (id)copyWithZone:(NSZone *)zone {
MyObject *copy = [[[self class] allocWithZone: zone] init]; copy.username = [self.username copyWithZone:zone]; return copy;
}
1.自动释放池是NSAutorelease
类的一个实例,当向一个对象发送autorelease
消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release
消息,释放对象。
2.[pool release]、 [pool drain]
表示的是池本身不会销毁,而是池子中的临时对象都被发送release
,从而将对象销毁。