block使用時的一些情況以及防止迴圈引用

2021-07-11 21:26:06 字數 3080 閱讀 3078

block 是在 ios 4 中引入的新特性,蘋果官方推薦使用這種做法。

block 注意事項

1,block 在實現時就會對它引用到的它所在方法中定義的棧變數進行一次唯讀拷貝,然後在 block 塊內使用該唯讀拷貝。

如下**:

-(void)testvariable

; outsidevariable = 30;

self

.membervariable = 30;

blockobject();

nslog(@" > %lu items in outsidearray", (unsigned

long)[outsidearray count]);}

列印結果如下:

注意到outside 變數的輸出值為10,這是因為blockobject 在實現時會對 outside 變數進行唯讀拷貝,在 block 塊內使用該唯讀拷貝。因此這裡輸出的是拷貝時的變數值 10。如果,我們想要讓 blockobject 修改或同步使用 outside 變數就需要用 __block 來修飾 outside 變數。

**注意**
a),在上面的 block 中,我們往 outsidearray 陣列中新增了值,但並未修改 outsidearray 自身,這是允許的,因為拷貝的是 outsidearray 自身。

b),對於 static 變數,全域性變數,在 block 中是有讀寫許可權的,因為在 block 的內部實現中,拷貝的是指向這些變數的指標。

c), __block 變數的內部實現要複雜許多,__block 變數其實是乙個結構體物件,拷貝的是指向該結構體物件的指標。

2 ,使用 weak–strong dance 技術來避免迴圈引用

在block中呼叫self很可能會引起迴圈引用,在block中需要對weakself進行strong,保證**在執行到block中,self不會被釋放,當block執行完後,會自動釋放該strongself。

先看這個例子:

nsarray *anarray = @[@"1", @"2", @"3"];

[anarray enumerateobjectsusingblock:^(id obj, nsuinteger idx, bool *stop) ];

這種情況下,block中retain了self,當block中的**被執行完後,self就會被arc釋放。所以不需要處理weakself的情況。

該vc被銷毀後會有delloc列印。

再來看乙個例子:

nsarray *anarray = @[@"1", @"2", @"3"];

[anarray enumerateobjectsusingblock:^(id _nonnull obj, nsuinteger idx, bool * _nonnull stop) ];

// __weak secondviewcontroller *weakself = self;

self

.ablock = ^(id obj, nsuinteger idx, bool *stop);

這種情況編譯器會包警告提示這兒的self:

並且不會有delloc的列印。

這個例子的區別在於:block被self strong引用。所以結果就是block中引用了self,self引用了block。那麼這個時候,如果你不使用weakself,則self和block永遠都不會被釋放。

那麼是不是遇到block都要使用weakself呢?當然不是,而且如果全部使用weakself,會出現你想執行block中的**時,self已經被釋放掉了的情況。

還有一種比較常用的方法,這個方法比較通用:

/**

* 強弱引用轉換,用於解決**塊(block)與強引用self之間的迴圈引用問題

* 呼叫方式: `@weakify_self`實現弱引用轉換,`@strongify_self`實現強引用轉換

** 示例:

* @weakify_self

* [obj block:^];

*/#ifndef weakify_self

#if __has_feature(objc_arc)

#define weakify_self autoreleasepool{} __weak __typeof__(self) weakself = self;

#else

#define weakify_self autoreleasepool{} __block __typeof__(self) blockself = self;

#endif

#endif

#ifndef strongify_self

#if __has_feature(objc_arc)

#define strongify_self try{} @finally{} __typeof__(weakself) self = weakself;

#else

#define strongify_self try{} @finally{} __typeof__(blockself) self = blockself;

#endif

#endif

/*** 強弱引用轉換,用於解決**塊(block)與強引用物件之間的迴圈引用問題

* 呼叫方式: `@weakify(object)`實現弱引用轉換,`@strongify(object)`實現強引用轉換

用的時候就:

@weakify(self) 外部weak

@strongify(self) 內部strong

這樣就避免了迴圈引用了,dealloc列印如下:

2016-05-18 11:36:31.531 lianxi[10219:1055254]*****dealloc

no retain cycle

Block 的使用時機

block 一般是用來表示 簡化一小段的程式碼,它特別適合用來建立一些同步執行的程式片段 封裝一些小型的工作或是用來做為某乙個工作完成時的回傳呼叫 callback 在新的ios api中block被大量用來取代傳統的delegate和callback,而新的api會大量使用block主要是基於以下...

block 的一些理解

typedef qglabel block3 uicolor color inte ce qglabel uilabel property nonatomic,copy block3 block2 property nonatomic,copy block3 block3 end implement...

Block使用中的一些疑問解答

本文主要是闡述一下block中如何的使用外部變數以及block本身的記憶體管理。先定義乙個block變數,作為後續的例子中使用 typedef void blockcc void blockcc block block中可以直接使用外部的變數,比如 int number 1 block 那麼實際上,...