在应用程序启动期间iOS测试连接到服务器需要太长时间

时间:2012-07-11 14:23:17

标签: iphone ios ipad networking reachability

我有一个允许用户自动登录的应用。我的老板想要的是,当应用程序启动时,应用程序需要测试与我们服务器的连接(而不仅仅是测试是否有WiFi或3G网络)。我借了苹果的Reachability样本,它有效。

问题是需要太长时间,特别是在发布时。我在没有互联网连接的本地无线网络上尝试过,我花了将近半分钟的时间。因为自动登录在-ViewDidLoad()中调用了半分钟,所以ui没有加载。花费很长时间的时间是完全不可接受的。更糟糕的是,如果我的应用程序加载时间太长,iOS甚至可能会关闭应用程序。

此外,我的应用程序中有很多Web服务调用。我理解每个网络服务电话都有可能失败,因为即使用户从一个地方走到另一个地方,iPhone / iPad也可能很容易丢失或获得连接。我个人不喜欢它,但这就是我老板要我做的事情,我可能不得不在应用程序中经常测试连接。

所以这里我要找的是一种非常快速(几秒钟内)检测连接的方法,或者是在幕后进行连接而不影响用户体验的方法。

有人有建议吗?

感谢您抽出宝贵的时间阅读我的问题。

3 个答案:

答案 0 :(得分:5)

在测试进行时,使用presentModalViewController显示中间加载视图,并使用performSelectorInBackground运行实际测试。然后用performSelectorOnMainThread

发回主线程
- (void)viewDidLoad
{
    [super viewDidLoad];

    // Make this a hidden member
    loadingViewController = [LoadingViewController new];
    [self presentModalViewController:loadingViewController animated:NO];

    [self performSelectorInBackground:@selector(testConnectivity) withObject:nil];
}

- (void)testConnectivity
{
    // Do expensive testing stuff

    [self performSelectorOnMainThread:@selector(testCompleted) withObject:nil waitUntilDone:NO];
}

- (void)testCompleted
{
    [loadingViewController dismissViewControllerAnimated:YES];
    loadingViewController = nil;
}

请注意,在您使用应用程序时,应用程序开始排序等待30秒的整体用户体验以及连接经常发生变化,因此即使您在每次启动时都进行测试,也不太可靠。但如果这是你的老板想要的,我会和你一起受苦。 ;)

答案 1 :(得分:5)

对于它的价值,这是我使用的方法..

- (BOOL)checkServerAvailability {
    bool success = false;
    const char *host_name = [@"host" cStringUsingEncoding:NSASCIIStringEncoding];

    SCNetworkReachabilityRef reachability = 
                  SCNetworkReachabilityCreateWithName(NULL, host_name);
    SCNetworkReachabilityFlags flags;
    success = SCNetworkReachabilityGetFlags(reachability, &flags);
    bool isAvailable = success && (flags & kSCNetworkFlagsReachable) 
                   && !(flags & kSCNetworkFlagsConnectionRequired);

    CFRelease(reachability);
    return isAvailable;
}

以下是我的服务器检查方法的日志记录结果......

2012-07-11 11:29:04.892 ASURecycles[1509:f803] starting server check...
2012-07-11 11:29:04.894 ASURecycles[1509:f803] creating reachability...
2012-07-11 11:29:04.894 ASURecycles[1509:f803] creating flags...
2012-07-11 11:29:04.913 ASURecycles[1509:f803] checking for success of reachability, assigning to flags..
2012-07-11 11:29:04.913 ASURecycles[1509:f803] checking our flags to determine network status...
2012-07-11 11:29:04.913 ASURecycles[1509:f803] not available

如你所见,一秒钟的分数。当然我们的服务器目前正在遇到麻烦,但我认为你的问题可能是服务器问题,而不是框架问题。你总是可以尝试在另一个线程上执行服务器检查。

答案 2 :(得分:4)

正如我在评论中所说,你应该使用Hampus Nilsson's approach来在后台执行请求。

关于你的30秒问题,我在another blog中找到了这个问题:

- (BOOL)isHostAvailable:(NSString*)hostName
{
    // this should check the host but does not work in the simulator, aka it returns YES when should be no
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName cStringUsingEncoding:NSASCIIStringEncoding]);
    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    if (reachability) {
        CFRelease(reachability);
    }

    if ( ( success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired) ) == NO) {
        return NO;
    }

    // we know at least the network is up, second check for a known page
    NSData *dataReply;
    NSURLResponse *response;
    NSError *error;

    // create the request
    NSString *urlString = [NSString stringWithFormat:@"http://%@/index.php", hostName];
    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]
                                            cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                        timeoutInterval:8.0];
    // Make the connection
    dataReply = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];

    if (response != nil) {
        NSLog(@"SNNetworkController.isHostAvailable %@", response);
        return YES;
    } else {
        // inform the user that the download could not be made
        NSLog(@"SNNetworkController.isHostAvailable %@ %@", response, error);
        return NO;
    }
}

这将执行超时值为8秒的请求。

//编辑:
ASIHTTPRequest示例:

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setNumberOfTimesToRetryOnTimeout:3];
[request setTimeOutSeconds:20.0];
[request setRequestMethod:@"POST"];
[request startAsynchronous];