2

Я создаю фреймворк для использования приложения Cocoa 10.6 и более поздних версий.Обработка ошибок Objective-C

Целью рамок является разбор текстового файла.

Очевидно, есть ошибки, которые могут возникнуть, например, файл не найдено, разрешение проблемы и т.д.

Что такое правильный способ обработки ошибок в рамках и уведомить хост-приложение?

Мои мысли были:

  1. не делать ничего, и пусть хост-приложение поймать каких-либо исключений.

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

Есть ли какой-либо из этих вариантов? Есть ли другие варианты? Каков правильный способ справиться с этим?

Я прочитал руководства по обработке ошибок и исключений, но они не охватывают эту ситуацию и описывают обработку ошибок только в самом приложении.

+1

Я никогда не слышал, чтобы какой-либо код пропускал NSErrors в цепочку ответчиков. (Что, если вызывающий код не имеет ничего общего с любыми NSR-ответами, например, если он находится в командной строке?) Что бы вы ни делали: не делайте этого! –

+0

@ KurtRevis, проверьте - [NSResponder presentError:] и друзья, например, –

+0

А, это интересно - я, должно быть, пропустил их, когда их добавили к 10.4. Я ожидал бы, что структура нижнего уровня (как в этом случае, только разбор текстового файла) передаст «NSError» своему вызывающему абоненту и пусть код UI будет иметь дело с презентацией. –

ответ

1

Я бы сказал, что правильным способом является использование NSError непосредственно во всех методах, которые могут привести к ошибке. Я сделал это недавно с созданным мной классом утилиты, и он работает очень хорошо. Затем вы разрешаете приложению решать, что делать с ошибкой (сбой, журнал, что-то еще), и фрейму не нужно беспокоиться.

Вот частных методов класса, которые я использовал для создания объектов ошибок, что позволяет нижележащие ошибки POSIX (errno и т.д.):

#pragma mark - Private Methods 

- (NSError *)error:(NSString *)localizedDescription 
       code:(EZipFileError)code 
    underlyingError:(NSError *)underlyingError 
{ 
    NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary]; 
    [errorDetail setValue:localizedDescription forKey:NSLocalizedDescriptionKey]; 
    if (underlyingError != nil) 
    { 
     [errorDetail setValue:underlyingError forKey:NSUnderlyingErrorKey]; 
    } 
    return [NSError errorWithDomain:@"MyErrorDomain" 
           code:(NSInteger)code 
          userInfo:errorDetail]; 
} 

- (NSError *)error:(NSString *)localizedDescription 
       code:(EZipFileError)code 
{ 
    return [self error:localizedDescription 
        code:code 
     underlyingError:nil]; 
} 

- (NSError *)error:(NSString *)localizedDescription 
       code:(EZipFileError)code 
     posixError:(int)posixError 
{ 
    NSMutableDictionary *underlyingErrorDetail = [NSMutableDictionary dictionary]; 
    [underlyingErrorDetail setValue:[NSString stringWithUTF8String:strerror(posixError)] 
          forKey:NSLocalizedDescriptionKey]; 
    NSError *underlyingError = [NSError errorWithDomain:NSPOSIXErrorDomain 
                code:posixError 
               userInfo:underlyingErrorDetail]; 
    return [self error:localizedDescription 
        code:code 
     underlyingError:underlyingError]; 
} 

который используется следующим образом:

if (![self isOpen]) 
{ 
    if (error != NULL) 
    { 
     *error = [self error:@"File is not open" 
         code:ErrorNotOpen]; 
    } 
    return nil; 
} 

Вот пример, который использует базовую версию ошибки POSIX метода:

filefp = fopen([filename UTF8String], "rb"); 
if (filefp == NULL) 
{ 
    if (error != NULL) 
    { 
     *error = [self error:@"Failed to open file" 
         code:ErrorOpenFileFailed 
        posixError:errno]; 
    } 
    return NO; 
} 
+0

Из любопытства, в чем смысл заполнять словарь basicErrorDetail? Он не возвращается, поэтому я могу только предположить, что он используется в другом месте вашего кода. – wadesworld

+0

@wadesworld Да, я не показывал пример вызова версии метода posixError, но есть и другие, которые я забыл. Точка unelyingError заключается в том, чтобы разрешить произвольную глубину информации, немного похожую на концепцию «Исходная причина Java». Я отредактирую свой ответ, чтобы добавить примерный вызов. – trojanfoe

1

Исключения должны использоваться только для терминальных ошибок в объективе-C. Более конкретно, Cocoa и Cocoa Touch не гарантируют, что исключения, брошенные через их границы, выйдут с другой стороны, поэтому вы не должны использовать исключения для обработки ошибок.

Правильный способ сообщить об ошибках вызывающему абоненту через объект NSError. Вы заметите, что многие методы Cocoa и Cocoa Touch включают параметр NSError * для этой цели.

Смежные вопросы