在Xcode中设置了一堆curl_easy_setopt函数,用于将文件上传到服务器/ API,并且(经过大量的试验和错误)它都像魅力一样。经过其他几个Q& As之后我还设法设置了一个简单的CURLOPT_PROGRESSFUNCTION,如下所示:
static int my_progress_func(void *p,
double t,
double d,
double ultotal,
double ulnow)
{
printf("(%g %%)\n", ulnow*100.0/ultotal);
// globalProgressNumber = ulnow*100.0/ultotal;
return 0;
}
随着上传的进行,“0%.. 16%.. 58%.. 100%”输出到控制台;灿烂。 我无法做的是实际使用这个数据(globalProgressNumber),例如。对于我的NSProgressIndicator; CURL类型劫持我的应用程序,并且在进度完成之前不允许任何其他输入/输出。
我尝试从my_progress_func更新IBOutlets(例如[_myLabel setStringValue:globalProgressNumber];)但是静态int函数不允许这样做。
也不允许[自我],因此无法发布到NSNotificationCenter:
[[NSNotificationCenter defaultCenter]
postNotificationName:@"Progressing"
object:self];
我的curl函数从我的主类/窗口(NSPanel)运行。
关于如何在我的.xib上实现实时/更新元素的任何好建议?
答案 0 :(得分:1)
CURL [...]在进度完成之前不允许任何其他输入/输出。
你是从主线程调用curl_easy_perform
吗?如果是,则不应该这样做,因为此函数是同步的,即它会在传输完成之前阻塞。
换句话说,长时间运行的任务(例如网络I / O)必须在单独的线程上运行,而UI代码(例如更新标签的文本)必须在主线程上运行。
如何实现实时/更新元素
你一定要注意在一个单独的线程中执行卷曲传输。
通过使用自定义协议将其包装到NSOperation
以通知代表进度(例如视图控制器),可以轻松实现这一点:
NSOperationQueue
,CURLOPT_PROGRESSDATA
curl选项将操作对象设置为不透明对象。通过这样做,每次调用progress函数时,您都可以通过强制转换void *clientp
不透明指针来检索操作对象。然后通知代理当前进度在主线程中(例如performSelectorOnMainThread
),以确保您可以执行UI更新,例如刷新NSProgressIndicator
。作为NSOperation
的替代方案,您还可以使用Grand Central Dispatch(GCD)和阻止。如果可能,我强烈建议您使用BBHTTP,这是iOS 5+和OSX 10.7+的libcurl客户端(BBHTTP使用GCD和块)。
仅供参考:这是一个example from BBHTTP,它说明了如何使用上传进度块轻松执行文件上传 - 这适用于iOS,但应该可以直接重用于OS X.