【Objective-C学习记录】第二十九天

内存管理的规则

1.alloc创建的必须释放,便利构造器创建的不要释放

2.加入容器中的对象会被执行一次retain操作,引用计数加1

3.容器移除对象,会向对象发送一次release消息,让对象的引用计数减1

4.当容器释放的时候,会向容器中的所有对象发送一次release消息

当进行内存管理时,只要遵循每次增加都对应一次释放就不会出错。下面是一个例子:

定义一个Hero类,添加如下几个属性和初始化方法:

1 @property (nonatomic, copy) NSString *name;
2 @property (nonatomic, assign) NSInteger speed;
3 @property (nonatomic, retain) NSString *ability;
4 
5 - (instancetype)initWithName:(NSString *)name speed:(NSInteger)speed ability:(NSString *)ability;
6 + (Hero *)heroWithName:(NSString *)name speed:(NSInteger)speed ability:(NSString *)ability;

在.m文件里一定要设置属性:

1 @synthesize name = _name;
2 @synthesize speed = _speed;
3 @synthesize ability = _ability;

接着实现初始化方法和销毁方法:

 1  - (void)dealloc
 2 {
 3      //因为speed不是对象类型所以不需要释放内存
 4      [_name release];
 5      [_ability release];
 6      [super dealloc];  
 7  }
 8   
 9  - (instancetype)initWithName:(NSString *)name speed:(NSInteger) speed ability:(NSString *)ability
10  {
11       self = [super init];
12       if (self)
13       {
14            _name = name;
15            _speed = speed;
16            _ability = ability; 
17       }
18       return self;
19 }
20  
21 + (Hero *)heroWithName:(NSString *)name speed:(NSInteger) speed ability:(NSString *)ability
22 {
23       return [[[Hero alloc] initWithName:name speed:speed ability:ability] autorelease];
24 }

以及setter和getter方法:

 1 - (void)setName:(NSString *)name
 2 {
 3     if(_name != name)
 4     {
 5         [_name release];
 6          _name = [name copy];
 7     }
 8 }    
 9 - (NSString *)name
10 {
11     return [[_name retain] autorelease];
12 }
13 
14 - (void)setAbility:(NSString *)ability
15 {
16     if(_ability != ability)
17     {
18          [_ability release];
19          _ability = [ability retain];
20     }
21 }
22 - (NSString *)ability
23 {
24     return [[ability retain] autorelease];
25 }

KVC

Key Value Coding,键值编码,是一种间接访问实例变量的方法。

KVC提供了一种使用字符串(key)而不是访问器方法,去访问一个对象实例变量的机制。

常用方法:

- (id)valueForKey:(NSString *)key;通过key(实例变量名)获取实例变量的值。

- (void)setValue:(id)value forKey:(NSString *)key;通过key(实例变量名)给实例变量赋值。

- (id)valueForKeyPath:(NSString *)keyPath;通过keyPath获取实例变量的值。

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;通过keyPath给实例变量赋值。

- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;将一个字典对象的键值对给对象的各个实例变量赋值。

注意!当使用KVC时,如果key值和属性名不一样时,就会崩溃。在解决该情况之前,先看看KVC的内部实现过程:

A.setValue:forKey:(假如给的key是name)

1.去类里面找是否有一个方法叫setName:,有的话赋值,没有的话执行第二步

2.去类里面找是否有一个叫_name的实例变量,有的话赋值,没有的话执行第三步

3.去类里面找是否有一个叫name的实例变量,有的话赋值,没有的话执行第四步

4.查找当前类是否实现了setValue:forUndefinedKey:方法,如果有,走方法内部实现,如果还没有,就会抛出异常,引起崩溃

B.valueForKey:(假设给的key是name)

1.去类里面找是否有一个方法叫getName:,有的话取值,没有的话执行第二步

2.去类里面找是否有一个叫_name的实例变量,有的话取值,没有的话执行第三步

3.去类里面找是否有一个叫name的实例变量,有的话取值,没有的话执行第四步

4.查找当前类是否实现了valueForUndefinedKey:方法,如果有,走方法内部实现,如果还没有,就会抛出异常,引起崩溃

所以为了防止崩溃情况的发生,只需要重新实现以下setValue:forUndefinedKey:valueForUndefinedKey:这两个方法即可:

1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
2 {
3 
4 }
5 
6 - (id)valueForUndefinedKey:(NSString *)key
7 {
8     return nil;
9 }

setValue:forUndefinedKey:方法里可以填充与之相关的操作

 

posted @ 2015-12-31 20:03  Shvier  阅读(156)  评论(0编辑  收藏  举报