0

How do I define a method that returns an error as well as a value?

For instance, when I call the managedObjectContext save method, the method returns a boolean, along with an error:

if(![context save:&error]) {
    NSLog(@"%@", error);
}

Would you be able to give me a straight-forward example of the method definition behind this?

Edit/Update: In the same regard, how would it be possible to pass back multiple errors. I'm doing something wrong below (I probably don't understand the concept yet), which doesn't work:

NSArray *errors = nil;
[self throwMultipleErrors:&errors];
for(id error in errors) {
    NSLog(@"Muliple error: %@", error);
}...

-(BOOL)throwMultipleErrors:(NSMutableArray **) errors {
    [*errors addObject:@"First Error"];
    [*errors addObject:@"Second Error"];
    [*errors addObject:@"Third Error"];

    return YES;
}
4

3 に答える 3

4

あなたの例では、メソッドの署名は次のとおりです。

- (BOOL)save:(NSError **)error;

これにより、呼び出し元は をポインター (ポインターへのポインター、および)NSErrorではなくアドレスとして渡すことができ、メソッドはそれを別のスコープから割り当てることができます。メソッドが false を返す場合、呼び出し元は、例に示すようにエラー変数の内容を確認できます。**&

&変数と(NSError **)署名の前で使用する方法の詳細については、この質問を参照してください。

一部のメソッド パラメータの前に `&` (アンパサンド) があるのはなぜですか?

実装例:

    - (BOOL)save:(NSError **)error
    {
       NSAssert(error != nil, @"Passed NSError must be nil!");
       // Attempt to do a save
       if (saveDidFail) {
             NSDictionary *userInfo = [NSDictionary dictionaryWithObjectAndKeys:@"Save Failed", kCustomErrorKey, nil];
             *error = [NSError errorWithDomain:@"domain" code:999 userInfo:userInfo];
             return NO;
       } 
       return YES;
    }
于 2013-10-06T21:47:41.467 に答える
3

あなたの例を使用すると、メソッドの署名は次のようになります。

-(BOOL)save:(NSError**)error;

ここで、ダブル ポインターを使用する場合は、プログラミングで防御する必要があります。まず、 の値がでerrorはないことを確認する必要があります。既存のオブジェクトに対して賢明なメモリ管理を行う方法がわからないため、これを行う必要があります。例えば:nil*errornil

NSError *error = nil;
[self save:&error];

正しいでしょう。しかし

NSError *error = [[NSError alloc] init];
[self save:&error];

あなたのsave:方法errorretained_ autoreleasedもしそうならreleaseautoreleasedあなたのアプリは最終的にクラッシュします。逆に、そうしないreleaseretainedメモリリークが発生します。コードがチェックインされる前に問題が迅速に処理されるように、アサートでこれをチェックすることをお勧めします。

NSAssert(!error || !*error, @"*error must be nil!");

最後に、設定するときは、 で*errorないことを確認する必要errorがありnilます。メモリ アドレス の値を設定することはできません0x0。チェックせずnilにメソッドに渡すと、設定しようとするとクラッシュします。

if (error)
{
    *error = [NSError ...];
    return NO;
}

配列を返すには、次のようにします。

-(BOOL)throwMultipleErrors:(NSError **) error {

    NSAssert(!error | !*error, @"*error must be nil");

    NSMutableArray *errorList = nil;

    if (error)
        errorList = [NSMutableArray array];


    [errorList addObject:@"First Error"];
    [errorList addObject:@"Second Error"];
    [errorList addObject:@"Third Error"];

    if (error && [errorList count] > 0)
    {
        *error = [NSError errorWithDomain:@"Some error"
                                     code:0
                                 userInfo:@{@"suberrors" : [NSArray arrayWithArray:errorList]}];
        return NO;
    }

    return YES;
}

戻り配列は不変であり、メソッド内でインスタンス化されることに注意してください。この配列をこのメソッドの外部で変更可能にする理由や、配列をその外部でインスタンス化する理由はまったくありません。配列を にカプセル化するNSErrorことで、既存のメソッド チェーンに簡単に適合させることができNSErrorます。

ノート

もちろん、戻り値をチェックするために、実際に[self save:&error];呼び出しをステートメントにスローします。if()ただし、&errorだけではなくを渡すことに注意してくださいerror。これは、それ自体ではなく、へのポインターを渡す必要があるためです。「エラーのアドレス」と読みます。errorerror&error

于 2013-10-06T22:13:03.950 に答える
2

ここでは構文に注意する必要があります。NSError をメソッドに渡すと: + (instancetype)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError * *)error

まだ初期化されていないエラー オブジェクトへのハンドル (ポインターへのポインター) を渡します。呼び出されたメッセージで問題が発生した場合、メッセージは初期化され、エラー オブジェクトが埋められます。エラーを「返す」のではなく、渡されたパラメータに値を入力するだけです。

したがって、値を返し、エラー パラメータも受け取るメッセージを定義する場合は、次のチュートリアルに従ってください: http://www.cimgf.com/2008/04/04/cocoa-tutorial-using-nserror-to-効果絶大/

于 2013-10-06T21:48:30.857 に答える