Objective-C 碎碎念 9

本文為大地瓜原創(chuàng),歡迎知識共享,轉(zhuǎn)載請注明出處。
雖然你不注明出處我也沒什么精力和你計較。
作者微信號:christgreenlaw


本節(jié)是關于OC中極其重要的一個特性,BLOCK。

Overall

Block是iOS中一種比較特殊的數(shù)據(jù)類型。
一提到數(shù)據(jù)類型,應該就馬上能想到,它可以定義數(shù)據(jù)類型,作為形參,作為返回值這三點應該是看到數(shù)據(jù)類型就馬上想到的

應用場景:

  • 動畫
  • 多線程
  • 集合遍歷
  • 網(wǎng)絡請求回調(diào)

作用:
保存一段代碼,在恰當時間取出來使用(與函數(shù)很相似,但是比函數(shù)厲害)

指向函數(shù)的指針:

void method() {
  printf(@"aaa");
}
void (*p)();
p = method;
p();

block變量,和函數(shù)一樣:

  1. 可以沒有返回值,沒有形參
  2. 也可以有返回值沒形參
  3. 可以有返回值有形參
  4. 可以沒返回值有形參
    四種情況嘛
void (^methodBlock)();
  • void代表block沒有返回值
  • ()代表block保存的代碼沒有形參
  • (^methodBlock)代表methodBlock是一個block變量,可以用于保存一段block代碼
methodBlock = ^{
  printf(@"aaa");
};

寫法:

有參數(shù)的:
返回值類型 (^block變量名)(參數(shù)列表) = ^(參數(shù)列表){};//建議使用
返回值類型 (^block變量名)(參數(shù)列表) = ^返回值類型(參數(shù)列表){};
//開發(fā)中幾乎沒人把后面的返回值類型寫上

沒有參數(shù)的話:
返回值類型 (^block變量名)() = ^(){};
返回值類型 (^block變量名)() = ^{};//建議使用,括號多余
以上兩種寫法是一樣的

各種例子

int(^sum)(int a, int b) = {
  return a + b;
;

sum(5,10);
-------------------

int (^sumBlock)(int,int);
sumBlock = ^(int v1, int v2){
  return v1 + v2;
};
sumBlock(5,10);

-------------------------
void(^printFuck)(int) = ^(int num){
  for(int i = 0; i < num; i++){
    print("fuck");
  }
};

printBlock(2);

block和typedef的結(jié)合

首先來看函數(shù)指針是怎么搞的:

int sum(int v1, v2) {
  return v1 + v2;
}

int minus(int v1, v2) {
  return v1 - v2;
}

typedef int (*calculate)(int, int);

int main(int argc, const char* argv[]) {
 // int (*sumP)(int, int);
  //sumP = sum;
  calculate sumP = sum;
  NSLog(@"sum = %i", sumP(1,2));
  //int (*minusP)(int, int);
  //minusP = minus;
  calculate minusP = minus;
  NSLog(@"minus = %i", minusP(1,2));
}

再來看看block是怎么搞的:

typedef int (^calculateBlock)(int, int);

int main(int argc, const char* argv[]) {
  //int (^sumBlock)(int, int);
  calculateBlock sumBlock = ^(int a, int b) {
    return a + b;
  };
  NSLog(@"sum = %i", sumBlock(1,2));

  //int (^minusBlock)(int, int);
  calculateBlock minusBlock = ^(int a, int b) {
    return a - b;
  };
  NSLog(@"minus = %i", minusBlock(1,2));
}

Block應用場景

傳遞數(shù)據(jù)兩個方式:代理(代碼分散)、block(代碼集中)

block用于傳遞一段代碼塊?。?!當你傳遞了一個block時,你可以在接收這個block的上下文中任何時候使用這段代碼!

Block注意事項

  1. block中可以訪問外面上下文的變量
  2. block中可以定義和外面同名的變量,若定義了,則會訪問本地定義的變量,而訪問不到外面了(作用域問題)
  3. 默認不可以在block中修改外界的變量值,因為block中的變量和外面的變量并不是同一個變量,若訪問了外面的變量 ,block會將外面的變量拷貝一份到堆內(nèi)存。(通過打印地址可以驗證)
  4. 也正因為這個拷貝問題,當你在外面修改了變量值,是不會修改block已經(jīng)拷貝的值的。也就是說,block只會捕獲其定義時上下文的變量值。
  5. 外界的變量之前加上__block關鍵字,就可以在block內(nèi)部修改值了。且此時會影響外界的值??!

__block關鍵字做了什么?

為什么默認不能改?為什么加了就能改?

默認是值傳遞的。所以默認情況下修改不了外界。
加上__block后變?yōu)閭鬟f地址。


  1. block 默認情況下存儲在棧中,若對block對象進行copy(Block_copy方法),則轉(zhuǎn)移到堆中。若block在棧中,block訪問外界對象,不會對對象進行retain。若block在堆中,訪問外界對象就會進行retain。
  2. 若在block內(nèi)部訪問外界對象,一定要加上__block,只要加上了,就不會對其進行retain了。(消滅了因此而產(chǎn)生的內(nèi)存泄漏問題)。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容