zoukankan      html  css  js  c++  java
  • 【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:方法里可以填充与之相关的操作

  • 相关阅读:
    AtCoder Grand Contest 015 题解
    AtCoder Grand Contest 014 题解
    AtCoder Grand Contest 013 题解
    AtCoder Grand Contest 012 题解
    AtCoder Grand Contest 011 题解
    AtCoder Grand Contest 010 题解
    AtCoder Grand Contest 009 题解
    NOIP2017 Day2 题解
    博客园主题备份
    多项式全家桶
  • 原文地址:https://www.cnblogs.com/shvier/p/5092592.html
Copyright © 2011-2022 走看看