Block隐含地保留了“自我”;明确提到'self'来表明这是预期的行为

时间:2014-02-05 12:45:37

标签: objective-c macos objective-c-blocks

鉴于以下内容:

- (void) someMethod
{
    dispatch_async(dispatch_get_main_queue(), ^{
        myTimer = [NSTimer scheduledTimerWithTimeInterval: 60
                                                           target: self
                                                         selector: @selector(doSomething)
                                                         userInfo: nil
                                                          repeats: NO];
    });
}

在私有界面中声明myTimer的地方:

@interface MyClass()
{
    NSTimer * myTimer;
}
@end

如何修复以下警告:

Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

从我到目前为止发现的内容来看,大多数建议都涉及到如下内容:

- (void) someMethod
{
    __typeof__(self) __weak wself = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        wself.myTimer = [NSTimer scheduledTimerWithTimeInterval: 60
                                                           target: self
                                                         selector: @selector(doSomething)
                                                         userInfo: nil
                                                          repeats: NO];
    });
}

除此之外,myTimer是一个ivar,意味着wself无法访问任何属性。

我想我的问题是:

  1. 我/我应该关心吗?
  2. 我应该将myTimer声明为属性吗?
  3. 我在代码中使用了很多ivars。我刚刚将-Weverything标志添加到我的项目中,以查看是否可以找到任何潜在问题,这是迄今为止最常见的警告。我没有问题,并通过制作我的ivars属性来修复它,但我想确保在我这样做之前得到更好的理解。

5 个答案:

答案 0 :(得分:63)

详细

Xcode:9.2,10.2

Objective-C Pods中的警告

我有快速的项目。使用Objective-C pod时出现警告Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

  • 螺栓
  • FBSDKCoreKit
  • FBSDKLoginKit

enter image description here

解决方案1(手动)

CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO

解决方案2(自动)

  

添加到Podfile的末尾:

post_install do |installer|
      installer.pods_project.targets.each do |target|
           target.build_configurations.each do |config|
                config.build_settings['CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF'] = 'NO'
           end
      end
 end

结果

enter image description here

答案 1 :(得分:58)

myTimer替换self->myTimer会修复您的警告。

当您在代码中使用iVar _iVar时,编译器将用self->_iVar替换代码,如果您在块中使用它,则块将捕获self而不是iVar本身。警告只是为了确保开发人员理解这种行为。

答案 2 :(得分:15)

对于那些因Bolts / FBSDKCoreKit / FBSDKLoginKit而收到这些警告的人,您应该避免使用Vasily的答案,而是将这些特定依赖项的警告静音。 / p>

选项1

提及每个pod而不仅仅是FacebookCore并添加inhibit_warnings: true

pod 'FacebookCore', inhibit_warnings: true
pod 'Bolts', inhibit_warnings: true
pod 'FBSDKCoreKit', inhibit_warnings: true
pod 'FBSDKLoginKit', inhibit_warnings: true

选项2

或者通过添加到您的Podfile中来静音所有pod:

inhibit_all_warnings!

结论

您仍会收到有关自己代码的警告。没有那些可能会在某些时候出现问题,这就是为什么我认为它是一个更好的解决方案。

下次更新Facebook sdk时,看看您是否可以删除inhibit_warnings: trueinhibit_all_warnings!

答案 3 :(得分:3)

这解决了Xcode 9.3的问题

- (void) someMethod{

    __weak MyClass *wSelf = self;

    dispatch_async(dispatch_get_main_queue(), ^{

    MyClass *sSelf = wSelf;
    if(sSelf != nil){
        wself.myTimer = [NSTimer scheduledTimerWithTimeInterval: 60
                                                       target: self
                                                     selector:@selector(doSomething)
                                                     userInfo: nil
                                                      repeats: NO];
       }

   });
}

答案 4 :(得分:2)

最近我遇到了同样的问题,@ Vasily Bodnarchuk的回答似乎很有帮助。

但是在持续集成环境中,无法在运行时将CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF标志更改为NO。 因此,为了通过检查Cocoapods安装的所有依赖GEMS来解决问题,并且发现gem XCODEPROJ版本1.5.7在执行CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF命令时将YES设置为pod install 。 解决方案是通过执行sudo gem install xcodeproj -v 1.5.1 XCODEPROJ 恢复到早期版本1.5.1 一旦恢复,只需执行pod install,该标志将始终设置为NO。