【问题标题】:Not Able to show UIAlert on Exception无法在异常时显示 UIAlert
【发布时间】:2013-11-04 15:17:58
【问题描述】:

我正在使用 UITableView。如果没有网络连接,viewDidload 会抛出异常。我的 viewDidLoad 函数是:

 @try {
                NSLog(@"Request URL = %@",URLString);

                NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
                                                                  URLWithString:URLString]];
                NSData *response = [NSURLConnection sendSynchronousRequest:request
                                                     returningResponse:nil error:nil];

                NSError *jsonParsingError = nil;
                NSDictionary *tableData = [NSJSONSerialization JSONObjectWithData:response
                                                                      options:0
                                                                        error:&jsonParsingError];
                // Grab whole data with data field in JSON
                //    responseArray = [tableData objectForKey:@"data"];


                responseArray = [[NSMutableArray alloc]initWithArray:[tableData objectForKey:@"data"]];
                for(int i = 0; i < responseArray.count; i++)
                {
                    NSArray * tempArray = responseArray[i];
                    responseArray[i] = [tempArray mutableCopy];
                }


                UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
                [btn setFrame:CGRectMake(280.0, 0.0, 40.0, 40.0)];
                [btn setImage:[UIImage imageNamed:@"sort_icon.png"] forState:UIControlStateNormal];
                [btn addTarget:self action:@selector(showActionSheet) forControlEvents:UIControlEventTouchUpInside];
                UIBarButtonItem *barbutton = [[UIBarButtonItem alloc]initWithCustomView:btn];
                self.navigationItem.rightBarButtonItem = barbutton;

        }
        @catch (NSException *exception)
        {
            exceptionOccured = YES;
            NSLog(@"Exception Ocurred");
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Error in connectivity" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
        }

在 cellForRowAtIndexPath 中我正在这样做:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    @try {

    NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
    tempDict = [responseArray objectAtIndex:indexPath.row];

    return cell;

    }
    @catch (NSException *exception)
    {
        NSLog(@"Error in CEll Create");
        NSLog(@"Draw Alert");
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Error in connectivity" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}

在我正在做的 AlertViewDelegate 函数中

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

    [self.navigationController popViewControllerAnimated:YES];
}

现在的问题是,每当出现异常并重新抛出异常并显示错误时,它都不会显示警报

Thread 1: EXC_BAD_ACCESS(code=2, address=0x2)

任何帮助将不胜感激...

【问题讨论】:

  • 你应该重写你的代码以避免抛出异常。它们不适用于网络连接不可用等正常情况。
  • 捕捉到异常并不意味着它会自动消失。您只是有机会清理情况并将数据重置为“稳定”状态。在这里,您只是显示一个警报并且没有采取进一步措施来纠正问题,因此异常仍然会下降并引发。
  • @Cyrille 那么我应该怎么做才能阻止它创建更多的单元格??
  • 当你到达cellForRowAtIndexPath 时已经太晚了。表格视图已经需要这么多行,而实际上您的行数更少。正如其他人所说,例外是 1)这不是一个神奇的解决方案,2)不打算像那样使用
  • 我想补充一点,在断言的情况下,比如'cellForRow'中的returnig nil try/catch 不会阻止应用程序崩溃,你应该防止异常并在这些情况下使用try/catch可能会发生预期的行为,例如处理文件时可能会引发 I/O 异常

标签: ios iphone objective-c uitableview exception-handling


【解决方案1】:

我建议导入这个SystemConfiguration 框架并使用它。这将检查网络连接是否可用。下面是简单的代码:-

    #import <SystemConfiguration/SystemConfiguration.h>
-(void)yourMethod
{    
     SCNetworkConnectionFlags flags = 0;
            if (yourhostname && [yourhostname length] > 0)
            {
                flags = 0;
                BOOL found = NO;
                SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [yourhostname UTF8String]);
                if (reachabilityRef)
                {
                    found = SCNetworkReachabilityGetFlags(reachabilityRef, &flags)
                    &&  (flags & kSCNetworkFlagsReachable)
                    && !(flags & kSCNetworkFlagsConnectionRequired);
                    CFRelease(reachabilityRef);
                    reachabilityRef = NULL;
                }
                if (found)
                {       
                   NSLog(@"Connection available");         
                  }
                  else
                 {
                  NSLog(@"Connection not available");         
                  }
}

【讨论】:

  • @hussain Shabbir:这里的 pingHost 是什么?
  • 抱歉是拼写错误,请检查我是否已修改
  • @hussain Shabbir:模拟器也能用吗??因为我每次都没有连接可用?
  • 这里的连接基本上是指您的VPN连接。如果它没有连接到 vpn,那么它肯定会显示连接不可用
  • @hussain Shabbir:有什么方法可以知道正常的wifi或移动互联网连接
【解决方案2】:

问题出在其他地方。当- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 被调用时,意味着系统需要重新加载tableView。因此,您不应检查该函数内的数据。当你进入这个函数时,你应该确定你的数据是ok的。

你要做的是首先在一个特定的函数中检查你的数据:

     -(void)CheckData(NSArray *responseArray) {
            @try {
                //Retrieve your data & check if its valid
                self.dataArray = responseArray;
                [self.tableView reloadData];
            }
            @catch (NSException *exception)
            {
                NSLog(@"Error in check Data");
                NSLog(@"Draw Alert");
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Error     in connectivity" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
            }

然后,实现您的数据源委托:

    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
           return [self.dataArray count];
       }

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"Cell";

        UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if(cell == nil){
            cell = [[[UITableViewCell alloc]initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier] autorelease] ; 
        }

        //TODO: Init your cell using your self.dataArray content

        return cell;
    } 

【讨论】:

    【解决方案3】:

    你应该避免在你的代码中抛出异常。

    首先,您可以使用Reachability Class 来确定是否有可用的互联网连接。

    我强烈推荐使用NSURLConnectionDelegate 协议进行 URL 连接。所以你可以使用更好的异步编程风格。

    【讨论】:

    • Reachability 只能在发生错误后使用,以找出适当的错误消息或自动刷新行为的原因。如果您想知道是否可以加载某些内容,请尝试加载它并处理错误。 (可达性并不能保证在线时成功或离线时失败,因此在加载之前询问它是没有意义的。)
    • 不保证,对。但实际上可达性是非常快速和准确的。您可以毫无问题地依赖它。对于几乎所有应用程序,可达性就足够了。
    • 不幸的是,我完全不同意您的评估,即您可以毫无问题地依赖它。例如,如果您的服务器返回 HTTP 500 错误,Reachability 会报告您没问题,但在加载数据时您会收到错误消息。你必须处理错误,而不是试图通过可达性来避免它们。同样,Reachability 很容易报告“无连接”,但 URL 加载可以正常工作;例如,如果内容已经在本地缓存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 2019-10-24
    相关资源
    最近更新 更多