4

ユーザーの自動ログインを許可するアプリがあります。私の上司が望んでいるのは、アプリの起動時に、アプリがサーバーへの接続をテストする必要があることです (WiFi または 3G ネットワークがあるかどうかをテストするだけではありません)。Apple のReachabilityサンプルを借りましたが、動作します。

問題は、特に起動時に時間がかかりすぎることです。インターネットに接続していないローカル ワイヤレス ネットワークで試してみたところ、30 分近くかかりました。そして、自動ログインが -ViewDidLoad() で呼び出されたため、その 30 分の間、UI が読み込まれませんでした。それほど長い時間をかけることは、単に受け入れられません。さらに悪いことに、アプリの読み込みに時間がかかりすぎると、iOS がアプリをシャットダウンすることさえあります。

さらに、私のアプリには多くの Web サービス呼び出しがあります。iPhone/iPad の性質上、ユーザーがある場所から別の場所に歩いてすぐに話しかけても、簡単に接続を失ったり取得したりできるため、各 Web サービス呼び出しが失敗する可能性があることは理解しています。個人的には好きではありませんが、それは上司が私に求めていることであり、おそらくアプリで頻繁に接続をテストする必要があります.

したがって、ここで私が探しているのは、接続を非常に高速に(数秒以内に)検出する方法か、ユーザーエクスペリエンスに影響を与えずに舞台裏でそれを行う方法です。

誰にも提案がありますか?

私の質問を読んでくれてありがとう。

4

3 に答える 3

5

Present an intermediate loading view with presentModalViewController while the test is taking place and run the actual test using performSelectorInBackground. Then signal back to the main thread with 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秒待つという全体的なユーザーエクスペリエンスは、アプリの使用中に接続が頻繁に変化するため、起動するたびにテストを行っても、信頼できるとは限りません。しかし、それがあなたの上司が望んでいるものであるならば、私はあなたと一緒に苦しみます。;)

于 2012-07-11T14:35:34.143 に答える
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

ご覧のとおり、ほんの一瞬です。もちろん、現在サーバーに問題が発生していますが、あなたの問題はフレームワークの問題ではなく、サーバーの問題である可能性があると思います。ただし、いつでも別のスレッドでサーバー チェックを実行してみることができます。

于 2012-07-11T17:04:17.977 に答える
4

コメントで言ったように、Hampus Nilsson のアプローチを使用して、とにかくバックグラウンドでリクエストを実行する必要があります。

あなたの 30 秒の問題に関して、私は別のブログでこれを見つけました:

- (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];
于 2012-07-16T14:22:37.037 に答える