根据 URL 中的特定页面检查可访问性

checking reachability against a specific page in a URL

提问人:JAHelia 提问时间:3/8/2012 最后编辑:Jonas DeichelmannJAHelia 更新时间:8/12/2020 访问量:9302

问:

在我阅读了这个问题的答案后,我发现使用不适用于这样的 URL:,是否有任何可以使用或任何类方法检查此 URL 的可访问性?reachabilityWithHostNamemySite.com/service.asmxreachabilityWithHostNamereachability

提前非常感谢。

iOS Objective-C Swift iPhone 可访问性

评论

1赞 Nick Bull 3/8/2012
可访问性仅用于检查您是否可以访问 Internet,以便您可以确定是否应该提醒用户并因此使用缓存的数据。这是 Apple 用户交互指南的一部分。如果要检查特定 URL,请尝试访问它,将超时设置为非常小并捕获错误。

答:

6赞 fbernardo 3/8/2012 #1

如果要根据 URL(通常使用的 URL 是针对主机名)检查可访问性,只需使用 NSURLConnection 执行 HEAD 请求即可。

17赞 gaige 3/8/2012 #2

Reachability 类 和 旨在成为一种快速、快速故障的机制,用于确定是否具有与主机的基本网络连接。如果需要验证是否可以下载特定 URL,则需要查看 use 来检索 URL 的内容,以验证它是否确实可用。-reachabilityWithHostname:NSURLConnection

根据你是否需要在前台或后台执行此操作,你可以使用简单但阻塞:

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

或者,您可以使用更复杂的方法来创建 NSURLConnection 对象,设置委托来接收响应并等待这些响应传入。

对于简单的情况:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 NSURLResponse *response;
 NSError *error;
 NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];

如果您收到非零 myData,则您已经拥有某种连接。 并会告诉你服务器对你做了什么回应(在响应的情况下,如果你收到了一个非零的myData),或者发生了什么样的错误,在零myData的情况下。responseerror

对于不平凡的情况,您可以从 Apple 的 Using NSURLConnection 中获得很好的指导。

如果您不想停滞前台进程,可以通过两种不同的方式执行此操作。上述文档将提供有关如何实现委托等的信息。不过,更简单的实现方式是使用 GCD 在后台线程上发送同步请求,然后在完成后在主线程上向自己发送消息。

像这样的东西:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, NULL), ^{
      NSURLResponse *response;
      NSError *error;
      NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
      BOOL reachable;

      if (myData) {
            // we are probably reachable, check the response
            reachable=YES;
      } else {
            // we are probably not reachable, check the error:
            reachable=NO;
      }

      // now call ourselves back on the main thread
      dispatch_async( dispatch_get_main_queue(), ^{
            [self setReachability: reachable];
      });
 });

评论

0赞 JAHelia 3/8/2012
您能否提供一个简单的示例,说明如何在后台执行此操作以防止应用程序挂起?
0赞 gaige 3/8/2012
我添加了一个示例,该示例使用 GCD 对后台线程的异步调用发出同步请求,并在响应完成后将响应作为消息返回给主线程。希望能有所帮助。
0赞 JAHelia 3/8/2012
棒!上面的代码有一个小错误,你必须在第一个 if 语句中设置 reachable = YES,在第二个 if 语句中设置为 NO。非常感谢盖奇。
0赞 gaige 3/31/2015
@brainray感谢您的有用编辑。 注意:对于那些想知道为什么域示例从 MySite.com 更改为 example.com 的人,这是 Stack Overflow 的要求。
4赞 Jonas Deichelmann 8/6/2020 #3

斯威夫特 5

Swift 的一个可能的解决方案是:

 func verifyURL(urlPath: String, completion: @escaping (_ isValid: Bool) ->()) {
    if let url = URL(string: urlPath) {
        var request = URLRequest(url: url)
        request.httpMethod = "HEAD"
        let task = URLSession.shared.dataTask(with: request) { _, response, error in
            if let httpResponse = response {
                if httpResponse.getStatusCode() == 200 {
                completion(true)
                }
            } else {
                completion(false)
            }
        }
        task.resume()
    } else {
        completion(false)
    }
}

然后像这样调用方法:

verifyURL(urlPath: "www.google.com", completion: { (isValid) in
    if isValid {
        runYourCode()
    } else {
        print("URL: www.google.com is not reachable")
    }
})