2016-03-03 81 views
0

这对高级和经验丰富的开发人员来说可能是一个明显的问题,所以我真的害怕问这个问题。向用户iOS显示错误信息的最佳方法

假设我有一个移动应用程序,它针对不同的数据模型调用了太多的RESTful API。假设有ViewController A,B,C可以在这些模型上进行CRUD。现在有几件事情可能会出错。每个呼叫都有一个故障块。我正在使用Strongloop/Loopback ios sdk。

悄悄忽略这样的错误的策略:

[repo logoutWithSuccess:^(){ 
    // ... success code 
} failure:CALLBACK_FAILURE_BLOCK]; 

具有限定CALLBACK_FAILURE_BLOCK

#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 

#define CALLBACK_FAILURE_BLOCK \ 
    ^(NSError *error) { \ 
    ALog("Callback failed: %@", error.description); \ 
    } 

将是一个理想的世界里,每一个客户端验证工作完全伟大,人们可以把头埋在沙子里。

目前我已经在每个ViewController中定义了一个帮助函数,当这些调用失败时向用户显示一个警报。

[self.trip saveWithSuccess:^(){ 
    //... success code 
} failure:^(NSError *error){ 
    [self displayErrorWithMessage:[error localizedDescription] 
         andTitle:NSLocalizedString(@"Service Error", @"Server Error")]; 
}]; 

- (void)displayErrorWithMessage:(NSString*)msg andTitle:(NSString*)title{ 
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:title 
                    message:msg 
                  preferredStyle:UIAlertControllerStyleAlert]; 

    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault 
                  handler:^(UIAlertAction * action) { 
                  }]; 

    [alert addAction:defaultAction]; 
    [self presentViewController:alert animated:YES completion:nil]; 
} 

我想重构这个辅助函数是在一个共同的地方,例如像AppDelegate中(也许在一个协议)。

这是一个正确的战略,你有任何其他最好的做法,如何更好地设计它?

+0

我认为你做得很好。但是,如果将相同的功能复制到整个视图控制器,则意味着您有代码复制。最简单的方法来处理它,你可以拥有所有视图控制器的基本视图控制器,并只实现一次该功能。之后,你可以很容易地对他们进行操作,如添加自定义错误视图,你可以给动画等。 – kekkeme

+0

@Sanandrea如果有人回答你的问题,这是你的工作,让你的宝贵意见。 – ChenSmile

回答

1

最近我使用这种方法为我的应用程序之一,我希望它的作品很好,很容易处理错误。为此,我创建了UIViewController的ErrorViewController子类(在我的案例中,它是VCBaseViewController,它是所有其他视图控制器的父类,它是UIViewController的子类)。你可以使用故事板或xib,它由你来决定。我通过我的应用程序使用故事板。

我ErrorViewController.h

@interface ErrorViewController : VCBaseViewController 

@property (nonatomic, strong) NSString *errorTitle; 
@property (nonatomic, strong) NSString *errorDescription; 

@property(nonatomic,assign) ErrorPageType errorPage; 

@property (weak, nonatomic) IBOutlet UILabel *lblErrorText; 
@property (weak, nonatomic) IBOutlet UITextView *textViewErrorString; 
@property (weak, nonatomic) IBOutlet UIButton *btnAction; 

@end 

ErrorViewController.m

@interface ErrorViewController() 

@end 

@implementation ErrorViewController

- (void)viewDidLoad { 
[super viewDidLoad]; 
[self configureNavigationBarWithStyle:NavigationStyleBackButton]; 
[self setViewControllerTitle:@"Error View"]; 
} 

- (void)viewWillAppear:(BOOL)animated{ 
[super viewWillAppear:YES]; 

switch (self.errorPage) 
{ 
    case ErrorTypeNetworkError: 
    { 

    } 
     break; 

    case ErrorTypeTechnicalError: 
    { 
     self.lblErrorText.text = @"Technical Error"; 
     self.textViewErrorString.text = @"Due to some technical error\n page not exist"; 
    } 
     break; 

    default: 
    { 
     self.lblErrorText.text = self.errorTitle; 
     self.textViewErrorString.text = self.errorDescription; 
    } 
     break; 
    } 
    } 

- (IBAction)btnErrorAction:(id)sender{ 
[self errorPageAction]; 
} 

- (void)backButtonPressed{ 
[self errorPageAction]; 
} 

- (void)errorPageAction 
{ 
switch (self.errorPage) 
    { 
    case ErrorTypeNetworkError: 
    { 

    } 
    break; 
    case ErrorTypeProductNotAvailable: 
    { 
     [self popToPreviousController]; 
    }break; 
    default: 
    { 
     [self popToPreviousController]; 
    }break; 
    } 
} 

- (void)popToPreviousController 
{ 
    NSArray* viewcontrollers = [self.navigationController viewControllers]; 
if(viewcontrollers.count>2) 
{ 
    int index = (int)viewcontrollers.count - 3; 
    [self.navigationController popToViewController:[viewcontrollers objectAtIndex:index] animated:YES]; 
}else{ 
    [self.navigationController popToRootViewControllerAnimated:YES]; 
    } 
} 

我的故事板的设计是这样的,它包含错误图像错误标签和TextView的和后退按钮,因为即时通讯使用导航控制器。 [![请在此输入图像说明] [1] [1]

我BaseViewController.h

typedef enum { 
ErrorTypeNetworkError = 0, 
ErrorTypeTechnicalError, 
ErrorTypeNone 
} ErrorPageType; 

- (void)pushErrorViewcontroller:(NSError*)error; 
- (void)pushErrorViewcontroller:(NSString*)errorTitle andErrorPage:(ErrorPageType)errorType; 
- (void)pushErrorViewcontroller:(NSString *)errorTitle errorDescription:(NSString *)errorDescription errorType:(ErrorPageType)errorType; 

BaseViewController.m

- (void)pushErrorViewcontroller:(NSString*)errorTitle andErrorPage:(ErrorPageType)errorType{ 
[self pushErrorViewcontroller:nil errorDescription:nil errorType:errorType]; 
} 

- (void)pushErrorViewcontroller:(NSError*)error{ 
[self pushErrorViewcontroller:nil errorDescription:[error localizedDescription] errorType:ErrorTypeNone]; 
} 

- (void)pushErrorViewcontroller:(NSString *)errorTitle errorDescription:(NSString *)errorDescription errorType:(ErrorPageType)errorType{ 
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 
ErrorViewController *errorViewController = [storyBoard instantiateViewControllerWithIdentifier:NSStringFromClass([ErrorViewController class])]; 
errorViewController.errorPage = errorType; 
errorViewController.errorDescription = errorDescription; 
errorViewController.errorTitle = errorTitle; 
[self.navigationController pushViewController:errorViewController animated:YES]; 
} 

我打电话是在其他errorView控制器方法查看这样的控制器。

- (void) ServiceCallForOrderHistoryWithCurrentPageMark: (NSString *)page 
{ 
__block __weak VCMyOrderViewController* blockMyOrderListView = self; 

[[ModelManager sharedInstance] getMyOrderDetail:[[Configuration sharedConfig] getLoggedInUserId] andPageNumber:page completionBlock:^(id result, NSError *error) 
{ 
    if (!error) 
    {   

     blockMyOrderListView.objOrderHistoryBaseClass = (OrderHistoryBaseClass *)result; 

     if (blockMyOrderListView.objOrderHistoryBaseClass.rESPONSE.totalOrderCount.intValue == 0) 
     { 
      [blockMyOrderListView.tblMyOrder setHidden:YES]; 
      [blockMyOrderListView.viewNoOrders setHidden:NO]; 
     } 
     else 
     { 
      [blockMyOrderListView setDataSourceMyOrders:blockMyOrderListView.objOrderHistoryBaseClass.rESPONSE]; 
      [blockMyOrderListView.tblMyOrder reloadData]; 
     } 
    } 
    else 
    { 
     [blockMyOrderListView pushErrorViewcontroller:error]; 
    } 
}]; 
} 
+0

这是否符合苹果的UI设计指南? – Sanandrea

+0

@Sanandrea我想这是基于设计模式。你可以写特定的邮件给苹果,并获得反馈。你问它在堆栈,所以我在这里回答。它适用于他 – ChenSmile

+0

@Sanandrea如果你确定我的回答。 PLZ接受它,所以其他人可以受益.. – ChenSmile

相关问题