首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用/测试子NSProgress实例的userInfo更改

如何使用/测试子NSProgress实例的userInfo更改
EN

Stack Overflow用户
提问于 2017-09-19 13:47:55
回答 1查看 1.2K关注 0票数 1

我正在一个库中实现NSProgress支持,我编写了一些单元测试来测试一切是否正常。虽然理想情况下,我希望能够传递一些额外的元数据(userInfo键不是由NSProgress本身使用,而是供我的API用户使用),但就目前而言,我只是想让localizedDescriptionlocalizedAdditionalDescription像文档所说的那样工作。由于我正在测试的方法从存档中提取文件,所以我将kind设置为NSProgressKindFile,并设置与文件操作相关联的各种键(例如NSProgressFileCompletedCountKey)。

当我观察到KVO对localizedDescription的更改时,我会看到这样的更新:

处理“测试文件A.txt” 处理“测试文件B.jpg” 处理“测试文件C.m4a”

当我停在一个断点上,并在worker po实例(下面的childProgress)上设置localizedDescription时,这实际上就是我所看到的。但是,当我的测试运行时,他们看到的只是下面的内容,这意味着它没有看到我设置的任何userInfo键:

0%已完成 0%已完成 53%已完成 100%完成 100%完成

看起来,我在子userInfo NSProgress 实例上设置的键并没有传递给它的父实例,尽管 fractionCompleted 是这样做的。我做错什么了吗?

下面我给出了一些抽象代码片段,但您也可以通过这些更改来自GitHub下载提交。如果您想要重现这种行为,请运行-[ProgressReportingTests testProgressReporting_ExtractFiles_Description]-[ProgressReportingTests testProgressReporting_ExtractFiles_AdditionalDescription]测试用例。

在我的测试用例类中:

代码语言:javascript
复制
static void *ProgressContext = &ProgressContext;

...

- (void)testProgressReporting {
    NSProgress *parentProgress = [NSProgress progressWithTotalUnitCount:1];
    [parentProgress becomeCurrentWithPendingUnitCount:1];

    [parentProgress addObserver:self
                     forKeyPath:NSStringFromSelector(@selector(localizedDescription))
                        options:NSKeyValueObservingOptionInitial
                        context:ProgressContext];

    MyAPIClass *apiObject = // initialize
    [apiObject doLongRunningThing];

    [parentProgress resignCurrent];
    [parentProgress removeObserver:self
                        forKeyPath:NSStringFromSelector(@selector(localizedDescription))];
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context
{
    if (context == ProgressContext) {
        // Should refer to parentProgress from above
        NSProgress *notificationProgress = object;
        
        [self.descriptionArray addObject:notificationProgress.localizedDescription];
    }
}

然后,在我被测试的班级里:

代码语言:javascript
复制
- (void) doLongRunningThing {
    ...
    NSProgress *childProgress = [NSProgress progressWithTotalUnitCount:/* bytes calculated above */];
    progress.kind = NSProgressKindFile;
    [childProgress setUserInfoObject:@0
                              forKey:NSProgressFileCompletedCountKey];
    [childProgress setUserInfoObject:@(/*array count from above*/)
                              forKey:NSProgressFileTotalCountKey];

    int counter = 0;

    for /* Long-running loop */ {
        [childProgress setUserInfoObject: // a file URL
                                  forKey:NSProgressFileURLKey];

        // Do stuff

        [childProgress setUserInfoObject:@(++counter)
                                  forKey:NSProgressFileCompletedCountKey];
        childProgress.completedUnitCount += myIncrement;
    }
}

在我增加childProgress.completedUnitCount时,这就是调试器中userInfo的样子。我设置的字段都表示为:

代码语言:javascript
复制
> po childProgress.userInfo

{
    NSProgressFileCompletedCountKey = 2,
    NSProgressFileTotalCountKey = 3,
    NSProgressFileURLKey = "file:///...Test%20File%20B.jpg"; // chunk elided from URL
}

当每个KVO通知返回时,notificationProgress.userInfo的外观如下:

代码语言:javascript
复制
> po notificationProgress.userInfo

{
}
EN

回答 1

Stack Overflow用户

发布于 2017-09-22 20:23:09

我想对@clarus的回答发表评论,但不会让我在评论中做可读的格式化。TL;DR -他们的观点一直是我的理解,在几年前我开始与NSProgress合作时,这就是我的痛处。

对于这种情况,我喜欢检查Swift基金会代码以获得实现提示。如果事情还没有完成的话,这也许并不是百分之百的权威,但是我喜欢看到一般的想法。

如果您查看setUserInfoObject(: forKey:)的实现,您可以看到该实现只是设置用户信息dict,而没有将任何内容传播到父节点。

相反,影响子部分已完成的显式回叫到(私有) _parent属性以指示其状态的更新应响应子级更改。

私有_updateChild(: from: to: portion:)似乎只关心更新已完成的部分,而不是任何与用户信息字典相关的内容。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46302206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档