Вопрос

Почему здесь используется «ошибка: и ошибка» (Objective-C)

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

Разве объект в Objective-C не будет эффективно проходить в любом случае?

Это было полезно?

Решение

Тип аргумента для error: является NSError** (т.е. указатель к указателю на объект). Это позволяет moc объект для распределения и инициализации нового NSError объект по мере необходимости. Это общий рисунок, особенно в какао.

А Несеррорная документация дает некоторое представление о мотивации для этого подхода:

Приложения могут выбрать создание подклассов NSError для обеспечения лучших локализованных строк ошибок, переоценив Локализованный припись.

Прохождение в 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 для error: параметр, следующим образом:

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

Обновлять: (В ответ на вопросы):

Есть две причины, по которым тип аргумента должен быть NSError** вместо NSError*: 1. Переменные правила обрезки, и 2. экземпляры NSERROR Imutable.

Причина № 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 * error = [[[NSError alloc] init...] autorelease];
[someArray executeFetchRequest:someRequest error:error];
if (error != nil) { /* handle error */ }

Прежде всего, переменные правила обрезки гарантируют, что error не может быть nil, Итак if (error != nil) { ... условие всегда будет правдой, но даже если вы хотите проверить конкретную информацию об ошибках внутри if Блок, вам не повезло, потому что случаи NSError находятся неизменный. Анкет Это означает, что после их создания вы не можете изменить их свойства, поэтому функция не сможет изменить domain или же userInfo того, что NSError экземпляр, который вы создали в вызовом коде.

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

Другие советы

Это фактически еще одно возвратное значение. Ошибка не является доминирующей соглашением в какао, когда есть возвратное значение для операции. Когда возникает ошибка, она может быть возвращена вам по этому параметру.

В случае NSError, это работает так, потому что NSError является нет измененный тип - его поля устанавливаются при инициализации и никогда не мутируют. Поэтому вы не можете пройти NSError Как обычно и установите код ошибки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top