Objective-c передает параметр ошибки в метод inside
Это общий шаблон для добавления параметра вывода ошибок при написании методов Objective-c.
Насколько я знаю, это то, как вы создаете метод, который возвращает ошибку, если что-то не так:
- (void)doSomethingWithObj:(id)obj error:(NSError *__autoreleasing *)error {
BOOL success = NO;
// do somthing...
if (!success) {
*error = [NSError errorWithDomain:@"the.domain" code:0 userInfo:nil];
}
}
Теперь бывают случаи, когда вы просто хотите, чтобы этот параметр ошибки отражал ошибку, возникшую в каком-либо другом методе, который вы используете внутри своего метода, скажем:
- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];
NSArray *results = [context executeFetchRequest:request error:nil];
}
Итак, я подумал, что я просто передам параметр error внутреннему методу, вот так:
- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];
NSArray *results = [context executeFetchRequest:request error:error];
if (error) {
NSLog(@"error %@", error);
}
}
Но у этого подхода есть две проблемы:
1. if (error)
чек возвращается YES
даже если нет ошибки.
2. строка журнала генерирует это предупреждение: Format specifies type 'id' but the argument has type 'NSError *__autoreleasing *'
Так что я здесь не так делаю?
2 ответа
Вы передаете адрес ошибки не фактическая ошибка это означает &error
Так что вам нужно разыменовать указатель ошибки.NSError *__autoreleasing *
вы принимаете параметр в качестве адреса error
. Обычно мы делаем это, потому что objective c
может возвращать только одно значение. Но нужно знать об ошибке, откуда мы вызываем метод, поэтому передача его в качестве адреса ошибки приведет к изменению на ошибку, если в ней возникает ошибка calle function
, Так что, если какая-либо ошибка появляется в строке ниже
NSArray *results = [context executeFetchRequest:request error:error];
чем это автоматически известно calle function
т.е. doSomethingWithObj
if (*error) {
NSLog(@"error %@", (*error).description);
}
использование
NSLog(@"error %@", (*error).description);
вместо
NSLog(@"error %@", (error).description);
Вы должны пройти и ошибка
Есть пара вещей не так. Во-первых NSError
Объект не должен использоваться для проверки на ошибки, вместо этого используйте возвращаемое значение метода. Поэтому ваш первый пример метода должен вернуть BOOL
указать на успех:
- (BOOL)doSomethingWithObj:(id)obj error:(NSError *__autoreleasing *)error {
BOOL success = NO;
// do somthing...
if (!success) {
if (error) { // Check it's been passed, and if so create the error object.
*error = [NSError errorWithDomain:@"the.domain" code:0 userInfo:nil];
}
}
return success;
}
И проверить на results
являющийся nil
не error
будучи неnil
:
- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];
NSArray *results = [context executeFetchRequest:request error:error];
if (!results) {
if (error && *error)
NSLog(@"error %@", [(*error) localizedDescription]); // Here is your 2. I think.
else
NSLog(@"Unknown error");
}
}
Во-вторых error
параметр обычно является необязательным (как видно из кода, где вы передаете nil
, который должен быть NULL
на самом деле). Поэтому вам нужно проверить, был ли он передан перед разыменованием (см. Код выше).
Однако, чтобы ответить на ваш общий вопрос, да, это хорошо, чтобы передать error
Параметр наряду с подчиненными вызовами методов и обычно используется.
Я понятия не имею о вашем 2. пока вы не обновите свой код... в ожидании. Я думаю, что ваша проблема 2. потому что вам нужно использовать [error localizedDescription]
с NSLog()
,