1

アドレスまたは IP の到達可能性をチェックする Swift 1.2 で記述された関数があります。ここにあります :

func isHostConnected(hostAddress : String) -> Bool
{
    var response : NSURLResponse?
    let request = NSMutableURLRequest(URL: NSURL(string: hostAddress)!)
    request.timeoutInterval = 3

    let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil)

    return ((response as? NSHTTPURLResponse)!.statusCode == 200)
}

は廃止されたため、NSURLConnectionXcode の提案に従って、 を使用して記述しようとしNSURLSession.dataTaskWithRequestましたが、次のとおりです。

func isHostConnected(hostAddress : String) -> Bool
{
    let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
    request.timeoutInterval = 3

    let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())

    var responseCode = -1

    session.dataTaskWithRequest(request, completionHandler: {(data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in
        responseCode = (response as? NSHTTPURLResponse)!.statusCode
    })!.resume()

    return (responseCode == 200)
}

上記のコードは、別のスレッドで実行されるため、常にfalse (明らか)を返します。completionHandler

私の懸念は、 MainThread をブロックすることによってcompletionHandler()何らかの方法で MainThread で実行できるかというsendSynchronousRequestことです。

ここで「Apple's Reachabilty」を使用しない理由があります。

どんな提案も役に立ちます。:)

4

1 に答える 1

11

( https://stackoverflow.com/a/30670518/1187415からの私の議論を繰り返します:)

リソースがサーバー上に存在するかどうかを確認するには、HTTP 要求を送信して応答を受信する必要があります。TCP 通信には、サーバーがビジー状態の場合、クライアントとサーバー間の一部のルーターが正しく機能していない場合、ネットワークがダウンしている場合など、ある程度の時間がかかることがあります。

そのため、非同期リクエストが常に優先されます。リクエストにミリ秒しかかからないと思っていても、ネットワークの問題で数秒かかることもあります。そして、誰もが知っているように、メイン スレッドを数秒間ブロックすることは絶対に厳禁です。

そうは言っても、「カウントセマフォ」または「ディスパッチグループ」を使用して、非同期タスクの完了を待つことができます。これをメイン スレッドで使用しないでください。3 秒までのメイン スレッドのブロックは許容されません。

func isHostConnected(hostAddress : String) -> Bool
{
    let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
    request.timeoutInterval = 3
    request.HTTPMethod = "HEAD"

    let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
    var responseCode = -1

    let group = dispatch_group_create()
    dispatch_group_enter(group)

    session.dataTaskWithRequest(request, completionHandler: {(_, response, _) in
        if let httpResponse = response as? NSHTTPURLResponse {
            responseCode = httpResponse.statusCode
        }
        dispatch_group_leave(group)
    })!.resume()

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
    return (responseCode == 200)
}

備考:

  • サーバーは実際のデータなしで応答ヘッダーのみを送信するため、HTTP メソッドを「HEAD」に設定するのは小さな最適化です。
  • 不正なホスト名の場合、responseになりnilresponseCode = (response as? NSHTTPURLResponse)!.statusCodeクラッシュします。
于 2015-06-20T10:04:51.430 に答える