iOS開發Block的介紹以及Block的循環引用問題


1:block的循環引用問題最主要記住兩點:

如果【block內部】使用【外部聲明的強引用】訪問【對象A】, 那么【block內部】會自動產生一個【強引用】指向【對象A】

如果【block內部】使用【外部聲明的弱引用】訪問【對象A】, 那么【block內部】會自動產生一個【弱引用】指向【對象A】

 2:

#import "ViewController.h"
#import "XMGPerson.h"

@interface ViewController ()
@property (nonatomic, copy) int (^sumBlock)(int, int);
@property (nonatomic, assign) int a;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    [self test5];
    /*
     如果【block內部】使用【外部聲明的強引用】訪問【對象A】, 那么【block內部】會自動產生一個【強引用】指向【對象A】
     如果【block內部】使用【外部聲明的弱引用】訪問【對象A】, 那么【block內部】會自動產生一個【弱引用】指向【對象A】
     */
}

/**
 *  不可行
 */
- (void)test6
{
    XMGPerson *p = [[XMGPerson alloc] init];
    
    __weak XMGPerson *weakP = p;
    
    p.name = @"Jack";
    
    p.block = ^{ // block1
        XMGPerson *strongP = weakP;
        NSLog(@"block1 -- %@", strongP.name);
        
        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
            NSLog(@"block2 -- %@", weakP.name);
        });
    };
    
    p.block();
}

/**
 *  可行
 */
- (void)test5
{
    XMGPerson *p = [[XMGPerson alloc] init];
    
    __weak XMGPerson *weakP = p;
    
    p.name = @"Jack";
    
    p.block = ^{ // block1
        NSLog(@"beign-------");
        XMGPerson *strongP = weakP;
        
        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
            
            // NSLog(@"block2 -- %@", weakP.name);
            NSLog(@"block2 -- %@", strongP.name);
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // block3
                NSLog(@"block3 -- %@", strongP.name);
            });
            
        });
    };
    
    p.block();
}

/**
 *  不可行
 */
- (void)test4
{
    XMGPerson *p = [[XMGPerson alloc] init];
    
    p.name = @"Jack";
    
    p.block = ^{ // block1
        NSLog(@"beign-------");
        
        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
            NSLog(@"after-----------%@", p.name);
        });
    };
    
    p.block();
}

/**
 *  不可行
 */
- (void)test3
{
    XMGPerson *p = [[XMGPerson alloc] init];
    __weak XMGPerson *weakP = p;
    
    p.name = @"Jack";
    
    p.block = ^{ // block1
        NSLog(@"beign-------");
        XMGPerson *strongP = weakP;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                       ^{ // block2
                           NSLog(@"after-----------%@", strongP.name);
                       });
    };
    
    p.block();
}

/**
 *  可行
 */
- (void)test2
{
    XMGPerson *p = [[XMGPerson alloc] init];
    
    __weak XMGPerson *weakP = p;
    
    p.name = @"Jack";
    p.block = ^{ // block1
        NSLog(@"beign-------");
        
        XMGPerson *strongP = weakP;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                       ^{ // block2
                           NSLog(@"after-----------%@", strongP.name);
                       });
    };
    
    p.block();
}

- (void)test1
{
    XMGPerson *p = [[XMGPerson alloc] init];
    
    __weak XMGPerson *weakP = p;
    
    p.name = @"Jack";
    p.block = ^{
        NSLog(@"-----------%@", weakP.name);
    };
}


#pragma mark - 其他
- (void)test:(int (^)(int, int))sumBlock
{
    
}

- (void)run:(int)a
{
    
}

- (void)testBlock
{
    [self test:^(int a, int b){
        return a + b;
    }];
    
    
    void (^block)() =  ^{
        NSLog(@"-------");
    };
    block();
    
    
    
    
    int (^sumBlock)(int, int) = ^(int num1, int num2){
        return num1 + num2;
    };
    sumBlock(10, 10);
    
    
    int a = 10;
    
    /*
     返回值類型 (^block的變量名)(形參類型列表) = ^(形參列表) {
     // block代碼
     };
     block的變量名(實參列表);
     */
}

@end

總結:1:block的定義:1:block以屬性定義的時候,用copy修飾,

@property (nonatomic, copy) void (^block)();無參數無返回值,因為block默認是在堆里,需要將堆中的block,copy到棧中才能使用  2:block的非屬性定義:1:無參數無返回值:

其中 void (^block)() 表示聲明一個名稱為block的block,block的類型表示為:void (^)(),右邊的為block任務的代碼塊,
    block();表示調用block,右邊為左邊的block賦值
  void (^block)() =  ^{ NSLog(@"-------"); }; block(); 
2:有參數有返回值的block:左邊
int (^sumBlock)(int, int)定義一個有參數有返回值的block:sumBlock,而右邊的block給左邊的block賦值,寫法:參數寫在^(int a,int b)其中ab為block的參數,返回值寫在block的代碼塊中。
 sumBlock(10, 10);調用block,並未block傳遞參數
 ^(int num1, int num2){
        return num1 + num2;
    };
 
  int (^sumBlock)(int, int) = ^(int num1, int num2){ return num1 + num2; }; sumBlock(10, 10); 
3:block作為參數傳遞:1: block作為參數傳遞 - (void)test:(int (^)(int, int))sumBlock,實現該方法,調用block傳遞參數 2:在外部調用test方法,其中ab就為傳遞的參數,

     [self test:^(int a, int b){

        NSLog(@"%d",a+b);

        return a + b;

    }];

 

- (void)test:(int (^)(int, int))sumBlock

{   

sumBlock(2,1);

}

 

4:1:block的循環引用:XMGPerson alloc init 之后在內存中產生一個對象,name 和 block是該對象的屬性(因為用copy修飾,也就相當於強引用),則該對象會對這兩個屬性分別有一個強引用,創建完對象之后,有一個強指針p指向該對象(指針里存放的是對象的地址,變量創建之后無論是全局變量還是局部變量都會有一個強引用),__weak那部分代碼是將強指針p的地址復制給一個弱指針weakSelf,此時弱指針weakSelf會有一個弱引用指向person對象,p.name = @"JACK";此時name屬性會對jack有一個強引用,block會對賦值的block有一個強引用。此時不會立即調用block代碼塊中的任務,但是此時會檢測block代碼塊中有無引用外部變量(即使是外部無引用,在after中引用了,也算block中引用了外部變量,此時會對訪問的該對象有一個強引用或是弱引用,代碼塊中有引用weakP,所以會產生一個弱引用),再執行代碼調用block,執行block代碼塊中的任務,將一個弱引用weakP指針賦值給一個強引用,此時block代碼塊中的strongP會對person對象有一個強引用,在執行gcd延遲函數,此時會產生延遲函數的block塊,會檢測延遲函數中有無引用外界的變量,有引用了strongP,則會產生一個強引用指向person對象,此時的代碼塊不立即執行(但是系統會有一個強指針指向該代碼塊,如圖2),此時會執行到方法結束,強指針p銷毀,弱指針weakp銷毀,strongP執行完銷毀,但此時block2還指向person對象,所以person對象不會銷毀,能打印出name  2:像類似於GCD的延遲函數在block中,想要保住對象使其不備銷毀,就在block中定義一個強引用指向就可以了

 
        

 

 

 









免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM