美文网首页
OC语言day08-19copy和property

OC语言day08-19copy和property

作者: liyuhong165 | 来源:发表于2016-09-04 19:12 被阅读21次

    pragma mark copy和property

    pragma mark 概念

    /**
     copy二个用途、一个引发问题
     
     1.copy的第一个用途, 防止外界修改内部的数据
     2.copy的第二个用途:__ 可以使用copy保存block, 这样可以保住 block中 使用的外界对象的命
     3.copy block之后引发 循环引用 (你引用我,我引用你 双方都无法释放)
     3.1 第三点出现的问题 需要对里面使用到的对象 添加一个 __block(意思是: 不要对block使用到该对象时, 进行一次retain操作)
     
     __block 用处
     1. 可以 在内部 修改 外部的值
     2. 并且引用计数不会加1
     
     */
    

    pragma mark 代码

    #import <Foundation/Foundation.h>
    #pragma mark 类
    #import "Person.h"
    #import "Dog.h"
    #pragma mark main函数
    int main(int argc, const char * argv[])
    {
    #pragma copy和property
       
    #pragma mark 一.copy的第一个用途, 防止外界修改内部的数据
     #warning 1.
        NSMutableString *temp = [NSMutableString stringWithFormat:@"lyh"];
        Person *p = [[Person alloc]init];
        p.name = temp;
        // 问题 : 修改了外面的变量, 影响到了 对象中的属性
        [temp appendString:@" cool"];
        NSLog(@"name = %@",p.name);
        // 记住 : 以后字符串属性都用copy
        NSLog(@"-----------1.end------------\n");
    
    #warning 2.block 在内容修改 外部的值 (需要在 外部变量 添加 __block) [本质:block 默认存储在栈中 不会对外界的对象进行retain, 在堆才会]
        // 调用block 想在内部里面修改 外部的值 加上__block
        __block int num = 10;
        // 1. 定义block
        void (^myBlock) () = ^{
            num = 20;
            NSLog(@"%i",num);
            
        };
        
        // 2.调用block
        myBlock();
        // 3. block 默认存储在栈中, 栈中的block 访问到了外界的对象, 不会对 外界的对象的进行retain \
            block 如果在堆中, 如果 在block中访问了外界的对象, 会对外界的对象 进行一次retain
        NSLog(@"-----------2.end------------");
    
        
    #warning 3.测试 将block 进行copy
        Person *p1 = [[Person alloc]init];
        NSLog(@"retainCount = %lu",[p retainCount]);
        // 1. 定义block
        void (^myBlock1) () = ^{
            num = 20;
            
            NSLog(@"%@",p);
            NSLog(@"retainCount = %lu",[p retainCount]);
    
        };
    //    myBlock1();
        Block_copy(myBlock1); // 对block进行拷贝   // 将block转移到堆中
        myBlock1();
        NSLog(@"-----------3.end------------");
    
        
    #pragma mark 二.copy的第二个用途:__ 可以使用copy保存block, 这样可以保住 block中 使用的外界对象的命
                // 避免以后调用 block的时候, 外界的对象 已经释放了
        
    #warning 4.
        Dog *d = [[Dog alloc]init]; //  引用计算器 1
        NSLog(@"d tainCount = %lu",[d retainCount]);
    
        Person *p2 = [[Person alloc]init];
        p2.pBlock = ^{
            NSLog(@"%@",d); // 访问 这条狗
        };  // 对block进行赋值
        NSLog(@"d tainCount = %lu",[d retainCount]);    // 2
    
    #warning 这里的block不知道什么时候调用 但是狗有可能提前释放了(开启僵尸对象 可以查看内存)
        // [Dog respondsToSelector:]
        // 如果狗仔 调用block之前释放了, 那么程序就会崩溃
        
        [d release]; // \
        [block 为assgin] 引用计算器 0 \
        [block 为copy 引用计算器 为 1]
    
        p2.pBlock(); // 执行p的block \
        [block 为assgin] 此处的狗的指针 是一个野指针 会崩溃 \
        [block 为copy 需要在dealloc里面进行[block 进行release] 操作  --- Block_release(_pBlock); ]
        [p2 release];
        NSLog(@"-----------4.end------------");
    
    #pragma mark 三. copy block之后引发 循环引用 (你引用我,我引用你 双方都无法释放)
    #warning 5.
        // 3. copy block之后引发 循环引用
        // 如果 对象中的block 有 用到了对象自己, 为了避免内存泄露, 应该将对象 修饰为 __block (里面不会进行retain了)
        __block Person *p3 =[[Person alloc]init];   // 1
        NSLog(@"p3 tainCount = %lu",[p3 retainCount]);
        p3.name = @"lyh";
        p3.pBlock = ^{
            NSLog(@"%@",p3.name);       // 2
        };
        NSLog(@"p3 tainCount = %lu",[p3 retainCount]);
    
        p3.pBlock();
        
        [p3 release];   // 1
    //    [p3 release];   // 2B青年
        
        return 0;
    }
    
    
    
    Person.h //人类
    #import <Foundation/Foundation.h>
    
    typedef void (^myBlock)();
    
    @interface Person : NSObject
    
    //@property(nonatomic, retain)NSString *name;
    
    @property(nonatomic, copy)NSString *name;
    
    //  注意: 如果block 使用 copy 并不是 拷贝, 而是从栈区 转移到 堆区
    @property (nonatomic,copy)myBlock pBlock;
    @end
    
    Person.m
    #import "Person.h"
    
    @implementation Person
    
    
    - (void)dealloc
    {
        // 只要 给 block 发送一条release消息, block中使用到的对象 也会收到该消息
        Block_release(_pBlock);
        NSLog(@"%s",__func__);
        [super dealloc];
    }
    
    @end
    

    Dog.h //狗类
    #import <Foundation/Foundation.h>
    
    @interface Dog : NSObject
    
    @end
    
    Dog.m
    #import "Dog.h"
    
    @implementation Dog
    - (void)dealloc
    {
        NSLog(@"%s",__func__);
        [super dealloc];
    }
    @end
    

    相关文章

      网友评论

          本文标题:OC语言day08-19copy和property

          本文链接:https://www.haomeiwen.com/subject/wiglettx.html