//属性的属性

属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在property里面重置setter或者getter的方法名(例如:@property(readwrite,setter=haha:,getter=dedaomingnzi) NSString *name;)属性的约束有:读写约束(readonly、readwrite)原子约束(atomic)非原子约束

也可以在.m文件里定义当前类的私有的实例变量和私有方法(私有方法在声明的时候也在.m文件里声明,如果在.h文件里声明,那就是能够提供给外部接口的方法了)这就是一个类的延展(Extension);如果一个我们看不到源代码的类,我们需要他的一些方法的实现,但是该类没有实现,那就建立一个分类 ,注意分类只能仅仅是添加类的方法,category;

 

/*

 1.读写特性(写在 property 关键字后面的 括号内 如果不设置的话,那就是默认的readwrite

 readonly(只能去读(获取值)不能写,只有getter方法,只能获取值,不能写)

 readwrite(默认的特性  既可以读又可以写,相当于他有gettersetter方法,可以访问( 值)也可以赋值)

 setter= 的用法:他是设置 setter 方法的名字 例如:@property(readwrite,setter = haha:) NSString *name;我们在使用的时候,直接  [对象  haha:消息];

 getter= 设置getter的方法名字,也就是修改 getter 方法的名字

 

 2.原子特性

 atomic  原子特性

 nonatomic  非原子特性

 原子特性 非原子特性 的区别:在我们用setter getter 方法的时候,系统默认的是原子特性,原子特性是保护我们的线程安全(多加了个上锁 开锁的过程)好处:保护属性的安全 坏处:占用系统资源

 非原子特性:没有做线程处理,(只是简单的生成setter getter 方法)(苹果推荐使用的特性)

 线程:就是同时的做多件事

 

 3.语义特性

 assign (系统默认的特性)通常使用于基本类型 NSInterger,CGFloat,在取值与值的时候,只是简单的取值与赋值操作(就是里面自己写了 _name = name 的方法)

 retain 通常使用于 所有的对象类型 setter getter 方法就会自动生成内存优化的的代码

 copy   通常适用于对象类型,服从NSCoping 协议的对象类型才会使用 例如 NSString

 **/

 

什么是KVC

//KVC 就是三个单词的简写 key-value-coding)键值编码

        //为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制

        Person * per = [[Person alloc]init];

        //在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC

    //setValue:forKey:间接的给实例变量赋值 取值就是[对象 valueForKey:@“key”];

        //赋值过程

        //1.系统先检查有没有name这个实例变量

        //2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值

        //3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法

 

[per setValue:@"Niujianwei" forKey:@"na"];

        [per setValue:@"" forKey:@"gender"];

        [per setValue:@"Niuni" forKey:@"id"];

        [per setValue:@"sd" forKey:@"name1"];

        NSLog(@"%@",[per valueForKey:@"na"]);

        //一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey valueForUndefinedKey 两个方法

        NSLog(@"%@",per);

        

        //有时候我们为了避免出错 id 改为 ID 因为 id 可能代表所有类型

       // NSString * ID

        //有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值)

        

        //对应的取值过程

        //1.先检查有没有 name 这个实例变量

        //2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值

        //3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法

  

        //下面方法也是给实例变量赋值

      // per setValue:<#(id)#> forKeyPath:<#(NSString *)#>

        Phone * phone = [[Phone alloc]init];

        [phone setValue:@"iphone" forKey:@"brand"];//间接为手机赋值

        [per setValue:phone forKeyPath:@"phone"];

        NSLog(@"%@",[per valueForKey:@"phone"]);

        NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径

        [per setValue:@"小米手机" forKeyPath:@"phone.brand"];

         NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);

 setValue: forKey    setValue: forKeyPath:


 

这段代码有什么问题吗:
@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;//点语法用在”=“的左边,就是setter 方法,self是调用当前setter 方法的对象,这样就导致了死循环,所以不能这样使用哦
}
@end


 

什么是Protocol?什么是代理?写一个委托的interface?委托的property声明用什么属性?为什么?
协议提供了一组方法,但是并不负责实现,如果一个类遵循了某个协议,并且实现了协议里面的方法,那么我们称这个类就是遵循了某个协议的代理。属性的声明使用assign,防止出现循环引用的问题。
分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?
category类目:在不知道源码的情况下为一个类扩展方法,extension:为一个类声明私有方法和变量。
继承是创建了一个新的类,而类别只是对类的一个扩展,还是之前的类。
类目的作用就是为已知的类添加方法。

 

KVC键值编码,可以直接通过字符串的名字(key)来间接访问属性的机制,而不是通过调用getter和setter方法访问。

对应代码:

//
//  main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Phone.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
     //KVC 就是三个单词的简写 (key-value-coding)键值编码
        //为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制
        Person * per = [[Person alloc]init];
        //在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC
    //setValue:forKey:间接的给实例变量赋值
        //赋值过程
        //1.系统先检查有没有name这个实例变量
        //2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值
        //3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法
        [per setValue:@"Niujianwei" forKey:@"na"];
        [per setValue:@"" forKey:@"gender"];
        [per setValue:@"Niuni" forKey:@"id"];
        [per setValue:@"sd" forKey:@"name1"];
        NSLog(@"%@",[per valueForKey:@"na"]);
        //一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey 和 valueForUndefinedKey 两个方法
        NSLog(@"%@",per);
        
        //有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型
       // NSString * ID
        //有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值)
        
        //对应的取值过程
        //1.先检查有没有 name 这个实例变量
        //2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值
        //3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法
        
        //下面方法也是给实例变量赋值
      // per setValue:<#(id)#> forKeyPath:(NSString *)
        Phone * phone = [[Phone alloc]init];
        //为phone的实例变量brand赋值
        [phone setValue:@"iphone" forKey:@"brand"];
        //通过路径:间接为手机赋值
        [per setValue:phone forKeyPath:@"phone"];
        NSLog(@"%@",[per valueForKey:@"phone"]);
        NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径
        //通过路径:为per的实例变量phone的实例变量brand赋值
        [per setValue:@"小米手机" forKeyPath:@"phone.brand"];
         NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);
     // per setValuesForKeysWithDictionary:<#(NSDictionary *)#>
        
    }
    return 0;
}
View Code  main.m文件

相关文章: