1. 程式人生 > >IOS中 Block簡介與用法(一)

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;
就是行為主體)。記得行為主體裡最後要加“;”,因為是敘述,而整個{}最後也要加“;”,因為Block是物件實體。用法如下:
    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 有什麼關係呢?具體又是如何工作的呢?想必大多數熱衷於應

iOStableview 兩級cell的展開收回

        在我們的很多專案實現過程中,都需要資料的展開與收回,就像騰訊QQ中的聯絡人,也是一個cell的收回操作。上一篇博文講述瞭如何展開一個兩級的資料來源,那麼我們就接著改例城講解一下資料的展開與收回。在這裡主要是為了講解兩個知識點,在tableview中插入資料與

JVMclass文件探索解析

範圍 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的簡單的增刪改查

JavaSocket的用法 普通Socket的簡單用法

Java中網路通訊是通過Socket實現的,Socket分為ServerSocket和Socket兩大類,ServerSocket用於服務端,可以通過accept方法監聽請求,監聽到請求後返回Socket,Socket用於具體完成資料傳輸,客戶端直接使用Socket發起請求並

ArcGIS API for JavaScript 實戰解析簡介快速上手

在這篇文章之前廢話幾句。 自從過完十一假期,每天都在奔波和加班中度過,直到今天才真正能夠休息。隱約記得去年是同樣的情形,但並不是相同的事由,希望明年十月對我好一點。 從二月到十月的八個月裡,我幾乎每天都堅持學習,從程式語言、軟體開發到機器學習、WebGIS,還有

Android Studioso庫的建立使用、jar庫jar呼叫so庫的建立使用

工程下載https://download.csdn.net/download/cnicfhnui/10422621一、Android Studio 建立so庫,呼叫so庫第一步先下載NDK開發包,下載地址:https://developer.android.google.cn