为什么这里使用"错误:错误"(objective-c)

Gre*_*reg 7 iphone objective-c pass-by-reference nserror ios

为什么这里使用"错误:错误"(objective-c)

NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
Run Code Online (Sandbox Code Playgroud)

不管怎样,Objective-c中的对象是否会被有效地传递?

e.J*_*mes 21

error:is 的参数类型NSError**(即指向对象的指针).这允许对象根据需要moc分配和初始化新NSError对象.这是一种常见的模式,特别是在Cocoa中.

NSError文档给出了动机这种方法的一些提示:

应用程序可以选择创建NSError的子类,以通过覆盖localizedDescription来提供更好的本地化错误字符串.

传入一个NSError**参数允许该方法返回任何NSError有意义的子类.如果您传入NSError*,则必须提供现有NSError对象,并且该方法无法从传入的对象返回其他对象.

要清楚,该方法可能如下所示:

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError**)error {
    ...
    if ((error != NULL) && (some_error_condition)) {
        *error = [[[SomeNSErrorSubclass alloc] init...] autorelease];
        return nil;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这也使调用代码通过简单地传递到忽略错误NULLerror:参数,如下所示:

NSArray *array = [moc executeFetchRequest:request error:NULL];
Run Code Online (Sandbox Code Playgroud)

更新:(回答问题):

参数类型必须NSError**代替以下两个原因NSError*:1.变量作用域规则,以及2. NSError实例是可变的.

原因#1:变量范围规则

我们假设函数声明看起来像这样:

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error;
Run Code Online (Sandbox Code Playgroud)

我们要调用这样的函数:

NSError * error = nil;
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
Run Code Online (Sandbox Code Playgroud)

当您以这种方式传入变量时,函数体将无法修改该变量的(即函数体将无法创建新变量来替换现有变量).例如,以下变量赋值仅存在于函数的局部范围内.调用代码仍会看到error == nil.

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
    ...
    error = [[[NSError alloc] init...] autorelease];             // local only
    error = [[[SomeNSErrorSubclass alloc] init...] autorelease]; // local only
}
Run Code Online (Sandbox Code Playgroud)

原因#2:NSError的实例是不可变的

让我们保持相同的函数声明,但是像这样调用函数:

NSError * error = [[[NSError alloc] init...] autorelease];
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
Run Code Online (Sandbox Code Playgroud)

首先,变量的作用域规则保证error不能nil,所以if (error != nil) { ...条件将永远是真实的,但即使你想,以检查内部特定的错误信息if块,你会倒霉的,因为实例NSError不可变的.这意味着,一旦被创建,就不能修改它们的属性,所以功能将无法更改domainuserInfo那个的NSError,你在调用代码中创建的实例.

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
    ...
    error.domain = ...   // not allowed!
    error.userInfo = ... // not allowed!
}
Run Code Online (Sandbox Code Playgroud)

  • 除非你在ARC或GC,否则你只是泄露了这个错误. (2认同)