IOS中 Block簡介與用法(一)
Block簡介:
Block的實際行為和Function很像,最大的差別是在可以存取同一個Scope的變數值。Block實體形式如下:
^(傳入引數列){行為主體};
Block實體開頭是“^”,接著是由小括號所包起來的引數列(比如 int a, int b, int c),行為主體由大括號包起來,專有名字叫做block literal。行為主體可以用return回傳值,型別會被compiler自動辨別。如果沒有引數列要寫成: ^(void)。
例如下面的一個例子:
^(int a){return a*a;};
這是代表Block會回傳輸入值的平方值(int a 就是引數列, return a*a;
int result = ^(int a){return a*a;}(5);
NSLog(@"%d", result);
很奇怪吧?後面的小括號裡面的5會被當成a的輸入值,然後經由Block輸出 5*5 = 25指定給result這個變數。
有沒有簡單一點的方法嗯?不然每次都寫這麼長?有。接下來介紹一個叫做Block Pointer的東西來簡化我們的寫法。
Block Pointer是這樣定義的:
回傳值(^名字)(引數列);
比如下面的例子:
是不是變的簡單了?//宣告一個square的Block Pointer,其所指向的Block有一個int輸入和int輸出 int (^square)(int); //將Block實體指定給square square = ^(int a){ return a*a ; }; //呼叫方法,感覺是是不是很像function的用法? int result = square(5); NSLog(@"%d", result);
也可以吧Block Pointer當成引數傳遞給一個function,比如:
void myFunction(int (^mySquare)(int)); //function的定義,將Block作為引數
int (^mySquare)(int) = ^(int a){return a*a;}; //定義一個mySquare的Block pointer變數
myFunction(mySquare); //把mySquare作為myFunction的引數
上面的三行程式碼其實等價於下面這行程式碼:
myFunction( ^int(int a){return a*a;} );
當其作為Object-C method的傳入值的話,需要把型別寫在變數前面,然後加上小括號。比如下面這種寫法:
-(void)objcMethod:(int(^)(int))square; //square引數的型別是int(^)(int)
存取變數
1、可以讀取和Block pointer同一個Scope的變數值:
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;};
//block裡面可以讀取同一型別的outA的值
int result = myPtr(3); // result is 11
NSLog(@"result=%d", result);
}
下面來看一段很有意思的程式碼:
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;}; //block裡面可以讀取同一型別的outA的值
outA = 5; //在呼叫myPtr之前改變outA的值
int result = myPtr(3); // result的值仍然是11,並不是8
NSLog(@"result=%d", result);
}
為什麼result 的值仍然是11?而不是8呢?事實上,myPtr在其主體中用到的outA這個變數值的時候做了一個copy的動作,把outA的值copy下來。所以,之後outA即使換成了新的值,對於myPtr裡面copy的值是沒有影響的。
需要注意的是,這裡copy的值是變數的值,如果它是一個記憶體的位置(地址),換句話說,就是這個變數是個指標的話,
它的值是可以在block裡被改變的。如下例子:
{
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@"test array :%@", mutableArray);
}
原本mutableArray的值是{@"one",@"two",@"three"},在block裡面被更改mutableArray後,就變成{@"one", @"two"}了。
2、直接存取static型別的變數
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){return outA + a;};
outA = 5;
int result = myPtr(3); //result的值是8,因為outA是static型別的變數
NSLog(@"result=%d", result);
}
甚至可以直接在block裡面修改outA的值,例如下面的寫法:
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
int result = myPtr(3); //result的值是8,因為outA是static型別的變數
NSLog(@"result=%d", result);
}
3、Block Variable型別的變數
在某個變數前面如果加上修飾字“__block”的話(注意,block前面有兩個下劃線),這個變數就稱作block variable。
那麼在block裡面就可以任意修改此變數的值,如下程式碼:
{
__block int num = 5;
int (^myPtr)(int) = ^(int a){return num++;};
int (^myPtr2)(int) = ^(int a){return num++;};
int result = myPtr(0); //result的值為5,num的值為6
result = myPtr2(0); //result的值為6,num的值為7
NSLog(@"result=%d", result);
}
因為myPtr和myPtr2都有用到num這個block variable,最終num的值為7. 未完待續。。
相關推薦
IOS中 Block簡介與用法(一)
Block簡介: Block的實際行為和Function很像,最大的差別是在可以存取同一個Scope的變數值。Block實體形式如下: ^(傳入引數列){行為主體}; Block實體開頭是“^”,接著是由小括號所包起來的引數列(比如 int a, int b, int c)
Redis Sentinel機制與用法(一)
clear monitor 拒絕 coff failure abstract trac 用法 XML from:https://my.oschina.net/dyyweb/blog/513680 摘要: Redis Sentinel機制與用法(一) Sentin
Docker簡介與安裝(一)
TP width Go src apache container 資源利用率 代碼托管 docker Docker簡介 Docker 是 Docker.Inc 公司開源的一個基於 LXC技術之上構建的Container容器引擎, 源代碼托管在 GitHub 上, 基於Go
核心除錯神器SystemTap — 簡介與使用(一)
a linux trace/probe tool. 簡介 SystemTap是我目前所知的最強大的核心除錯工具,有些傢伙甚至說它無所不能:) (1) 發展歷程 Debuted in 2005 in Red Hat Enterprise Linux 4 Update
Spring Security原理學習--簡介與示例(一)
一、簡介 Spring Security 提供了基於javaEE的企業應有個你軟體全面的安全服務。這裡特別強調支援使用SPring框架構件的專案,Spring框架是企業軟體開發javaEE方案的領導者。如果你還沒有使用Spring來開發企業應用程式,我們熱忱的鼓
block的高階用法(一) -- block傳值
我們先從簡單的入手,先講下block的傳值,後面會有更精彩的。 在講傳值之前我們先複習下block的基礎知識: - (void)viewDidLoad { [super viewDidLoa
Git&GitHub簡介與入手(一)
顯示 更新 分享 out 控制 取消 b- src 信息保存 一、Git版本控制 1、集中式版本控制工具:SVN(版本控制集中在服務器端,會有單點故障風險); 2、分布式版本控制工具:Git; 3、Git簡史 Talk is cheap, show me the cod
認證鑑權與API許可權控制在微服務架構中的設計與實現(一)
引言: 本文系《認證鑑權與API許可權控制在微服務架構中的設計與實現》系列的第一篇,本系列預計四篇文章講解微服務下的認證鑑權與API許可權控制的實現。 1. 背景 最近在做許可權相關服務的開發,在系統微服務化後,原有的單體應用是基於Session的安全許可權方式,不能滿足現有的微服務架構的認證
遊戲中的數學與物理(一)
(看了《遊戲開發的數學與物理》,感覺很不錯,記下點東西。 這是本“圖靈程式叢書”,對於這個系列的書,我一直是蠻喜歡的,感覺書的內容、排版等,都讓人看著很舒服。) 1.1讓物體沿水平方向運動 瞭解勻速直線運動(最簡單的運動),若左邊為x,速度為v,則:x+=v,v=
SQL2005中的事務與鎖定(一)
------------------------------------------------------------------------ -- Author : HappyFlyStone -- Date: 2009-09-24 21:36:30 -- Versi
Android入門——Fragment詳解之基本概念與用法(一)
引言 Android在3.0中引入了Fragments的概念,其目的是用在大螢幕裝置上–例如平板電腦上,支援更加動態和靈活的UI設計。平板電腦的螢幕要比手機的大得多,有更多的空間來放更多的UI元件,並且這些元件之間會產生更多的互動。Fragment允許這樣的一
淺析鴻蒙中的 Gn 與 Ninja(一)
目錄: Ninja簡介 make 的 3 個特性 舉例說明Ninja 的用法 如何向構建工具 Ninja 描述構建圖 後記 下載Ninja學習手冊及原始碼 鴻蒙系統的編譯構建是基於 Gn 和 Ninja 完成的,那麼 Gn 和 Ninjia 有什麼關係呢?具體又是如何工作的呢?想必大多數熱衷於應
iOS中tableview 兩級cell的展開與收回(一)
在我們的很多專案實現過程中,都需要資料的展開與收回,就像騰訊QQ中的聯絡人,也是一個cell的收回操作。上一篇博文講述瞭如何展開一個兩級的資料來源,那麼我們就接著改例城講解一下資料的展開與收回。在這裡主要是為了講解兩個知識點,在tableview中插入資料與
JVM中class文件探索與解析(一)
範圍 protected test except itl 指向 strac 相關 父類索引 一直想成為一名優秀的架構師的我,轉眼已經工作快兩年了,對於java內核了解甚少,閑來時間,看看JVM,吧自己的一些研究寫下來供大家參考,有不對的地方請指正。 廢話不多說,一起來看看J
golang 中io包用法(一)
不同的 下一個 同時 顯示 cte () ews 執行 忽略 本文轉自Golove博客:http://www.cnblogs.com/golove/p/3276678.html io 包為I/O原語提供了基礎的接口.它主要包裝了這些原語的已有實現,如 os 包中的
django之ORM介紹與基本用法(一)
一、ORM介紹 1.什麼是ORM ORM 全拼Object-Relation Mapping. 中文意為 物件-關係對映. 在MVC/MVT設計模式中的Model模組中都包括ORM 2.ORM優勢 (1)只需要面
MySQL中的關鍵字用法(一)
MySQL中關鍵字的用法(一) Insert:增加 insert into * values() insert into user values(‘11’,‘諸葛亮’,‘1011’); 不多解釋,向表中新增一條語句,不清楚的去看MySQL的簡單的增刪改查
Java中Socket的用法(一) 普通Socket的簡單用法
Java中網路通訊是通過Socket實現的,Socket分為ServerSocket和Socket兩大類,ServerSocket用於服務端,可以通過accept方法監聽請求,監聽到請求後返回Socket,Socket用於具體完成資料傳輸,客戶端直接使用Socket發起請求並
ArcGIS API for JavaScript 實戰與解析(一):簡介與快速上手
在這篇文章之前廢話幾句。 自從過完十一假期,每天都在奔波和加班中度過,直到今天才真正能夠休息。隱約記得去年是同樣的情形,但並不是相同的事由,希望明年十月對我好一點。 從二月到十月的八個月裡,我幾乎每天都堅持學習,從程式語言、軟體開發到機器學習、WebGIS,還有
Android Studio中so庫的建立與使用、jar庫(jar呼叫so庫)的建立與使用(一)
工程下載https://download.csdn.net/download/cnicfhnui/10422621一、Android Studio 建立so庫,呼叫so庫第一步先下載NDK開發包,下載地址:https://developer.android.google.cn