同时调用多个 ViewController 实例会导致应用在 AppDelegate 中崩溃

Posted

技术标签:

【中文标题】同时调用多个 ViewController 实例会导致应用在 AppDelegate 中崩溃【英文标题】:Multiple instances of ViewController being called simultaneously cause the app to crash in AppDelegate 【发布时间】:2013-01-16 08:32:38 【问题描述】:

我在做什么?

    我目前正在为我的应用程序在没有互联网的情况下进行防崩溃。 我已经安装了Little snitch暂时禁用网络访问。 发出请求并且如果响应为零,则触发“可达性测试”。下面代码中的 ReachabilityController 只是 Apple 提供的 Reachability 类的包装器。

此代码在其他地方是否有效?

应用程序充满了在线请求,我在其他视图控制器中从未遇到过这个问题。如果互联网不可用,它会显示一条很好的描述状态的小消息。

错误发生在哪里

应用代理

错误

* * * -[ReachabilityController respondsToSelector:]:消息发送到已释放实例 0x12a71320

ReachabilityController 显示一个描述错误状态的 UIAlertView。警报视图会出现大约一秒钟,然后应用程序崩溃。

调试和仪器?

NSLog(@"%p", reachability); 记录与错误中相同的地址。 0x12a71320。不用说,这个地址在每次运行时都会有所不同。

Instruments 中的 Zombies 模板也在 Reachability Controller 中指出。

下图中“Responsible”部分的4行白色补丁包含应用的名称。

我期待什么?

老实说,我不知道这种行为背后的原因。我相信它必须非常基本。

与现在的本地声明相比,我是否必须声明一个属性才能保留“ReachabilityController”?

代码

发生崩溃的片段。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

dispatch_async(queue, ^
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myUrl"]];
    NSData *authResponse = [NSData dataWithContentsOfURL:url];

    dispatch_sync(dispatch_get_main_queue(), ^
        if(authResponse == nil) 
            ReachabilityController *reachability = [[ReachabilityController alloc] init];
            NSLog(@"%p", reachability);
            [reachability checkReachability];
            NSLog(@"%p", reachability);
            return; // app crashes round here
         

ReachabilityController.h

#import <UIKit/UIKit.h>
#import "Reachability.h"

@interface ReachabilityController : UIViewController
  -(void) checkReachability ;
@end

ReachabilityController.m

#import "ReachabilityController.h"

@interface ReachabilityController ()

@end

@implementation ReachabilityController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   if (self) 
     // Custom initialization
   
   return self;


- (void)viewDidLoad

    [super viewDidLoad];
// Do any additional setup after loading the view.


- (void)viewDidUnload

    [super viewDidUnload];




-(void) checkReachability 
    Reachability* internetAvailable = [Reachability reachabilityForInternetConnection];
    NetworkStatus netStatus = [internetAvailable currentReachabilityStatus];
    NSString *messageText;
    if (netStatus == NotReachable)
    
        messageText = [NSString stringWithFormat:@"iRestaurant has determined that internet access is not available at the moment"];

     else 
        NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
        NSString *ipAdress = [infoDict objectForKey:@"LookUpIpAdress"];
        NSString *host = [NSString stringWithFormat:@"%@/iRestaurant", ipAdress];

        Reachability *netReach = [Reachability reachabilityWithHostName:host];
        NetworkStatus hostStatus = [netReach currentReachabilityStatus];
        if (hostStatus == NotReachable)
        
            messageText = [NSString stringWithFormat:@"Sorry, for your inconvenience. iRestaurant server is currently unreachable. The iRestaurant server may be down for maintenance. Please check back after 5 mins"];

         else 
            messageText = [NSString stringWithFormat:@"Sorry, for your inconvenience. This service is temporarily unavailable. We are working very hard to get it back on track."];
        

    

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"iRestaurant"
                                                    message:messageText
                                                   delegate:self
                                          cancelButtonTitle:@"Done"
                                          otherButtonTitles:nil];
    [alertView show];




@end

更新:

更改问题的标题

只是最近的发现。有 3 个实例从在线服务器请求数据。由于无法上网,这三种方法几乎同时要求进行可达性测试。这三种方法都有与上面类似的方法声明。三种方法都使用如下所示的“本地声明”来触发测试。

ReachabilityController *reachability = [ReachabilityController alloc] init];
[reachability checkReachability];

【问题讨论】:

【参考方案1】:

您将 UIAlertView 的委托设置为 self。除非您有办法在 UIAlertView 发布之前保留您的 ReachabilityController,否则这是一个悬空引用。

您是否需要 UIAlertView 与您的 ReachabilityController 进行交互?将 nil 作为委托传递可能是最简单的。

【讨论】:

我想我可以试试。此外,针对“可达性测试”提出了三个请求。第一个测试就足够了,所以我正在考虑将 NSNotification 引入图片中。你有什么感觉? 在 ReachabilityController 中将 UIAlertView 委托设置为 nil 解决了问题

以上是关于同时调用多个 ViewController 实例会导致应用在 AppDelegate 中崩溃的主要内容,如果未能解决你的问题,请参考以下文章

从另一个 ViewController 调用一个 ViewController 的实例方法

以同一方法处理和运行多个 ViewController

在RelationshipSegue之后调用ViewController中的函数

如何在 ViewController 中调用所有自定义 UIView 的方法?

在 viewDidLoad 之前调用 ViewController 上的自定义 init 方法

如何同时滚动多个tableview