繁体   English   中英

如何正确地为用户提供网络反馈? [关闭]

[英]How to correctly provide networking feedback to the user? [closed]

我的应用程序使用后台GCD队列中的同步NSURLConnection从Web服务检索货币兑换率,如下所示:

// This method is called in background queue
- (NSData*)fetchDataWithURLStr:(NSString*)urlStr {
    NSData *jsonData = nil;

   [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    NSURL *url = [NSURL URLWithString:urlStr];
    NSURLResponse *response = nil;
    NSError *error = nil;
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    if (error != nil) {
        NSString *errorMsg = nil;
            NSInteger ec = [error code];

        if (ec == NSURLErrorTimedOut || ec == NSURLErrorCannotConnectToHost) {
            errorMsg = @"Data temporarily not available.";
        }


        // Call on main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            // Present the error
            [self showErrorWithCode:ec title:@"ERROR" message:errorMsg];
        });


        jsonData = nil;
    }

    return jsonData;
}

但问题往往是应用程序试图获取数据,下载似乎永远在运行,没有任何反应。 没有任何状态更新。 通常我的WiFi只是停滞不前,我必须去设置,禁用并重新启用它。 或者我家里的WiFi路由器的互联网连接已关闭,但设备已连接到WiFi。

我真正想做的是提供有关网络目前究竟发生了什么的准确反馈。 例如

“试图联系服务器......”“等等......还在尝试......”“你的互联网似乎已经破了......”“再试一次......”“收到回复......”“已下载20%”“已下载40%“”完了!“

关于正在发生的事情的确切反馈。

有人推荐MKNetworkKit,但它只是觉得死了,没有任何反馈。

这个问题的解决方案适用于iOS吗?

编辑:我有可达性,但它没有给我这种我想在网络中显示的反馈。 此外,Reachability并没有告诉我当有WiFi连接但互联网停滞时发生了什么。

这里的根本问题是,根据您的应用程序可用的信息,不可能(是不可能的 )对网络问题进行可靠的诊断。 可能的原因太多,如果不了解实际网络和/或访问其他诊断信息源,其中一些原因根本无法区分。

你可以使用Reachability类。

下面是一个使用此可访问性类的示例代码,并通知我们正在使用哪种类型的连接。 示例代码来自apple。

以同样的方式看看和实现。

为了向用户显示进度,我建议从其委托方法使用NSURLConnection ,您可以轻松获取连接/请求的状态。

在其中一个委托中,它给出了错误描述。

您应该使用异步 API。 在单独的工作线程/队列中使用同步API通常不是正确的方法(参见有关这些主题的WWDC'12视频)

更好的解决方案是使用较新的NSURLConnection API和+sendAsynchronousRequest:queue:completionHandler:方法,而不是使用sendSynchronousRequest: returningResponse: error: . 通过这种方式,您可以避免阻止API并在请求失败时被通知(无论是启动失败还是因为网络中断而运行失败等)。

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse*, NSData*, NSError*) {
     // Code that will be executed asynchronously
     // when the response to the request has been received 
 }];
// After the call to this method above, the code will continue executing
// WITHOUT WAITING for the network request to have its response.

这样您的UI就不会“冻结”,其余代码将继续运行,因此您可以在视图中显示一些进度指示器,例如,依此类推。 只有在响应到达completionHandler才会异步调用completionHandler块中的代码(独立于其余代码)。

此外,为了在网络本身无法访问(下降等)时获得通知,请使用可达性[编辑]您似乎已经按照您在问题的编辑中添加的那样执行此操作,因此您应该已经了解了这一点,能够在这种情况下通知用户)


提示:您也可以使用一些第三方框架,例如优秀的[ AFNetworking (https://github.com/AFNetworking/AFNetworking),它允许您在发送网络请求时执行更多操作,例如具有Objective-C块在网络请求正在进行时调用的代码,使您可以轻松了解下载的进度。

AFNetworking项目集成到工作区后,您就可以执行以下操作:

AFHTTPRequestOperation* reqOp = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
[reqOp setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, id responseObject)
 {
    // Code to execute asynchronously when you successfully received the whole page/file requested
    // The received data is accessible in the responseObject variable.
 } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // Code to execute asynchronously when you request failed, for example if you have a network error, or received some 404 error code, etc.
    progressLabel.text = [NSString stringWithFormat:@"Download error: %@", error];
 }];
[reqOp setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
 {
    // Code to execute periodically each time a partial chunk of data is received
    // So that you can update your progression. For example:
    progressLabel.text = [NSString stringWithFormat:@"Downloading %.1f%%", (float)totalBytesRead*100.f/totalBytesExpectedToRead];
 }];
[reqOp start]; // start the request
// The rest of the code will continue to execute, and the blocks mentioned above will be called asynchronously when necessary.

这是我检查互联网连接的方式。 您需要先添加Reachability。

+ (BOOL) checkNetworkStatus
{
   Reachability *reachability = [Reachability reachabilityForInternetConnection];
   NetworkStatus networkStatus = [reachability currentReachabilityStatus];
   return !(networkStatus == NotReachable);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM