为什么是“错误:&错误”?这里使用(objective-c)

发布于 2024-12-19 09:43:01 字数 205 浏览 8 评论 0原文

为什么这里使用“error:&error”(objective-c),

NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];

objective-c 中的对象无论如何都不会有效地传递引用吗?

why is "error:&error" used here (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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

痴梦一场 2024-12-26 09:43:01

error: 的参数类型是 NSError** (即指向对象的指针的指针)。这允许 moc 对象根据需要分配并初始化一个新的 NSError 对象。这是一种常见的模式,尤其是在可可中。

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;
    }
}

请注意,这还允许调用代码通过简单地为 错误传入 NULL 来忽略错误: 参数,如下:

NSArray *array = [moc executeFetchRequest:request error:NULL];

更新:(回答问题):

参数类型必须为 NSError** 而不是 NSError 有两个原因*:1. 变量作用域规则,2. NSError 实例是不可变的。

原因#1:变量作用域规则

让我们假设函数声明如下所示:

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error;

我们将这样调用函数:

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

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

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

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

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

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

首先,变量作用域规则保证 error 不会为 nil,因此 if (error != nil) { ... 条件将始终为 true,但即使您想检查 < 中的特定错误信息code>if 块,你会运气不好,因为 NSError 的实例是不可变的。这意味着一旦创建它们,您就无法修改它们的属性,因此该函数将无法更改该 NSError 的 domainuserInfo > 您在调用代码中创建的实例。

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

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.

The NSError documentation gives some indication of the motivation for this approach:

Applications may choose to create subclasses of NSError to provide better localized error strings by overriding 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.

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:

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.

Reason #1: variable scoping rules

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.

- (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

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.

- (NSArray*)executeFetchRequest:(Request *)request error:(NSError*)error {
    ...
    error.domain = ...   // not allowed!
    error.userInfo = ... // not allowed!
}
如此安好 2024-12-26 09:43:01

它实际上是另一个返回值。按照 Cocoa 中的惯例,当操作有返回值时,错误并不占主导地位。当遇到错误时,可能会通过这个 out 参数返回给您。

对于 NSError 来说,它以这种方式工作,因为 NSError 不是一个可变类型 - 它的字段在初始化时设置并且永远不会改变。因此,您不能像往常一样传递 NSError 并设置错误代码。

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文