fb_license

技術標籤

@selector (1) 初使化區塊 (1) 物件 (1) 物件導向 (2) 型別 (4) 封裝 (1) 流程控制 (1) 陣列 (3) 推論型別 (2) 實機測試 (1) 蓋索林(gasolin) (1) 模組 (1) 憑證 (1) 轉型 (1) 羅康鴻 (121) 類別 (1) 變數 (5) Accelerometer (1) ActiveRecord (1) Activity (1) AFNetworking (1) alloc (1) Android (3) Animation (1) App (1) App ID (1) APP上傳 (1) ASP.NET (1) AVAudioPlayer (1) block (1) C# (2) class (1) CLLocationManager (1) CLLocationManagerDelegate (1) CMMotionManager (4) Controller (1) delegate (1) DELETE語法 (1) Device Motion資料 (1) Dialog (1) DropDownList (1) dynamic language (2) Facebook SDK (9) FBRequest (5) FBRequestConnection (2) FMDB (1) Gesture Recognizers (6) GROUP BY (2) Gyro (1) HAVING (1) IBAction (1) IBOutlet (1) id (3) inheritance (1) init (1) Insert (1) instance variable (1) Interface Builder (1) iOS (70) iOS idea (7) iOS Introduction (1) Layout (1) Magnetometer (1) Menu (2) Method (2) MKMapView (1) MKPointAnnotation (1) MS SQL (5) Nil (1) NSArray (1) NSDictionary (1) NSError (1) NSFileManager & .plist (1) NSMutableArray (1) NSMutableDictionary (1) NSNotificationCenter (1) NULL (1) object (2) Objective-C (16) Objective-C idea (1) ORDER BY (1) Parameter (1) property (1) protocol (2) Provisioning (1) Proximate Sensor (1) Q and A (2) R類別 (1) Rails (9) RESTful SOA (9) Ruby (8) Scene (1) SEELECT (1) Segue (2) SEL (1) SELECT語法 (1) Shake (1) Simulator (1) SOA (8) SQL (6) SQL Server (5) SQL函數 (1) SQL彙總函數 SQL (1) SQLite (1) Storyboard (1) Style (1) Swift (1) Table (1) target & action (1) Theme (1) Toast (1) TRUNCATE TABLE語法 (1) UIActionSheet (1) UIActionSheetDelegate (1) UIActivityIndicatorView (1) UIAlertView (1) UIBarButtonItem (1) UIButton (1) UICollectionView (1) UICollectionViewDataSource (1) UIControl (9) UIDatePicker (1) UIImage (1) UIImagePickerController (2) UIImagePickerControllerDelegate (2) UIImageView (1) UILabel (1) UILongPressGestureRecognizer (1) UINavigationController (2) UIPanGestureRecognizer (1) UIPinchGestureRecognizer (1) UIProgressView (1) UIResponder (1) UIRotationGestureRecognizer (1) UISegmentedControl (1) UISlider (1) UIStepper (1) UISwipeGestureRecognizer (1) UISwitch (1) UITabBarController (1) UITableView (1) UITableViewDataSource (1) UITapGestureRecognizer (1) UITextField (1) UITextFieldDelegate (1) UITextView (2) UITextViewDelegate (1) UIToolBar (1) UIView (8) UIWebView (1) UPDATE語法 (1) var (2) VB.NET (7) View (4) WHERE子句 (1) XML (1)

2014/03/18

[Objective-C] 將處理過程分離 - block


idea...



有時我連上網後我會用去amazon找一些書,有時我上網會去看看email,甚至上FB與人聊天,甚至我沒法保證我10天後會用網路作些什麼事,我要如何設計上網功能呢? 才能調性的確保我之後可以作些不一樣的事?!
我是block程式區塊,
你可以透過我自行定義想要進行的操作,
你可以隨時定義你想作的事,
如此你就不用擔心未來上網後,
不能作你現在沒想到的事了。





1. 建立iPad
  • 建立iPad類別
iPad.h
#import <Foundation/Foundation.h> @interface iPad : NSObject @end


2. 宣告上網後執行的block型別 - doBlock_type
  • block其實就是一個函數,只是objective-c用block來表示,當然,功能與應用上加強了非常的多
  • 在iPad.h檔中,使用typedef定義block的型別,如同函數分3部份,依順序分成回傳值、名稱、參數,每一部份皆以小括號來組成,回傳值與參數皆是"(void)",表示不回傳值也不傳入值,而中間的小括號中放入名稱doBlock_type,即是這個block型別的名稱
#import <Foundation/Foundation.h> //定義傳入block型別, //其實block型別定義的就是型別函數的型別, //只是在此一個特別的名字block來表示一個函數的區段, //就好像函數是以程式區段組成的。 //一個block如何函數有3個元素組成, //回傳值,在此為void,不回傳資料, //函數名稱,在此以"(^)"表示,在此因使用typedef定義block的型別, //因此可在"^"之後加上block型別的名稱,即doBlock_type, //最後的小括號"()"表示傳入的參數,代入void表示無傳入值。 typedef void (^doBlock_type)(void); @interface iPad : NSObject @end


3. 宣告接收doBlock_type型別的參數
  • 為了讓iPad在連Wifi網路後,可執行使用者自訂的程式,以進行自已要作的事,我們把connectInternetWithWifi方法修改一下,加上doBlock_type型別的參數,以在連接網路上執行使用者自訂的程式
  • 更改後的方法為connectInternetWithWifiThenDoBlock:
#import <Foundation/Foundation.h> //定義傳入block型別, //其實block型別定義的就是型別函數的型別, //只是在此一個特別的名字block來表示一個函數的區段, //就好像函數是以程式區段組成的。 //一個block如何函數有3個元素組成, //回傳值,在此為void,不回傳資料, //函數名稱,在此以"(^)"表示,在此因使用typedef定義block的型別, //因此可在"^"之後加上block型別的名稱,即doBlock_type, //最後的小括號"()"表示傳入的參數,代入void表示無傳入值。 typedef void (^doBlock_type)(void); @interface iPad : NSObject //定義connectInternetWithWifiThenDoBlock方法, //其中代入doBlock_type型別的block, //接收block的參數名為block_param, //記住,block就是一段程式, //由使用者自行定義此段程式的內容。 -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; @end

4. 實作connectInternetWithWifiThenDoBlock:方法
  • 實作connectInternetWithWifiThenDoBlock:方法很簡單,就是在連接Wifi網路後,呼叫執行參數所代入的block,以執行使用者自訂在block中的程式
  • 呼叫的方法如何呼叫函數一樣,加上小括號"()"代入參數就可以了
  • 因doBlock_type型別的block並無需參數,所以加上小括號就"()"可呼叫執行block了
#import "iPad.h" @implementation iPad -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; { NSLog(@"透過Wifi連上網路…已連線"); //執行block_param參數代入的block, //執行的方法就如同呼叫函數一樣, //加上小括號"()"代入參數即可, //但…其執行的是什麼內容呢?! //這就是block的功用, //讓使用者自行決定要執行的程式, //在此connectInternetWithWifiThenDoBlock方法的任務很簡單, //就是連上wifi網路後, //接著執行block, //以執行使用者後續想要執行的作業。 block_param(); } @end

5. 代入block,以在連網後進行不同的作業
  • 現在使用者想在連接wifi後,想上網去Amazon、或去收email、或去FB聊天都沒問題,只要使用者在block中定義想要作的事就ok了
  • 在傳送connectInternetWithWifiThenDoBlcok:訊息時代入block實體就可在連接wifi後作block中定義的事
  • 產生block實體很簡單,只需使用"^{}"並符合doBlock_type型別所定義的函數格式就ok了,,因無參數也參回傳值,因此直接使用"^{}"就可建立block實體
  • 當然,因為doBlock_type也是一種型別,因此可作為變數的型別使用
  • 在此使用"^{}"建立block實體,其中的程式表示上Amazon買書,並帶入block1變數中,而後在代入connectInternetWithWifiThenDoBlock:訊息中,以在連網後去Amazon買書
  • 當然,也可以另建立個block2,在連網後去收email
  • 而block並不需要先存在變數中,也可以直接代入至訊息中,在此的第3個範例就是如此,直接上建立block實體後代入至connectInternetWithWifiThenDoBlock:訊息中,在連網後至FB聊天
#import "iPad.h" #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { iPad * pad1 = [[iPad alloc] init]; //建立doBlock_type型別的變數block1, //透過"^{}"實際建立block的實體, //在大括號中"{}"即可定義您想要執行的程式, //在此為上Amazon買書去! doBlock_type block1 = ^{ NSLog(@"上Amazon買書去!"); }; //現在透過iPad連wifi上網, //同時在連上網後, //執行block1中的程式, //如此就達到上Amazon買書的需求。 [pad1 connectInternetWithWifiThenDoBlock:block1]; //現在想上網後去收email, //調整block中的內容就ok了! doBlock_type block2 = ^{ NSLog(@"上網去收email!"); }; [pad1 connectInternetWithWifiThenDoBlock:block2]; //當然block也可以透過"^{}"直接建立block實體後代入, //只要符合block的型別doBlock_type, //所定義的回傳值與參數就ok了 [pad1 connectInternetWithWifiThenDoBlock:^{ NSLog(@"上FB找朋友聊天!"); }]; } return 0; }

檔案連結:objective_c_block.zip



帶有參數與回傳值的block:
  • block即然是函數,那當然也會有回傳值和參數
  • 因此我們可以在typedef時,就定義block的格式
  • 在下列範例中定義一個帶有參數與回傳值的block型別,如下:
iPad.h
#import <Foundation/Foundation.h> //宣告一個有回傳值與參數的block型別, //typedef後接的就是型別, //在此使用NSString,用以表示block以執行在執行後的結果字串, //在最後一個小括號中加入BOOL, //表示會帶入一個BOOL參數, //在參數用以代入網路是否開啟成功。 typedef NSString* (^doBlock_type)(BOOL); @interface iPad : NSObject //定義connectInternetWithWifiThenDoBlock方法, //其中代入doBlock_type型別的block -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; @end
iPad.m
#import "iPad.h" @implementation iPad -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; { NSLog(@"透過Wifi連上網路…已連線"); //代入YES,表示網路開啟成功 //並使用resultString變數接收執行結果的字串 NSString * resultString = block_param(YES); NSLog(@"執行完畢:%@", resultString); } @end
main.m
#import <Foundation/Foundation.h> #import "iPad.h" int main(int argc, const char * argv[]) { @autoreleasepool { //使用"^{}"建立doBlock_type型別的block實體, //因doBlock_type定義block需代有一個參數, //因此在^後加上小括號,其中帶入一個BOOL參數, //此參數在此範例表示是否網路已開啟, //而因doBlock_type型別有定義NSString型別的回傳值, //因此,程式中需使用return將資料回傳 doBlock_type block1 = ^(BOOL isInternetOpened){ if(isInternetOpened == YES) { NSLog(@"上FB聊天真開心!"); return @"上FB聊天完畢!"; } else { return @"很傷心,無法上網聊FB..."; } }; iPad * pad1 = [[iPad alloc] init]; [pad1 connectInternetWithWifiThenDoBlock:block1]; } return 0; }

檔案連結:objective_c_block_2.zip

多個參數的block:
  • 當然,block也可以帶入多個參數,如同函數一樣,如下:
#import <Foundation/Foundation.h> //宣告帶有多個參數的block型別, //在最後一個小括號中, //只要定義參數的型別與個數, //每個參數以逗號","隔開即可。 typedef NSString* (^doBlock_type)(BOOL, NSString*, NSInteger);

定義匿名的block型別:
  • block其實是可以不用透過typedef事先定義block的型別的
  • 當然,最大不同的地方是,宣告匿名block的格式,而匿名的意思是這個block型別不需要名字,只有宣告block的格式,如下:
iPad.h
#import <Foundation/Foundation.h> @interface iPad : NSObject //直接在參數的型別上定義block的格式, //特別的是這個匿名block型別沒有名稱, //因此第2個小括號中僅有一個"^"即(^), //在此匿名block的格式, //回傳值為void //(^)沒有block型別沒有名字, //(void)沒有任何參數 -(void) connectInternetWithWifiThenDoBlock: (void(^)(void))block_param; @end

檔案連結:objective_c_block_3.zip

更多block的應用: