zoukankan      html  css  js  c++  java
  • oc82--成员变量使用copy修饰

    //
    //  Person.h
    
    #import <Foundation/Foundation.h>
    
    
    typedef void (^myBlock)();
    
    @interface Person : NSObject
    
    //@property (nonatomic, retain) NSString *name;
    @property (nonatomic, copy) NSString *name;
    
    // 注意: 如果是block使用copy并不是拷贝, 将pBlock所指向的代码块从栈转移到堆中。block在堆中,使用外界对象的时候,会对外界对象的计数器加1,
    @property (nonatomic, copy) myBlock pBlock;
    //@property (nonatomic, retain) myBlock pBlock;
    @end
    //
    //  Person.m
    
    #import "Person.h"
    
    @implementation Person
    
    - (void)dealloc
    {
        // 由于block使用外界对象会对里面的对象加1,因此要在Person释放的时候把里面使用的对象也释放。
        // 只要给block发送一条release消息, block中使用到的对象d也会收到该消息。
        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
    //  main.m
    //  Copy与string,block的结合使用
    
    #import <Foundation/Foundation.h>
    #import "Person.h"
    #import "Dog.h"
    
    int main(int argc, const char * argv[]) {
        
        // 1.copy的第一个用途, 防止外界修改内部的数据
        NSMutableString *temp1 = [NSMutableString stringWithFormat:@"lnj"];
        Person *p1 = [[Person alloc] init];
        p1.name = temp1;  //p1.name是一个新的对象,
        // 问题: 修改了外面的变量, 影响到了对象中的属性,记住: 以后字符串属性都用copy
        [temp1 appendString:@" cool"];
        NSLog(@"name = %@", p1.name);//lnj
        
        
        
        __block int num = 10;//block的本质是传了指针。才能修改外面的变量。
        void (^myBlock1)() = ^{
            num = 20;
            NSLog(@"%i", num);
        };
        myBlock1();// 20
        
        
        
        // block默认存储在栈中, 栈中的block访问到了外界的对象, 不会对对象进行retain
        // block如果在堆中, 如果在block中访问了外界的对象, 会对外界的对象进行一次retain
        Person *p2 = [[Person alloc] init];
        NSLog(@"retainCount = %lu", [p2 retainCount]);//1
        void (^myBlock)() = ^{
            NSLog(@"%@", p2);
            NSLog(@"retainCount = %lu", [p2 retainCount]);
        };
        myBlock();// retainCount = 1
        Block_copy(myBlock); // 将block转移到堆中
        myBlock();// retainCount = 2
        
        
        
        
        // 2.可以使用copy保存block, 这样可以保住block中使用的外界对象的命
        // 避免以后调用block的时候, 外界的对象已经释放了
        /*__block*/ Dog *d = [[Dog alloc] init]; // 1
        NSLog(@"Dog retainCount = %lu", [d retainCount]);// 1
        Person *p3 = [[Person alloc] init];
        p3.pBlock = ^{
            //2,block在堆中,使用外界对象的时候,会对d的计数器加1,Dog前面加了__block,block里面使用dog也不会对dog加1,
            NSLog(@"%@", d);
        };
        NSLog(@"Dog retainCount = %lu", [d retainCount]); // 2
        // 如果狗在调用block之前释放了, 那么程序就会崩溃
        [d release]; // 1
        p3.pBlock();
        [p3 release];
        
        
        
        // 3.注意点: copy block之后引发循环引用。
        // 如果对象中的block又用到了对象自己, 那么为了避免内存泄露, 应该将对象修饰为__block。
        __block Person *p = [[Person alloc] init]; // 1
        p.name = @"lnj";
        NSLog(@"retainCount = %lu", [p retainCount]);
        p.pBlock = ^{//由于是copy,所以这段代码在堆中,
            NSLog(@"name = %@", p.name); // 2,由于内部用到了外部对象p,对p加1,所以p为2,所以p前面要加__block,block里面就不会对外部对象加1,
        };
        NSLog(@"retainCount = %lu", [p retainCount]);
        
        p.pBlock();
        
        [p release]; // 1,p始终是1,无法释放。
        [p release]; // 2B
        
        return 0;
    }

     3的图片内存示意图

    pBlock指向的是堆中的代码块地址。

  • 相关阅读:
    5-29
    5-28
    5-27
    -5-26
    5-25
    5-24
    5-21
    RabbitMQ消息中间件极速入门与实战
    细说java多线程之内存可见性
    全面解析java注解
  • 原文地址:https://www.cnblogs.com/yaowen/p/7442955.html
Copyright © 2011-2022 走看看