iOSの開発プロセスでは、我々はあまりにも多くの場合、予期しない問題が発生しました
NSError(エラーメッセージ)
NSErrorを使用する場合には
使用NSError
ベンへの影響の崩壊を引き起こすことはありません、エラーの原因が呼び出し元に戻るプログラム、及びプログラムの正常な動作につながることができますフォームを
NSErrorコンテンツが含まれています
@interface NSError:NSObjectの<NSCopying、NSSecureCoding> { @private _reserved無効*; NSIntegerの_CODE。 * _domainをNSStringの。 NSDictionaryの* _userInfo。 }
NSError _code
(エラーコード、タイプNSInteger
):特定の範囲内で発生するエラーを示す固有のエラーコード。あなたが定義する列挙型を使用できるようにコレクションのシリーズは、間違っている可能性があります。NSError *_domain
(誤差範囲のタイプNSString
):誤差範囲、通常、特定のグローバル変数とが定義されています。NSError *_userInfo
(ユーザ情報、タイプNSDictionary
):いくつかの「ローカライズされた記述」が含まれ、そしておそらく、このエラーが発生した別のエラーにつながるエラーに関する追加情報、。ユーザー情報は、エラー・チェーンとして記述することができます
どちらの場合もNSErrorの使用
APIメソッドの実装または設計するとき、我々はNSError
二つの方法で状況を使用します。転送プロトコルと「出力パラメータ」を呼び出し元に戻ります
1.送信する信託契約によるエラー
- (void)connection:(NSURLConnection *)connection withError:(NSError *)error;
あなたは、情報転送代理店契約により、エラーを報告することができます
2.「出力パラメータ」呼び出し元に返さ
- (BOOL)doSomething:(NSError **)error;
(オブジェクト・エラーへのポインタである)ポインタへのポインタとして誤った情報
NSException @throw(例外がスローされます)
@throwケースを使用して
APPは、例外がスローされたプログラムの問題を終了するように動作する問題やニーズが発生し、実行時には、それを使用することができます@throw
に
問題が@throwを使用して発生する可能性があります
例外がスローされた場合には例外が、例えば、スローされます。リソースの異常放出の背後にあるコードの実装を達成するためにスローは、オブジェクトの終了時に解放されないように、実行されません。あなたは、「セキュリティ異常」のコードを生成したい場合は、コンパイラフラグを設定することができる-fobjc-arc-exceptions
達成します。例外がスローされたときしかし、我々はいくつかの余分なコードを追加するようにしてコードを実行しません。
使用していないARCは、例外を達成することは困難であるとき場合にリリースされるメモリにスローされます。
NSError *エラー= nilを; BOOL成功= [自己のdoSomething:&エラー]; (エラー&&成功){もし @throw [NSException ...]。 } [成功リリース]。
上記の例外の実現に従った処理がスローされると、成功は解放する機会がありました。だから、例外がスローされる前に、しかし、解放するリソースは例がたくさんあった際に、その操作がより複雑になっている缶成功がリリースされる上記の問題を解決するために。
開発プロセスは、インスタンスメソッドと呼ばれる抽象基本クラスを使用して行うことができる時に例外がスローされます。この方法ではない場合は、基本クラスは、override
例示的な方法がオーバーライドされて保証することができます例外をスローするように設定されています。
@try @catch @finally(異常キャプチャ)
@try @catch @finallyケースを使用して
@try @catch @finally個人的な感情は、NSException拡張バージョン@throwです。前者は、異常出力に関連する異常を捕捉するために実施されてもよいし、特定操作が@finally出力に関連する例外の後に行われます。後者はNSExpectionがスローされた特定の一種であり、前者は完璧な流線手続きではありません。
実装は、基本クラスで提供され@throw場合基底クラスインスタンスメソッドをオーバーライドする必要があり、この方法は、捕捉例外@try @catch @finallyに使用されます。たとえば:NSArrayの、NSDictionaryの初期変数リテラルが値を取得するためのデータを防ぐAPPクラッシュnilに返されるかどうかを判断する必要があります。
問題と解決策
使用するときは@try @catch @finally
、時間を、そこに2つのケースがあるMRC
とARC
。
MRC
(IOS 5の前に)環境、上記のコードは次のように表示することができます。
工ass *工ass = nilを; @try { 工ass = [[工ass ALLOC] INIT]。 【工ass doSomeThingsThatMayThrow]。 } @catch(){ のNSLog(...)。 } @finally { [工assリリース]。 }
ARC環境では、上記のコードは次のように示されています。
工ass *工ass = nilを; @try { 工ass = [[工ass ALLOC] INIT]。 【工ass doSomeThingsThatMayThrow]。 } @catch(...){ のNSLog(...)。 } @finally { }
メモリの解放のために達成することができMRCの場合に見られるように、システムは、だから、それを修正するために?ARCの場合のメモリの解放を達成しますか?
答えは:ARCは自動的に処理しません、あなたがしたい場合は、自動プロセスは、それがクリーンアップされたときに明らかにスロー目的を達成することができる多くのコードを追加する必要があるためです。コードの追加は、実行時のパフォーマンスに影響する場合しかし、それは通常の操作でケースになります。
あなたは現在の実装で有効にした場合-fobjc-arc-exception
に実装することができ、モデルの@try @catch @finally
オブジェクトの管理の放出を達成するために例外的な状況でのメモリのために解放されません
最終的にはC ++のソースコード@キャッチ@てみてください@
:ビュー例外がスローされたソース
のビルドプロジェクトをmain.m
次のコードファイルを達成するために:
工ass *工ass = nilを; @try { 工ass = [[工ass ALLOC] INIT]。 【工ass doSomeThingsThatMayThrow]。 } @catch(...){ のNSLog(...)。 } @finally { }
端末を開きmain.m
、次のフォルダパス端末文の実装
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
ファイルが生成されmain.cpp
たファイルは、ビューファイルを開くことができます@try @catch @fianlly
NSExpection属性内容
__ __attribute((__ objc_exception__)) #ifndefの_REWRITER_typedef_NSException の#define _REWRITER_typedef_NSException のtypedef構造体objc_object NSException; typedefは構造体{} _objc_exc_NSException; #endifの 構造体NSException_IMPL { 構造体NSObject_IMPL NSObject_IVARS; //インスタンス変数 *名のNSString; //例外名 NSStringの*理由; /原因/例外 NSDictionaryの*ユーザー情報; //例外は、より多くの情報の使用を実証 ID予約済み; // }。
NSError属性内容
_REWRITER_typedef_NSError #ifndefの に#define _REWRITER_typedef_NSError のtypedef構造体objc_object NSError; typedefは構造体{} _objc_exc_NSError; #endifの 構造体NSError_IMPL { 構造体NSObject_IMPL NSObject_IVARS; //インスタンス変数 メソッドの//例コール;ボイド*は_reserved NSIntegerの_CODE; //エラーエラーコード NSStringの* _domain; //エラー誤差範囲 NSDictionaryの* _userInfo; //エラー特定情報は、エラーを説明しました }。
以下でmain.m
使用Clang
解決するための@try @catch @finally
C ++環境で解決
パラメータなしの下で
INTメイン(){ @try { } @catch(NSException *例外){ } @finally { } }
クランは、ソースコードを解析した後に次のように
メインINT(){ = 0 {揮発性_rethrowのID、 トライ{ 試み{ //例外トラップ }キャッチ(_objc_exc_NSException _exception *){ NSException例外* =(NSException *)_例外; //キャッチ例外とスロー } } キャッチ(ID E){ _rethrow = E; } { 構造体_FIN {_FIN(ID RETH):再スロー(RETH){} 〜_FIN(){IF(再スロー)objc_exception_throw(再スロー);} ID再スロー; } _fin_force_rethow(_rethrow)。 コンテンツ例外が//スローされた後、最終的に実行 } } } 静的構造体IMAGE_INFO {符号なしのバージョン。符号なしフラグ。} _OBJC_IMAGE_INFO = {0,2}。
状況のパラメータの場合
int型のmain(){ NSDictionaryの* DIC = @ {@ "名": "梁"、@ "姓" @: "BAI" @、 "夢" @:@、 "bussinessmanされるように" "仕事" @: @"それ"}; NSStringの* salaryLiterals = nilを; NSStringの* salaryAtIndex = nilを; @try { salaryAtIndex = [DIC objectForKey:@ "給料"]。 salaryLiterals = DIC [@ "給与"]; } @catch(NSException *例外){ のNSLog(@ "エラー名が%である@、理由:%@、ユーザー情報:%@"、exception.name、exception.reason、exception.userInfo)。 } @finally { } }
クランは、ソースコードを解析した後に次のように
INTメイン(){ NSDictionaryの* DIC =((NSDictionaryの*(*)(クラス、SEL、CONSTのObjectType *、CONST ID *、NSUInteger))(ボイド*)objc_msgSend)(objc_getClass( "NSDictionaryの")、 sel_registerName(「dictionaryWithObjects :forKeys:数: ")、 (定数ID *)__ NSContainer_literal(4U、(NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_1、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_3、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_5、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_7).arr、 (定数ID *)__ NSContainer_literal(4U、(NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_0、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_2、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_4、 (NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_6).arr、4U)。 NSStringの*給与= __null。 {ID揮発性_rethrow = 0。//使用揮発性修饰的_rethrow记录异常的局部变量 してみてください{ 試み{ 給与=((ID _Nullable(*)(ID、SEL、ます。KeyType))(void *型)objc_msgSend)((ID)DIC、sel_registerName(「objectForKeyedSubscript: 「)、 (ID)(NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_8)。 } キャッチ(_objc_exc_NSException * _exception){ NSException *例外=(NSException *)_例外。 NSLog((NSStringの*)&__ NSConstantStringImpl__var_folders_tv_4c43vcqx24vcxx6d51n4ntc00000gn_T_main_753a25_mi_9、 ((NSExceptionName(*)(ID、SEL))(void *型)objc_msgSend)((ID)例外、sel_registerName( "名前"))、 ((NSString の* _Nullable(*)(ID 、SEL))(void *型)objc_msgSend)((ID)例外、sel_registerName( "理由"))、 ((NSDictionary の* _Nullable(*)(ID、SEL))(void *型)objc_msgSend)((ID)の例外、 sel_registerName( "のUserInfo"))); } } キャッチ(ID電子){ _rethrow = E。 } { 構造体_FIN { _FIN(識別RETH): IF(再スロー)objc_exception_throw(再スロー)。 } IDの再スロー。 } _fin_force_rethow(_rethrow)。 給与= __null。 } } } 静的構造体IMAGE_INFO {符号なしのバージョン。符号なしフラグ。} _OBJC_IMAGE_INFO = {0,2}。
要約:
(1)ベン・崩壊の出会いの問題や間違った問題、優先利用
NSError
ベンの崩壊とエラーをカプセル化するために、そして、NSLog
それを印刷(2)
@try @catch @finally
プロセスの非常に便利な使用が、MRC
変数はローカル変数のメモリの問題のリリースを欠場する可能性が高いとあればARC
、問題がスローされた場合、ローカル変数は自動的にオープン(解放されていない-fobjc-arc-expections
モードが解除されますが、コードの導入)のパフォーマンスに影響を与えます