why is "error:&error" used here (objective-c)
为什么这里使用“错误:错误”(objective-c)
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
wouldn't an object in objective-c be effectively pass-by-reference anyway?
不管怎样,Objective-c中的对象是否会被有效地传递?
2 个解决方案
#1
21
The argument type for error:
is NSError**
(i.e. a pointer to a pointer to an object). This permits the moc
object to allocate and initialize a new NSError
object as required. It is a common pattern, especially in Cocoa.
错误的参数类型:是NSError **(即指向对象的指针)。这允许moc对象根据需要分配和初始化新的NSError对象。这是一种常见的模式,特别是在Cocoa中。
The NSError documentation gives some indication of the motivation for this approach:
NSError文档给出了这种方法动机的一些指示:
Applications may choose to create subclasses of NSError to provide better localized error strings by overriding localizedDescription.
应用程序可以选择创建NSError的子类,以通过覆盖localizedDescription来提供更好的本地化错误字符串。
Passing in an NSError**
argument allows that method to return any subclass of NSError
that makes sense. If you passed in NSError*
, you would have to supply an existing NSError
object, and there would be no way for the method to return a different object from the one you passed in.
传入NSError **参数允许该方法返回任何有意义的NSError子类。如果传入NSError *,则必须提供现有的NSError对象,并且该方法无法从传入的对象返回其他对象。
To be clear, the method could look something like this:
要清楚,该方法可能如下所示:
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError**)error {
...
if ((error != NULL) && (some_error_condition)) {
*error = [[[SomeNSErrorSubclass alloc] init...] autorelease];
return nil;
}
}
Note that this also allows the calling code to ignore errors by simply passing in NULL
for the error:
parameter, as follows:
请注意,这也允许调用代码通过简单地为error:参数传递NULL来忽略错误,如下所示:
NSArray *array = [moc executeFetchRequest:request error:NULL];
Update: (in response to questions):
更新:(回答问题):
There are two reasons why the argument type has to be NSError**
instead of NSError*
: 1. variable scoping rules, and 2. NSError instances are imutable.
参数类型必须是NSError **而不是NSError *有两个原因:1。变量范围规则,以及2. NSError实例是不可变的。
Reason #1: variable scoping rules
原因#1:变量范围规则
Let's assume that the function declaration were to look like this:
我们假设函数声明看起来像这样:
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error;
And we were to call the function like this:
我们要调用这样的函数:
NSError * error = nil;
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
When you pass in a variable this way, the function body will not be able to modify the value of that variable (i.e. the function body will not be able to create a new variable to replace the existing one). For example, the following variable assignments will exist only in the local scope of the function. The calling code will still see error == nil
.
当您以这种方式传入变量时,函数体将无法修改该变量的值(即函数体将无法创建新变量来替换现有变量)。例如,以下变量赋值仅存在于函数的局部范围内。调用代码仍然会看到错误== nil。
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
...
error = [[[NSError alloc] init...] autorelease]; // local only
error = [[[SomeNSErrorSubclass alloc] init...] autorelease]; // local only
}
Reason #2: instances of NSError are immutable
原因#2:NSError的实例是不可变的
Let's keep the same function declaration, but call the function like this:
让我们保持相同的函数声明,但是调用这样的函数:
NSError * error = [[[NSError alloc] init...] autorelease];
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
First of all, the variable scoping rules guarantee that error
can not be nil
, so the if (error != nil) { ...
condition will always be true, but even if you wanted to check for specific error information inside the if
block, you would be out of luck because instances of NSError
are immutable. This means that once they are created, you cannot modify their properties, so the function would not be able to change the domain
or userInfo
of that NSError
instance that you created in the calling code.
首先,变量作用域规则保证错误不能为零,因此if(error!= nil){...条件将始终为true,但即使您要检查if块内的特定错误信息,你会失败,因为NSError的实例是不可变的。这意味着一旦创建它们,就无法修改它们的属性,因此该函数将无法更改您在调用代码中创建的NSError实例的域或userInfo。
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
...
error.domain = ... // not allowed!
error.userInfo = ... // not allowed!
}
#2
3
It's effectively another return value. The error is not dominant by convention in Cocoa when there is a return value for the operation. When an error is encountered, it may be returned to you by this out parameter.
它实际上是另一种回报价值。当存在操作的返回值时,错误在Cocoa中不是惯例。遇到错误时,可能会通过此out参数返回给您。
In the case of NSError
, it works this way because NSError
is not a mutable type - its fields are set at initialization and never mutated. Therefore, you cannot pass an NSError
as usual and set the error code.
在NSError的情况下,它以这种方式工作,因为NSError不是一个可变类型 - 它的字段在初始化时设置,从不变异。因此,您不能像往常一样传递NSError并设置错误代码。
#1
21
The argument type for error:
is NSError**
(i.e. a pointer to a pointer to an object). This permits the moc
object to allocate and initialize a new NSError
object as required. It is a common pattern, especially in Cocoa.
错误的参数类型:是NSError **(即指向对象的指针)。这允许moc对象根据需要分配和初始化新的NSError对象。这是一种常见的模式,特别是在Cocoa中。
The NSError documentation gives some indication of the motivation for this approach:
NSError文档给出了这种方法动机的一些指示:
Applications may choose to create subclasses of NSError to provide better localized error strings by overriding localizedDescription.
应用程序可以选择创建NSError的子类,以通过覆盖localizedDescription来提供更好的本地化错误字符串。
Passing in an NSError**
argument allows that method to return any subclass of NSError
that makes sense. If you passed in NSError*
, you would have to supply an existing NSError
object, and there would be no way for the method to return a different object from the one you passed in.
传入NSError **参数允许该方法返回任何有意义的NSError子类。如果传入NSError *,则必须提供现有的NSError对象,并且该方法无法从传入的对象返回其他对象。
To be clear, the method could look something like this:
要清楚,该方法可能如下所示:
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError**)error {
...
if ((error != NULL) && (some_error_condition)) {
*error = [[[SomeNSErrorSubclass alloc] init...] autorelease];
return nil;
}
}
Note that this also allows the calling code to ignore errors by simply passing in NULL
for the error:
parameter, as follows:
请注意,这也允许调用代码通过简单地为error:参数传递NULL来忽略错误,如下所示:
NSArray *array = [moc executeFetchRequest:request error:NULL];
Update: (in response to questions):
更新:(回答问题):
There are two reasons why the argument type has to be NSError**
instead of NSError*
: 1. variable scoping rules, and 2. NSError instances are imutable.
参数类型必须是NSError **而不是NSError *有两个原因:1。变量范围规则,以及2. NSError实例是不可变的。
Reason #1: variable scoping rules
原因#1:变量范围规则
Let's assume that the function declaration were to look like this:
我们假设函数声明看起来像这样:
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error;
And we were to call the function like this:
我们要调用这样的函数:
NSError * error = nil;
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
When you pass in a variable this way, the function body will not be able to modify the value of that variable (i.e. the function body will not be able to create a new variable to replace the existing one). For example, the following variable assignments will exist only in the local scope of the function. The calling code will still see error == nil
.
当您以这种方式传入变量时,函数体将无法修改该变量的值(即函数体将无法创建新变量来替换现有变量)。例如,以下变量赋值仅存在于函数的局部范围内。调用代码仍然会看到错误== nil。
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
...
error = [[[NSError alloc] init...] autorelease]; // local only
error = [[[SomeNSErrorSubclass alloc] init...] autorelease]; // local only
}
Reason #2: instances of NSError are immutable
原因#2:NSError的实例是不可变的
Let's keep the same function declaration, but call the function like this:
让我们保持相同的函数声明,但是调用这样的函数:
NSError * error = [[[NSError alloc] init...] autorelease];
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }
First of all, the variable scoping rules guarantee that error
can not be nil
, so the if (error != nil) { ...
condition will always be true, but even if you wanted to check for specific error information inside the if
block, you would be out of luck because instances of NSError
are immutable. This means that once they are created, you cannot modify their properties, so the function would not be able to change the domain
or userInfo
of that NSError
instance that you created in the calling code.
首先,变量作用域规则保证错误不能为零,因此if(error!= nil){...条件将始终为true,但即使您要检查if块内的特定错误信息,你会失败,因为NSError的实例是不可变的。这意味着一旦创建它们,就无法修改它们的属性,因此该函数将无法更改您在调用代码中创建的NSError实例的域或userInfo。
- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
...
error.domain = ... // not allowed!
error.userInfo = ... // not allowed!
}
#2
3
It's effectively another return value. The error is not dominant by convention in Cocoa when there is a return value for the operation. When an error is encountered, it may be returned to you by this out parameter.
它实际上是另一种回报价值。当存在操作的返回值时,错误在Cocoa中不是惯例。遇到错误时,可能会通过此out参数返回给您。
In the case of NSError
, it works this way because NSError
is not a mutable type - its fields are set at initialization and never mutated. Therefore, you cannot pass an NSError
as usual and set the error code.
在NSError的情况下,它以这种方式工作,因为NSError不是一个可变类型 - 它的字段在初始化时设置,从不变异。因此,您不能像往常一样传递NSError并设置错误代码。