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/20

[Objective-C] 哪裡出了問題? 讓我NSError來告訴您 - NSError


idea...



wifi網路打不開?!我要如何處理這個錯誤呢,讓使用者知道網路目前不通,而不是簡單的說wifi不通? 甚至是當機呢?!
我是NSError錯誤,
我可以幫您表示現在發生了什麼錯誤,
只要將您的錯誤資訊提供給我保存就可以了,
如此您就可以後續依照保存在NSError中的錯誤資訊,
提示使用者現發生什麼事了。





1. 建立iPad
  • 建立iPad類別
  • 加入isAirPlaneModeOn屬性與setAirPlaneModeOn:方法,以提供開啟關閉飛航模式的功能
  • 加入hasSignal方法,取得目前有訊號
iPad.h
#import <Foundation/Foundation.h> @interface iPad : NSObject //取得飛航模式狀態 @property (readonly) BOOL isAirPlaneModeOn; //開啟與關閉飛航模式 -(void) setAirPlaneModeOn:(BOOL) yesno; //手機是否有訊號 -(BOOL) hasSignal; @end
iPad.m
#import "iPad.h" @implementation iPad //取得飛航模式狀態 @synthesize isAirPlaneModeOn = _isAirPlaneModeOn; //開啟與關閉飛航模式 -(void) setAirPlaneModeOn:(BOOL) yesno { _isAirPlaneModeOn = yesno; } //手機是否有訊號 -(BOOL) hasSignal { //以arc4random_uniform()產生0或1,以表示是否有訊號, //0表示沒有, //1表示有 return (BOOL)arc4random_uniform(2); } @end


2. 為連結wifi的方法加上error參數
  • 於iPad.h中宣告connectInternetWithWifi:(NSError**)errorPtr方法,其中的errorPtr參數即是一個NSError的指標的指標參數,用以指向error物件,以透過errorPtr參數將error物件代出給使用者
  • 於iPad.m中,即可判斷是否有訊號,或是否因為飛航模式而無法連結wifi網路,若是的話則建立NSError物件,在透過errorPtr參數指向此error物件,以傳回給使用者,如下:
iPad.h
#import <Foundation/Foundation.h> @interface iPad : NSObject //略過一些程式 //加入NSError參數, //目的在連結wifi網路時, //若無法連絡, //則傳回NSError物件, //以透過NSError物件了解為何會無法連網。 //注意,在此的errorPtr參數是一個NSError型別的指標的指標, //用意是我們將帶入一個指標的指標變數, //以指向這個NSError物件。 -(void) connectInternetWithWifi:(NSError**) errorPtr; @end
iPad.m
#import "iPad.h" @implementation iPad //略過一些程式 -(void) connectInternetWithWifi:(NSError**) errorPtr; { //飛航模式已開啟 if(_isAirPlaneModeOn == YES) { //建立NSRrror物件, //其中有3個自訂的資訊可代入, //Domain => 表示error的範圍,在此代入WifiOperation, //表示是操作wifi時所產生的錯誤 //code => 表示error的代碼,在此以1表示飛航模式已開啟 //userInfo => 以NSDictionary表示其他資訊, //在此代入一個message資訊, //讓使用者了解發生了什麼錯誤 *errorPtr = [[NSError alloc]initWithDomain:@"WifiOperation" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @"飛航模式已開啟", @"message", nil]]; return; } //手機沒訊號 if([self hasSignal] == 0) { //此code為2,表示手機沒訊號 //message資訊則代入"手機沒訊號"字樣 *errorPtr = [[NSError alloc]initWithDomain:@"WifiOperation" code:2 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @"手機沒訊號", @"message", nil]]; return; } NSLog(@"wifi網路連線中...已連線!"); } @end


3. 實際連結Wifi測試
  • 此時,當iPad連線wifi網路時,則可能因為無訊息,或是飛航模式的開啟,導致無法連結wifi網路
  • 但因為透過NSError的關係,此時若發生錯誤,則可查看發生了什麼錯誤,而後在回報給使用者,如此就會很清楚到底是何原因無法連上wifi了
#import "iPad.h" #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { iPad * pad1 = [[iPad alloc] init]; NSError * error; //連線時,有可能因為沒訊號而產生error [pad1 connectInternetWithWifi:&error]; if(error != nil) NSLog(@"%@", [[error userInfo] objectForKey:@"message"]); //刻意開啟飛航模式 //當然就一定連不上wifi, //直接發生錯誤 [pad1 setAirPlaneModeOn:YES]; [pad1 connectInternetWithWifi:&error]; if(error != nil) NSLog(@"%@", [[error userInfo] objectForKey:@"message"]); } return 0; }


檔案連結:objective_c_nserror.zip



block與NSError:
  • 在objective-C與iOS程式設計中,NSError時常會與block搭配使用,block讓使用者可自行定義後續的工作,同時block也接收NSError物件,以判斷是否有錯誤,以決定是否要繼續後續的工作
  • 以連結wifi網路為例,透過block可讓使用者在連結wifi後做自已想作的事,當然若block中又接收NSError,則可透過NSError的判斷,決定是否要進行後續的作業,如下:
iPad.h
#import <Foundation/Foundation.h> //定義傳入block型別, //其中帶有NSError參數 typedef void (^doBlock_type)(NSError**); @interface iPad : NSObject //取得飛航模式狀態 @property (readonly) BOOL isAirPlaneModeOn; //開啟與關閉飛航模式 -(void) setAirPlaneModeOn:(BOOL) yesno; //手機是否有訊號 -(BOOL) hasSignal; //定義connectInternetWithWifiThenDoBlock方法, //其中代入doBlock_type型別的block -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; @end
iPad.m
#import "iPad.h" @implementation iPad //取得飛航模式狀態 @synthesize isAirPlaneModeOn = _isAirPlaneModeOn; //開啟與關閉飛航模式 -(void) setAirPlaneModeOn:(BOOL) yesno { _isAirPlaneModeOn = yesno; } //手機是否有訊號 -(BOOL) hasSignal { //以arc4random_uniform()產生0或1,以表示是否有訊號, //0表示沒有, //1表示有 return (BOOL)arc4random_uniform(2); } -(void) connectInternetWithWifiThenDoBlock: (doBlock_type)block_param; { NSError * errorPtr; //飛航模式已開啟 if(_isAirPlaneModeOn == YES) { //建立NSRrror物件, //其中有3個自訂的資訊可代入, //Domain => 表示error的範圍,在此代入WifiOperation, //表示是操作wifi時所產生的錯誤 //code => 表示error的代碼,在此以1表示飛航模式已開啟 //userInfo => 以NSDictionary表示其他資訊, //在此代入一個message資訊, //讓使用者了解發生了什麼錯誤 errorPtr = [[NSError alloc]initWithDomain:@"WifiOperation" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @"飛航模式已開啟", @"message", nil]]; block_param(&errorPtr); return; } //手機沒訊號 if([self hasSignal] == 0) { //此code為2,表示手機沒訊號 //message資訊則代入"手機沒訊號"字樣 errorPtr = [[NSError alloc]initWithDomain:@"WifiOperation" code:2 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @"手機沒訊號", @"message", nil]]; block_param(&errorPtr); return; } NSLog(@"wifi網路連線中...已連線!"); block_param(nil); } @end
main.m
#import "iPad.h" #import >Foundation/Foundation.h< int main(int argc, const char * argv[]) { @autoreleasepool { iPad * pad1 = [[iPad alloc] init]; //當然block也可以透過"^{}"直接建立block實體後代入, //只要符合block的型別doBlock_type, //所定義的回傳值與參數就ok了 [pad1 connectInternetWithWifiThenDoBlock:^(NSError ** errorPtr){ if(errorPtr != nil){ //NSLog(@"%@", [[errorPtr userInfo] objectForKey:@"message"]); } else { NSLog(@"上FB找朋友聊天!"); } }]; } return 0; }

檔案連結:objective_c_nserror_2.zip


那Objective-C是否也有try/catch呢?:
  • 當然,objective-c也有所謂的try/catch,當在整個objective-c與ios的設計上,皆習慣使用NSError來處理錯誤
  • Apple建議try/catch是給程式設計人員使用的,而非使用您套件的使用者使用的
  • 其try/catch語法如下:
@try { } @catch { } @finally { }


更多NSError的資訊: