iOSアプリでタイムアウトありでデータを同期ロードしたい

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

NSData や NSString にはネットワーク越しでも URL を指定するだけで、 同期でデータを読み込むことができる init メソッドが用意されています。
アプリケーションの初期化や別スレッドで連続してデータ読み込むような場合には、 このような同期型メソッドを利用すると見通しよく実装できます。

NSData である URL のファイルを読み込みときのコードは次のようになります。

NSURL *url = [NSURL URLWithString:@"https://classmethod.jp/foo.xml"];
NSError *error = nil;
NSData *data = [[NSData alloc] initWithContentsOfURL:url options:0 error:&error];
if (!data || error) {
    NSLog(@"failed to get data.");
    return;
}

// data を処理

上記の方法では、サーバがダウンしてるときにタイムアウトが極端に長くなるため、 ユーザビリティを損なう可能性があります。
NSURLConnection の同期呼び出しを使うと、NSURLRequest の初期化時に timoutInterval でタイムアウトの秒数を指定することができます。
timoutIntervalの型は、NSTimeInterval (double) なので小数点以下も指定できます。

これを利用して同期ロードでタイムアウトを適切な長さにすることができます。
以下は、10秒でタイムアウトするようにしました。

NSURL *url = [NSURL URLWithString:@"https://classmethod.jp/foo.xml"];
NSError *error = nil;
NSURLResponse *res = nil;
NSURLRequest *req = [[NSURLRequest alloc] initWithURL:url
                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                      timeoutInterval:10.0];
NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&error];
[req release];
if (!data || error) {
    NSLog(@"failed to get data.");
    return;
}

// data を処理