【问题标题】:Strange retain cycle warning in unit tests in XcodeXcode 单元测试中出现奇怪的保留周期警告
【发布时间】:2016-05-03 08:07:23
【问题描述】:

我有一项服务,目前正在为其编写单元测试。代码按预期工作,但我收到一个奇怪的保留周期警告。

[self.myService doSomethingCoolWithCompletionBlock:^(MyResponseObject *obj) {
    XCTAssertNil(obj, @"obj should be nil");
}];

XCTAssertNil(obj, @"obj should be nil"); 行在 Xcode 中显示警告 Capturing 'self' strongly in this block is likely to lead to a retain cycle

如果我将代码更改为以下内容,则会删除警告:

__weak MyService *weakService = self.myService;
[weakService doSomethingCoolWithCompletionBlock:^(MyResponseObject *obj) {
    XCTAssertNil(obj, @"obj should be nil");
}];

我在其他单元测试中使用self.someService,从来没有遇到过这个问题。有没有人经历过这种情况?

编辑

我有另一个测试具有以下内容:

[self.myService doSomethingElseCoolWithCompletionBlock:(NSArray *results) {
    XCTestAssertNotNil(results, @"results should not be nil");
}];

这并没有给我一个警告。我看到的唯一区别是这是检查数组,另一个是检查特定类型的对象。

【问题讨论】:

    标签: ios objective-c xcode unit-testing


    【解决方案1】:

    断言它是宏并且在内部使用了self。 所以你需要创建一个名为 self 的局部变量。

    __weak id weakSelf = self;
    self.fooBlock = ^{
        id self = weakSelf;
        XCTAssert(YES);
    };
    

    【讨论】:

    • 谢谢,这似乎已经解决了警告。仍然没有解释为什么在其他测试中没有为其他 NSAssert 显示警告。你能详细说明一下吗?
    • 我尝试过,但是我的英语在这个时候不允许我说出我的全部想法(对不起)。在这种情况下,您使用块(myService 保留块,自我保留 myService)并在内部使用 assert。断言它是一个宏(#define),这个宏将在编译时粘贴到代码中。所以你的街区里面有自我。并且将是关系 = self -> myService -> block -> self。可能其他测试没有这个关系?
    • 谢谢。这就说得通了。我添加了一个我拥有的另一个测试的示例,它不会引发警告。有什么想法吗?
    • 如果你没有警告它并不意味着你的代码是清楚的((我不知道你为什么没有警告(也许它不需要?),但你应该知道什么所有断言都在内部使用变量self。但块内的每个self并不是意味着保留周期。例如,此代码没有保留周期,因为块在堆栈内存中。
    • 您可以设置习惯使用弱自用宏@weakify(self) 外部块和@strongify(self) 内部。它不会删除能力保留周期,但会减少它。
    【解决方案2】:

    不要这样做:

    @interface MyCoolTests : XCTestCase
    
    @property (retain) id myService;
    
    @end
    
    @implementation MyCoolTests
    
    -(void)testCoolness{
      self.myService = [MyService new];
    
      self.myService.callback = ^{
        XCTAssert(YES);
      };
      // ...
    }
    
    @end
    

    这样做:

    @interface MyCoolTests : XCTestCase
    
    
    @end
    
    @implementation MyCoolTests
    
    -(void)testCoolness{
      id myService = [MyService new];
    
      myService.callback = ^{
        XCTAssert(YES);
      };
      // ...
    }
    
    @end
    

    这是 XCTTestCase 的一个限制,在使用 setup 方法时可能会引起人们的注意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多