根据我看到的文档NSProgress,-[NSProgress localizedAdditionalDescription]可以报告下载速度和剩余时间,例如:
1.61 GB的3.22 GB(2 KB /秒) - 剩余2分钟
但是,当我NSProgress将a 关联到a 时,我无法获得这些细节NSURLSessionDownloadTask.这是我的代码:
Downloader.h
@interface Downloader : NSObject
@property NSProgress *overallProgress;
-(void)startDownload;
@end
Run Code Online (Sandbox Code Playgroud)
Downloader.m
- (void)startDownload {
self.overallProgress = [NSProgress progressWithTotalUnitCount:100];
[self.overallProgress setKind:NSProgressKindFile];
[self.overallProgress setUserInfoObject:NSProgressFileOperationKindKey forKey:NSProgressFileOperationKindDownloading];
[self.overallProgress becomeCurrentWithPendingUnitCount:100];
[self work1];
[self.overallProgress resignCurrent];
}
- (void)work1 {
NSProgress *firstTaskProgress = [NSProgress progressWithTotalUnitCount:1];
[firstTaskProgress setKind:NSProgressKindFile];
[firstTaskProgress setUserInfoObject:NSProgressFileOperationKindKey forKey:NSProgressFileOperationKindDownloading];
NSURL *downloadURL = [NSURL URLWithString:@"http://ipv4.download.thinkbroadband.com/200MB.zip"];
NSURL *destinationDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSURL *destinationURL = …Run Code Online (Sandbox Code Playgroud) 我有一个由几个子任务组成的大任务.我想为这项重大任务添加进度报告.
为了我想要使用NSProgress,并根据类文档,我可以通过使用其子 - 父机制来做这种子任务进展.
所以为了简化它,让我说我有一个由一个子任务组成的大任务(当然在现实生活中会有更多的子任务).这就是我所做的:
#define kFractionCompletedKeyPath @"fractionCompleted"
- (void)runBigTask {
_progress = [NSProgress progressWithTotalUnitCount:100]; // 100 is arbitrary
[_progress addObserver:self
forKeyPath:kFractionCompletedKeyPath
options:NSKeyValueObservingOptionNew
context:NULL];
[_progress becomeCurrentWithPendingUnitCount:100];
[self subTask];
[_progress resignCurrent];
}
- (void)subTask {
NSManagedObjectContext *parentContext = self.managedObjectContext; // self is AppDelegate in this example
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:parentContext];
[bgContext performBlockAndWait:^{
NSInteger totalUnit = 1000;
NSInteger completedUnits = 0;
NSProgress *subProgress = [NSProgress progressWithTotalUnitCount:totalUnit];
for (int i=0; i < totalUnit; i++) {
// run some …Run Code Online (Sandbox Code Playgroud) 我一直在调查,NSProgress但发现现有的文档,课程参考和教程缺乏.我主要想知道我的NSProgress是否适用于我的用例.类引用文档或者引用suboperations或者subtasks,我可能会弄错,但我解释suboperations为NSOperation管理一组其他的情况NSOperations.我的用例的一个例子如下:
Upload All Items in Group为存在的每个组创建操作.NSOperationQueue.Upload All Items in Group操作都将Upload Item为其组中的每个项目创建一个操作.这些都被添加到NSOperationQueue由操作管理的中.我本来希望NSProgress支持这一点,并允许我将进度从嵌套操作(Upload Item操作)传播到父操作,然后最终传播到主线程和UI.但是我很难实现这一点,似乎NSProgress对于在一个后台线程上执行所有代码的长操作意味着更多,但是有单独的"部分"可以很容易地确定何时进行了进展,如果这是在这种情况下,使用该术语suboperation有点误导,因为它会让人联想到嵌套的使用NSOperations.
感谢您提供的任何帮助,如果需要其他详细信息,请与我们联系.
multithreading objective-c nsoperation nsoperationqueue nsprogress
说我有一些NSProgress对象的层次结构.为简单起见,请说2个孩子的根进度.如果已经开始进度,我可以在层次结构中添加另一个子进程并期望正确的事情发生吗?例如,假设我开始与2个孩子,所以totalUnitCount根是2和pendingUnitCount是2.一旦第一个孩子完成,根本进展' fractionCompleted将是0.5.如果我然后添加另一个子进程,则根进度' fractionCompleted会~0.33按照我的意愿更新到,但是根目录totalUnitCount仍然保留2,以及pendingUnitCount.我可以totalUnitCount手动更新,但这会抛出root fractionCompleted.此外,似乎没有办法更新pendingUnitCount没有调用becomeCurrentWithPendingUnitCount:.是NSProgress不适合这种用途的或者是有一个"正确"的方式做到这一点?
我的用例是我有一个可以将文件上传到远程服务器的应用程序.用户可以选择一些文件并点击按钮开始上传它们.在他们上传时,用户可以看到上传作业的整体进度.现在,如果用户想要在上传已经进行时选择要上传的更多照片,我想更新进度以反映新的总数.例如,他目前正在上传2个文件,1个已经完成,当他们上传时,他还增加了2个上传文件.进展应该自我调整.现在总单位数应为4,并且还有3个项目要上传.对我来说这似乎是一个常见的用例.
这是我用动态扩展NSProgress层次结构编写的单元测试.下面测试中的所有断言都会通过,但是如果你检查根目录,totalUnitCount那么它总是保持为2,并且似乎没有办法告诉根目录进度还有多少项目需要完成.UI的进度是UI会观察到的,因此重要的是层次结构中更深层次的变化会传播,包括totalUnitCount等等.
- (void)testDynamicNSProgress
{
NSProgress *root = [NSProgress progressWithTotalUnitCount:2];
[root becomeCurrentWithPendingUnitCount:2];
NSProgress *child1 = [NSProgress progressWithTotalUnitCount:1];
NSProgress *child2 = [NSProgress progressWithTotalUnitCount:1];
XCTAssertEqual(root.totalUnitCount, 2);
XCTAssertEqual(root.completedUnitCount, 0);
child1.completedUnitCount++;
XCTAssertEqual(ceil(root.fractionCompleted * 100), 50);
NSProgress *child3 = [NSProgress progressWithTotalUnitCount:1];
NSProgress *child4 = …Run Code Online (Sandbox Code Playgroud) 我使用 NSProgress 来通知复杂任务的进度(该任务由许多子任务组成,可以由其他子任务组成)。
我在 startTask 方法中创建主要进度:
- (void)_startTask
{
_progress = [NSProgress progressWithTotalUnitCount:100]; //sometimes crash is here
<...>
}
Run Code Online (Sandbox Code Playgroud)
没有当前进度:
(lldb) po [NSProgress currentProgress]
nil
有时我会因为奇怪的 stackTrace 崩溃:
0:0x000000018539a7e8在object_isClass()
1:0x0000000186b39fe0在KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED()
2:0x0000000186b384bc在
NSKeyValueWillChangeWithPerThreadPendingNotifications()
3:0x0000000186cac9c0在- [NSProgress _setValueForKeys:settingBlock:]()
4:0x0000000186cacc7c在- [NSProgress setTotalUnitCount:]()
5:0x0000000186cab718在 +[NSProgress progressWithTotalUnitCount:] ()
此代码在 mainThread 中执行。
为什么会发生这种情况,我可以做些什么来避免这种情况?