码迷,mamicode.com
首页 > 其他好文 > 详细

知识点7

时间:2016-05-06 20:21:39      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:

KVC(Key-Value Coding)键值编码

KVO(Key-Value  Observing)键值观察

 

这两个方法都是runtime方法  运行时方法

 

KVC:

 

KVCClass *kvc = [KVCClass new];

//通过setValue: forKey:来动态设置属性的值

[kvc setValue:@"我是同过setValue方法设置的值" forKey:@"name"];

//通过valueForkey来获取值

NSLog(@"name = %@", [kvc valueForKey:@"name"]);

 

 

我们可以通过键路径给实例变量是其他类的对象赋值 setValue: forKeyPath:

 

//通过键路径来给KVCClass中的对象的属性赋值

SubKVCClass *sub = [SubKVCClass new];

kvc.subKVC = sub;  

[kvc setValue:@"我是subName, 通过kvc的键路径来给我赋的值" forKeyPath:@"subKVC.subName"];

NSLog(@"subName = %@", [kvc valueForKeyPath:@"subKVC.subName"]);

NSLog(@"%@", kvc);

 

 

到底什么是闭包或者block呢?用大白话说就是匿名函数

 

 在block中可以对全局变量进行访问和修改,但对局部变量只可以访问,若想修改的话,我们可以在声明局部变量的时候加上关键字__block

 

 

 

 

 

-(void)test{

    //定义两个变量一个是可变的一个是不可变的

    NSString *str1 = @"文明"; //不可变

    NSMutableString *str2 = [NSMutableString stringWithFormat:@"失灵"]; //可变

    //初始值

    NSLog(@"两个字符串的初始值和初始地址");

    NSLog(@"str1 = %@,  str1_p = %p", str1, str1);

    NSLog(@"str2 = %@,  str2_p = %p", str2, str2);

   

    //定义block在block中输出连个变量的值和参数

    void (^myBlock) () = ^()

    {

        NSLog(@"******************************************");

        NSLog(@"在block块中输出局部变量的可变和不可变变量");

        NSLog(@"str1 = %@,  str1_p = %p", str1, str1);

        NSLog(@"str2 = %@,  str2_p = %p", str2, str2);

    };

    

    //修改前赋值

    str1 = @"文明改变";

    [str2 appendString:@"改变"];

    NSLog(@"******************************************");

    NSLog(@"输出修改后的值和地址");

    NSLog(@"str1 = %@,  str1_p = %p", str1, str1);

    NSLog(@"str2 = %@,  str2_p = %p", str2, str2);

   

    //调用block

    myBlock();

    

    NSLog(@"******************************************");

    NSLog(@"调用block后的值和地址");

    NSLog(@"str1 = %@,  str1_p = %p", str1, str1);

    NSLog(@"str2 = %@,  str2_p = %p", str2, str2);

}

 

输出:

两个字符串的初始值和初始地址

str1 = 文明,  str1_p = 0x107898270

str2 = 失灵,  str2_p = 0x7fb3ca518e40

******************************************

输出修改后的值和地址

str1 = 文明改变,  str1_p = 0x107898350  //因为str1是不可变字符串  当其值修改了  就会产生一个新的字符串 会分配一个新的内存地址

str2 = 失灵改变,  str2_p = 0x7fb3ca518e40

******************************************

在block块中输出局部变量的可变和不可变变量

str1 = 文明,  str1_p = 0x107898270

str2 = 失灵改变,  str2_p = 0x7fb3ca518e40

******************************************

调用block后的值和地址

str1 = 文明改变,  str1_p = 0x107898350

str2 = 失灵改变,  str2_p = 0x7fb3ca518e40

 

 

总结:

对值类型的修改,如果block初始化后,无法同步到block内部  因为值类型修改后 就会产生一个新的内存地址  原先的不变 所以block中还是调用原先内存地址 所以没有改变  

 

对于引用类型的修改,如果block初始化后,修改指针指向,即指向另外一块内存,这样也是无法同步到block内部  因为指针指向另一个内存地址  原先的内存地址中的值没有改变 所以没有改变

 

对于引用类型的修改,如果block初始化后,对指针指向的内存进行修改,这样是可以用同步到block内部,但block内部同样无法修改。 因为没有产生新的内存地址 只是修改了原先的内存地址中的值 所以会改变。

 

 

 

成员变量在block中的使用是加上self->a使用的,所以在声明成员变量的时候加不加__block,在成员函数中的代码块中都可以访问修改;

 

 

 

@interface ViewController (){

 

    

    __block NSString *hasBlock;

    NSString *noBlock;

    

}

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

 

    [self test];

    

}

 

-(void)test{

 

    

    //分别给两个成员变量赋初始值

    hasBlock = @"ludashi";

    noBlock = @"ludashi";

    NSLog(@"hasBlock = %@, hasBlock_p = %p", hasBlock, hasBlock);

    NSLog(@" noBlock = %@,  noBlock_p = %p", noBlock, noBlock);

    

    //定义block

    void (^myBlock)() = ^()

    {

        //修改加__block的成员变量的值

        hasBlock = @"ludashi_update";

        NSLog(@"block中输出的内容");

        NSLog(@"hasBlock = %@, hasBlock_p = %p", hasBlock, hasBlock);

        NSLog(@" noBlock = %@,  noBlock_p = %p", noBlock, noBlock);

    };

    

    //改变noBlock的值

    noBlock = @"ludashi_update";

    NSLog(@"更新后的值");

    NSLog(@"hasBlock = %@, hasBlock_p = %p", hasBlock, hasBlock);

    NSLog(@" noBlock = %@,  noBlock_p = %p", noBlock, noBlock);

    

    //调用block

    myBlock();

    

    //调用block后的值

    NSLog(@"调用myBlock后的值");

    NSLog(@"hasBlock = %@, hasBlock_p = %p", hasBlock, hasBlock);

    NSLog(@" noBlock = %@,  noBlock_p = %p", noBlock, noBlock);

    

    

}

 

 

 

 输出:

hasBlock = ludashi, hasBlock_p = 0x1047b9270

noBlock = ludashi,  noBlock_p = 0x1047b9270    //如果两个字符串的值相同 则这两个字符串指向同一个内存地址

更新后的值

hasBlock = ludashi, hasBlock_p = 0x1047b9270

noBlock = ludashi_update,  noBlock_p = 0x1047b92d0

block中输出的内容

hasBlock = ludashi_update, hasBlock_p = 0x1047b92d0

noBlock = ludashi_update,  noBlock_p = 0x1047b92d0

调用myBlock后的值

hasBlock = ludashi_update, hasBlock_p = 0x1047b92d0

noBlock = ludashi_update,  noBlock_p = 0x1047b92d0

 

 总结:对于一个、多个成员变量,不管是否用__block修饰(用不用都没任何影响),block结构体会生成一个成员 :self,并且会引用成员变量所属的对象实例 self。

 

 

 

那么在ARC模式下是不是意味着我们就可以一点也不用进行内存管理的呢?并不是这样的,我们还需要代码进行内存的管理。

 

知识点7

标签:

原文地址:http://www.cnblogs.com/wwm881101/p/5466824.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!