• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - AFNetworking 2.0 + UIProgressView 如何正确显示上传 session 的进度

[复制链接]
菜鸟教程小白 发表于 2022-12-12 09:30:36 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在使用 AFHTTPSessionManager 子类通过网络服务下载和上传数据。除了上传进度 View 之外,一切似乎都运行良好,我使用的是 UIProgressView+AFNetworking 类别。
代码是这样设置的:

 NSURLSessionTask * task = [[AFHTTPSharedClient sharedHTTPClient] addMediaWithURI:self.filePath success:^(NSURLSessionDataTask *task, BOOL added) {
        if (added) {
            NSLog(@"Operation succ");
        }
        weakSelf.progressContainerView.hidden = YES;
    } orFailure:^(NSURLSessionDataTask *task, NSError *error) {
        weakSelf.progressContainerView.hidden = YES;
    }];
    self.progressContainerView.hidden = NO;
    [self.uploadProgressView setProgressWithUploadProgressOfTaskNSURLSessionUploadTask*)task animated:YES];


该方法直接调用:

session = [self POST:ApiPostURL parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
            [formData appendPartWithFileURL:[NSURL fileURLWithPath:mediaURI] name: ParameterMultimedia error:appendError];
        } success:^(NSURLSessionDataTask *task, id responseObject) {
            NSLog(@"%@", responseObject);
            if ([responseObject[@"status"] isEqualToString"ko"]) {
                NSError * error = [NSError errorWithDomain"it.share.auth" code:500 userInfo:nil];
                failure(task, error);
                return ;
            }
            success (task, YES);
        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            NSLog(@"%@", error);
            failure(task, error);
        }];

一旦我附加了进度 View ,如果我 checkin 它的方法,我可以确定它正确地观察了方法中的任务进度:

- (void)observeValueForKeyPathNSString *)keyPath
                      ofObjectid)object
                        change__unused NSDictionary *)change
                       contextvoid *)context <br>

问题是 if ([object countOfBytesExpectedToSend] > 0) 总是 false 因为 countOfBytesExpectedToSend 为 0,阅读有关 NSURLSession 的文档苹果表示:

Discussion The URL loading system can determine the length of the upload data in three ways:

From the length of the NSData object provided as the upload body. From the length of the file on disk provided as the upload body of an upload task (not a download task). From the Content-Length in the request object, if you explicitly set it

如果我从请求 header Content-Leght 的请求中打印值,我会得到一个有效值:

"Accept-Language" = "it;q=1, en;q=0.9, fr;q=0.8, de;q=0.7, ja;q=0.6, nl;q=0.5";
"Content-Length" = 232172;
"Content-Type" = "multipart/form-data; boundary=Boundary+357828FACC07BFAC";
"User-Agent" = "XXXXX/1.0 (iPad; iOS 7.1; Scale/1.00)";

我不明白为什么总是返回等于 0 的值。



Best Answer-推荐答案


Googleing,githubbing,我找到了答案,本质上这是 NSURLSession 的“功能”,当您使用 uploadstream 创建 session 时,任务会接管您设置的标题。由于在流中没有真正的内容大小,如果我们设置一些东西,任务将重写它。
幸运的是 NSURLSession 有两个请求属性 currentRequest(被覆盖的)和 originalRequest。原始请求将继续保留我们的 Content-Length
我对 UIProgressView+AFNetworking 类别做了一些修改,以使其使用设置的内容长度工作,最好再检查一下是否有流。

- (void)observeValueForKeyPathNSString *)keyPath
                      ofObjectid)object
                        change__unused NSDictionary *)change
                       contextvoid *)context
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
    if (context == AFTaskCountOfBytesSentContext || context == AFTaskCountOfBytesReceivedContext) {
        if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) {

            //upload content length issue
//            if ([object countOfBytesExpectedToSend] > 0) {
            NSInteger byteToSend = [[[object originalRequest] valueForHTTPHeaderField"Content-Length"] integerValue];
            if (byteToSend){
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self setProgress:[object countOfBytesSent] / (byteToSend * 1.0f) animated:self.af_uploadProgressAnimated];
//                    [self setProgress:[object countOfBytesSent] / ([object countOfBytesExpectedToSend] * 1.0f) animated:self.af_uploadProgressAnimated];
                });
            }
        }

        if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) {
            if ([object countOfBytesExpectedToReceive] > 0) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self setProgress:[object countOfBytesReceived] / ([object countOfBytesExpectedToReceive] * 1.0f) animated:self.af_downloadProgressAnimated];
                });
            }
        }

        if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) {
            if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) {
                @try {
                    [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))];

                    if (context == AFTaskCountOfBytesSentContext) {
                        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))];
                    }

                    if (context == AFTaskCountOfBytesReceivedContext) {
                        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))];
                    }
                }
                @catch (NSException * __unused exception) {}
            }
        }
    }
#endif
}

关于ios - AFNetworking 2.0 + UIProgressView 如何正确显示上传 session 的进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23193983/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap