《iOS高級編程》中的Block:概要規範篇

關於我的倉庫

  • 這篇文章是我爲面試準備的iOS基礎知識學習中的一篇
  • 我將準備面試中找到的所有學習資料,寫的Demo,寫的博客都放在了這個倉庫裏iOS-Engineer-Interview
  • 歡迎star👏👏
  • 其中的博客在簡書,CSDN都有發佈
  • 博客中提到的相關的代碼Demo可以在倉庫裏相應的文件夾裏找到

前言

  • 本文主要是對於《高級編程》類似於總結的學習筆記

準備工作

  • 閱讀《Objective-C 高級編程》中的p.79 ~ 91

Blocks概要

  • 一句話概括Blocks的擴充功能:帶有自動變量(局部變量)的匿名函數

疑惑: p.81 buttonId

int buttonID = 0;

void buttonCallback(int event) {

   NSLog(@"button:%d event = %d", buttonID, event);
}

void setButtonCallback(int offset, void (*p)(int)) {

   p(offset);
}

void setButtonCallbacks() {

   for (int i = 0; i < 10; i++) {
       buttonID = i;
       setButtonCallback(0 + i, &buttonCallback);
   }
}

  • 書上沒有給出setButtonCallback函數的具體實現,但估計肯定是這樣的,因爲我們使用函數指針很大一部分就是爲了使用函數回調
  • 可是書上說,這樣寫了會出現問題,我覺得他的意思是說這樣寫會出現buttonID只會是for循環的最後一個,也就是9
  • 可是我實驗下來和正常情況沒有什麼區別,不是很懂

887D7308-7318-4B92-A638-EBFF549147A1

Block語法

與一般C語言函數不同點:

  • 沒有函數名
  • 帶有“^”號【插入記號】

格式

標準格式

ECDEC5C7-C6FF-4F5F-A1B8-DB8BA7F2BB6C

^int (int count){return count + 1;}

省略格式

  • 可以省略返回值類型
  • 省略返回值類型的情況下,return什麼類型返回值就是什麼類型,不寫return的話默認就是void
  • 可以省略參數列表
  • 沒有參數的情況下block可以這麼寫

60F591B8-D410-4FE9-886F-CFC273B52AEB

  • 也可以直接把(void)省略,直接這麼寫

B89A2A1D-FFEB-49F7-867B-721ABAB15A98

  • 所以我們的block省略完可以這麼寫:

40B1C054-38B8-42A4-AD0A-43608AB50B85

block變量

  • block變量類似於函數指針【聯想:我們說block是匿名函數】
  • 對於函數,我們可以使用一個函數指針,將函數的地址賦值給函數指針,在調用函數的時候可以直接通過函數指針調用函數
//ex:C語言函數指針
int func(int count) {
  return count + 1;
}

int (*funcptr)(int) = &func;

//這樣子下面兩個語句代表的含義一樣
int res = func(2);
int res = funcptr(2);
  • 同樣對於block,我們可以使用block變量調用block中的表達式
  • 聲明block變量的語法和函數指針基本一致,只是把*號換成了^號

2E876C3B-C47B-4345-A03C-5794F45A8996

  • block變量和C語言變量完全相同,可以作爲以下用途:
    • 自動變量
    • 函數參數
    • 靜態變量
    • 靜態全局變量
    • 全局變量

截獲自動變量

  • 看一段代碼:
int dmy = 256;
int val = 10;
const char  *fmt = "val = %d\n";
void (^blk)(void) = ^{
  
		printf(fmt, val);
	};
	val = 2;
	fmt = "THESE VALUES WERE CHANGED. val = %d\n";
	blk();
  • 結果爲val = 10,而不是2,也就是說val這個變量被截獲了,截獲時它是10,雖然在塊裏面的代碼在val = 2之後才被執行,但打印的依然是截獲時的10,這就是截獲自動變量
  • 也就是說變量在代碼運行到定義那一塊就被截獲了,執行的時候已經不是原變量了

__block說明符

  • block可以截獲變量,但是不能在塊裏修改變量的值

668D72AD-79AB-47D5-842E-C3CDFCFF8374

  • 此時就是需要使用__block修飾符修飾變量,對需要在block內進行賦值的變量,使用修飾符修飾,保證可以對變量進行賦值
  • 賦值後按序執行,也就是說執行完了以後,變量的值就是塊裏面的新的值

[外鏈圖片轉存失敗(img-tWPYSvQp-1568541047715)(https://tva1.sinaimg.cn/large/006y8mN6ly1g70bvgcjfjj30n009j78u.jpg)]

  • 比如上述代碼,就過就是1而不是0,還是要記住,block的定義和執行是分爲兩塊的,兩者可能會垮文件,相隔十萬八千里
  • 但只有執行完了代碼纔會生效

截獲的自動變量

  • 這一段主要講的東西我認爲其實就是我們捕獲到的東西不能賦值,但是如果只是拿來用的話是沒問題的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章