Object-C基础(8)——KVC、KVO与继承

合成属性

     (1)使用@property来合成属性。

      @property (指示符) 类型 属性名; 

      @property合成属性之后,一次性得到3个东西:成员变量、setter方法、getter方法。

     (2)使用@synthesize指定合成属性对应的成员变量的名字。

合成属性的指示符

      assign:如果属性类型是基本类型,就用该指示符。

                       short、int、long、long long、float、double、BOOL、枚举。

                      程序只对该属性赋值,不改变引用计数(RC)。

      atomic | nonatomic: 对于该属性的赋值操作(setter)是否为原子的。

                     如果setter是原子的,也就是线程安全的,那么性能较低;反过来,线程不安全,性能就更好。

                     如果你声明该属性是atomic,那么你去重写setter、getter方法时,就必须自己保证线程安全。

      copy:对属性赋值时,程序会先把被赋的值拷贝一个副本。然后用副本进行赋值。

                  一般来说,如果你被赋的值的类型是可拷贝的,尽量使用该指示符。

                  getter、setter: 用于改变getter、setter方法的方法名。

                  getter=方法名   setter=方法名:

      readonly|readwrite:readonly表明只生成getter方法,没有setter方法。

                                            readwrite表明同时生成getter、setter方法 —— 这个是默认。

      retain:每次赋值,都会将其RC增加1。 ——你们以后基本上不会使用它。主要在MRC(Manual Reference Counting).在ARC(Auto Reference Counting)阶段无需使用该指示符。

      weak | strong:弱引用和强引用。

                                 弱引用:一个弱引用不会增加对象的RC。通过弱引用去访问被指向的对象时,可能为nil。

                                 当两个对象形成强引用循环时,就一定要把其中一个引用改为弱引用。

                                 强引用:默认就是strong。

      unsafe_unretainted:类似于weak,实际用的很少。

KVC(key-valuecoding、键-值编码)

      按以前的做法,要改变对象的属性,要么直接对对象成员变量赋值,要么调用它的setter方法。 

      KVC: 是一种允许动态操作对象属性的机制。

      KVC只有2个方法:

      - [对象 setValue:值 forKey:属性名] —— 相当于调用  [对象 set属性名:值];

      - [对象 valueForKey:属性名]   —— 相当于 [对象 属性名]

      用了KVC之后,forKey后面的属性名支持变量,因此可以动态变化,这就是优势。

      上面这两个方法都来自于NSObject。

      KVC的查找顺序

        [user setValue: 值 forKey:@"name"];

        查找顺序如下:

        (1)KVC会查找user是否有setName:方法。如果有,就执行setName:方法。

        (2)如果setName:不存在,KVC会查找user是否存在名为_name的成员变量,如果有,直接对_name赋值。

        (3)如果setName:不存在,_name也不存在,KVC会查找user是否存在名为name的成员变量,如果有,直接对name赋值。

        (4)如果上面3步都没有找到,就会激发setValue:forUndefinedKey:方法。

                 setValueForUndefinedKey:是系统定义的方法,默认行为就是报错,我们可以重写该方法。


        [user valueForKey: @"name"];

        查找顺序如下:

        (1)KVC会查找user是否有name方法。如果有,就执行name方法。

        (2)如果name不存在,KVC会查找user是否存在名为_name的成员变量,如果有,直接返回_name的值。

        (3)如果name:不存在,name也不存在,KVC会查找user是否存在名为name的成员变量,如果有,直接返回name的值。

        (4)如果上面3步都没有找到,就会激发valueForUndefinedKey:方法。

                  valueForUndefinedKey:是系统定义的方法,默认行为就是报错,我们可以重写该方法。

     处理不存在的key

        当你通过kvc对不存在的key进行设值时,系统自动激发setValue:forUndefinedKey:方法。

        setValue: forUndefinedKey:方法默认的行为是报一堆的错误信息。

        如果我们希望改变这种行为,可以重写该方法。

        当你通过kvc访问不存在的key对应的值时,系统自动激发valueForUndefinedKey:方法。

        valueForUndefinedKey:方法默认的行为是报一堆的错误信息。

        如果我们希望改变这种行为,可以重写该方法。

     处理nil值

        对于KVC而言,如果属性是指针类型,可以为之设置nil值的。如果属性是基本类型,它是不能接受nil值的。

        如果程序尝试对不能接受nil值的属性,使用kvc设置为nil,程序将会自动激发setNilValueForKey:方法。

             setNilValueForKey:是系统定义的方法,默认行为就是报错,我们可以重写该方法。

        重写setNilValueForKey:方法即可让程序获得对nil值进行任意定制处理的机会。

       KVC另外2个高级方法:用于处理key路径。

         -setValue: forKeyPath: key路径

         -valueForKeyPath: key路径

         这两个高级方法只是将原来的forKey:,改成了forKeyPath:,这样就可以为复合属性设置值。

 KVO(key-value observing,键、值监听)

     它可用于监听某个对象的状态发生了修改。

     在cocoa touch典型开发中,model组件负责数据部分,但view负责显示部分,此时当model发生改变时,View需要立即更新自己。

     通常来说,有如下几种做法:

     1. 让model组件持有一个view组件的引用,当model的状态发生改变时,model即可调用view的方法来更新view的状态。

          缺陷:由于View必须依赖model(因为它显示的数据来自model),这样就形成相互依赖,很糟糕的设计。

     2. 利用iOS的通知中心来实现。model发生改变时,会发送一个消息给通知中心;而view组件收到消息之后,立即去获取model数据,更新自己。

         缺陷:这么小的功能,没必要用iOS的通知中心。

     相对来说,比较简单、方便、轻度的解决方案就是此处KVO。

     ——只要让View作为model的监听器即可,当model的状态发生改变时,View特定的监听方法就会被激发。

     【注意:】这个监听方法也属于重写父类的方法。

    (1) 注册监听器。(view监听模型)

        被监听的对象 addObserver: 监听器forKeyPath: 被监听的属性 options: context:

    (2) 重写监听器的特定方法。

       observeValueForKeyPath: ofObject:change:  context:

    最后还要注意:应该重写监听器的dealloc方法,保证系统回收该对象时,取消监听器。

对象的初始化

     创建对象要分为2部分:

     1. 分配内存。  [类名 alloc]

     2. 执行初始化。 init方法。

     init方法,也被称为【构造器】

     NSObject本身提供了init方法,因此程序也可以自行去实现init方法。

      重写NSObject的init方法

     NSObject的init方法只是将所有的成员变量初始化为广义的0.

     如果你希望执行默认的初始化,就可以重写init方法。

     便利的初始化方法—— 带参数的初始化方法。

        initWithXxx: yyy: zzz: www: ...

        很多时候,还会提供一个类方法,用于执行对象的初始化。该方法名通常为: 类名WithXxx:yyy: zzz: www: ...

继承

     面向对象的3大特征之一。

    什么是继承?继承是一种非常重要的代码复用的手段:子类继承了父类,子类就可直接获取父类的成员变量、方法、初始化方法。

    继承关系,是一种由一般到特殊的关系。子类,其实就是一种特殊的父类。

    面向对象的继承,其实是一种类与类之间关系,不是对象与对象之间的关系。

    子类,继承父类;可认为子类(小类)是一种特殊的父类(大类)

    继承语法

    @interface 类名 : 父类

    @end

    Object-C是一门单继承的语言,因此每个类最多只能有一个直接父类。

    @interface Fruit : NSObject

    @end;


    @interface Apple : Fruit

    @end;


    @interface RedFuji: Apple

    @end

    RedFuji的直接父类(immediateparent)是Apple,其他父类还有Fruit、NSObject。

    一个结论:一些类都是NSObject的子类。一切皆对象!

    重写父类的方法

      有时候,子类需要重新定义自己的行为,此时就要考虑重写父类的方法。

      重写父类方法:将父类方法的方法签名拷贝过来(也就要子类方法与父类方法的签名相同),但方法体是重新定义的。

      【注意:】子类重写父类方法时,并不需要在子类的接口部分重新声明。

      一旦重写了父类的方法之后,当程序执行子类中重写过的方法时,程序将会表现出被重写后的行为。

    super关键字

      总是用于显式调用父类的方法。

你可能感兴趣的:(继承,KVO,Object-C,KVC)