【问题标题】:What's the correct use of NSErrorRecoveryAttempting, NSError, and UIAlertView in iOS?iOS 中 NSErrorRecoveryAttempting、NSError 和 UIAlertView 的正确用法是什么?
【发布时间】:2011-08-22 22:30:43
【问题描述】:

我找不到在 iOS 上同时使用 NSErrorUIAlertViewNSErrorRecoveryAttempting 的正确方法示例。我可以找到的大多数文档和示例都涵盖了 OS X 上的等效功能,其中相关行为由 Cocoa 集成。但在 iOS 中,似乎有必要“手动”执行此操作,但我找不到如何完成的好示例。

我非常感谢使用 NSError 中的信息来支持从NSErrors 向用户报告的恢复尝试的最佳实践示例。

【问题讨论】:

  • 在某一时刻,我编写了代码来做到这一点(使用 UIAlertView 处理呈现 NSError 等),但我还没有看到实际上有 recoveryAttempter 的错误,所以我不知道是否真的很对。

标签: cocoa-touch ios error-handling uialertview nserror


【解决方案1】:

根据 Apple 的文档:

重要提示:NSError 类在 Mac OS X 和 iOS 上都可用。但是,错误响应和错误恢复 API 和机制仅在 Application Kit (Mac OS X) 中可用。

所以,我不确定您是否可以使用 NSErrorRecoveryAttempting,即使它似乎在文档中已定义(看起来这是 UIKit 文档的一个区域,在从AppKit 的文档)。

这是我如何处理代码中的错误:

NSError *error = nil;
id result = [SomeClass doSomething:&error];

if (!result) {
    NSLog(@"Do something failed: %@", error);
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Something failed!" message:@"There was an error doing something." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
    [alert show];
    return;
}

【讨论】:

  • 由于 NSErrorRecoveryAttempting 是一个非正式的协议,一个对象所需要的只是实现这两个方法。 iOS 上的 NSError 确实包含必要的属性和常量。苹果的评论显然只是指herehere描述的具体appkit方法。
  • NSErrorRecoveryAttempting 在 iOS 上运行良好。您可以在 NSError 标头中看到它。缺少的是像在 MacOS X 上一样将错误传递给警报的能力 - 这很容易通过在 UIAlertView 上添加一个执行错误恢复的类别来实现,并且有几个示例说明如何做到这一点。
【解决方案2】:

我发现了一个很好的例子。

请参阅 James Beith 的以下博客文章和 GitHub 代码(包括示例项目)

http://www.realmacsoftware.com/blog/cocoa-error-handling-and-recovery

https://github.com/realmacsoftware/RMErrorRecoveryAttempter

我能够在 iPhone 模拟器上成功使用它。

【讨论】:

    【解决方案3】:

    我试图在 UIKit 中镜像 AppKit 的错误处理机制,主要是因为我想利用响应者链向上转发错误。我尚未对此进行全面测试,但目前看起来如下所示。

    它非常接近地反映了 AppKit,但是可以覆盖 will/did 挂钩以分别执行自定义错误呈现和恢复。默认行为是显示 UIAlertView 进行演示,并使用伪 NSErrorRecoveryAttempting 对象进行恢复。

    @implementation UIResponder (ErrorHandling)
    
    - (void)presentError:(NSError *)error
            completion:(void (^)(BOOL recovered))completion
    {
        if (nil == (error = [self willPresentError:error])) {
            return;
        }
        if (self.nextResponder) {
            [self.nextResponder presentError:error completion:completion];
            return;
        }
    
        // Code to create and show UIAlertView
        // e.g. https://github.com/jayway/CWUIKit/blob/master/Classes/UIAlertView%2BCWErrorHandler.m
    
        // The UIAlertViewDelegate calls didPresentError...
    }
    
    /*
     Override to customise the error object as in AppKit.
     You can also perform your own error presentation, and return nil to terminate the default handling.
     Custom error presentation UI should still call didPresentError... when dismissed
     */
    - (NSError *)willPresentError:(NSError *)error
    {
        return error;
    }
    
    /*
     Override to perform custom error recovery.
     */
    - (void)didPresentError:(NSError *)error optionIndex:(NSInteger)optionIndex completion:(void (^)(BOOL recovered))completion
    {
        id recoveryAttempter = [error recoveryAttempter];
        if ([recoveryAttempter respondsToSelector:@selector(attemptRecoveryFromError:optionIndex:completion:)]) {
            [recoveryAttempter attemptRecoveryFromError:error optionIndex:optionIndex completion:completion];
        }
    }
    
    @end
    

    【讨论】:

    • 您在 2018 年对此有何看法?
    猜你喜欢
    • 2013-01-07
    • 2015-12-08
    • 1970-01-01
    • 2010-10-14
    • 2015-12-23
    • 2016-01-12
    • 1970-01-01
    • 2012-03-29
    • 2013-03-09
    相关资源
    最近更新 更多