NSError: Использует ли nil для обнаружения Error фактическое отключение отчетов об ошибках? - PullRequest
6 голосов
/ 18 января 2011

У меня появилась привычка кодировать мою обработку ошибок следующим образом:

 NSError* error = nil;
 NSDictionary *attribs = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error];
 if (error != nil) {
  DLogErr(@"Unable to remove file: error %@, %@", error, [error userInfo]);
  return; 
 }  

Но, глядя на документацию Кажется, что я понял это неправильно.:

- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error

Если возникает ошибка, по возвращении содержит объект NSError, который описывает проблему.Передайте NULL, если вы не хотите получать информацию об ошибке.

Технически нет никакой разницы между nil и NULL, поэтому это означает, что я фактически отключаю это и никогда не получу сообщение об ошибке (даже еслиудалить в приведенном выше примере не удалось)?Есть ли лучший способ закодировать это?

Спасибо.

Ответы [ 3 ]

13 голосов
/ 18 января 2011

Во-первых, следующая строка не имеет смысла:

NSDictionary *attribs = [[NSFileManager defaultManager]
 removeItemAtPath:fullPath error:&error];

-removeItemAtPath:error: возвращает значение BOOL, а не словарь.

Мне кажется, я понимаю, о чем вы удивляетесь значением NULL. Обратите внимание, что в параметре error в сигнатуре метода есть 2 *:

- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error

Это означает указатель на указатель. Когда вы передаете &error, вы передаете адрес указателя на NSError. (Тьфу, кто-то другой, вероятно, может помочь мне здесь, так как моя голова все еще начинает плавать при работе с указателями на указатели). Другими словами, даже если вы установили error на nil, вы не передаете error методу, вы передаете &error.

Итак, вот как должен выглядеть переписанный метод:

// If you want error detection:
NSError *error = nil;
if (![[NSFileManager defaultManager] removeItemAtPath:fullPath
            error:&error]) {
    NSLog(@"failed to remove item at path; error == %@", error);
    // no need to log userInfo separately
    return;
}

// If you don't:
if (![[NSFileManager defaultManager] removeItemAtPath:fullPath
            error:NULL]) {
    NSLog(@"failed to remove item at path");
    return;
}
10 голосов
/ 18 января 2011

Передача NULL означает следующее:

BOOL itemRemoved = [[NSFileManager defaultManager] removeItemAtPath:fullPath
    error:NULL];

, т.е. параметр error равен NULL. Внутри -removeItemAtPath:error: видит, был ли передан действительный указатель. Если это NULL, он просто не сообщит об ошибке как экземпляр NSError - но возвращаемое значение будет указывать, завершился ли метод успешно.

Кроме того, ваш тест неверен. Не следует использовать выходной параметр error, чтобы определить, произошла ли ошибка, потому что она может быть установлена ​​, даже если метод завершается успешно . Вместо этого вы должны использовать возвращаемое значение метода для обнаружения ошибок. Если возвращаемое значение (в данном конкретном случае) NO, используйте выходной параметр error, чтобы получить информацию об ошибке:

NSError *error = nil;
BOOL itemRemoved = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error];
if (itemRemoved == NO) {
    DLogErr(@"Unable to remove file: error %@, %@", error, [error userInfo]);
    return; 
}

Цитирование Руководство по программированию обработки ошибок ,

Важно: Успешность или неудача указывается возвращаемым значением метода. Хотя методы Какао, которые косвенно возвращают объекты ошибок в домене ошибок Какао, гарантированно возвращают такие объекты, если метод указывает на сбой, напрямую возвращая ноль или НЕТ, вы всегда должны проверять, чтобы возвращаемое значение было ноль или НЕТ, прежде чем пытаться что-либо делать с NSError object.


Редактировать : Как указал NSGod, -removeItemAtPath:error: возвращает BOOL, а не NSDictionary *. Я отредактировал свой ответ, чтобы отразить это.

0 голосов
/ 18 января 2011

Нет, я делаю то же самое, и он отлично работает для обнаружения ошибок.Вы не передаете ему NULL, вы передаете на него указатель на NULL, что совсем другое.Хотя вы можете добавить еще один вариант:

if (error != nil){...
}else{
  [NSApp presentError:error]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...