Блок неявно сохраняет "self"; явно упоминайте "self", чтобы указать, что это предполагаемое поведение

учитывая следующее:

- (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];
    });
}

за исключением того, что митимер-Ивар, что означает wself не имеет доступа к каким-либо свойствам.

Я думаю, мои вопросы:

  1. сделать / должен ли я уход?
  2. должен ли я объявить myTimer свойством?

Я использую ivars довольно много через мой код. Я просто добавил -Weverything флаг для моего проекта, чтобы увидеть, могу ли я найти какие-либо основные проблемы, и это, безусловно, самое распространенное предупреждение. У меня нет проблем с тем, чтобы пойти и исправить это, сделав мои свойства ivars, но я хочу убедиться, что я получу лучшее понимание, прежде чем я это сделаю.

5 ответов


замена myTimer by self->myTimer исправит ваше предупреждение.

когда вы используете iVar _iVar в коде компилятор заменит код на self->_iVar, и если вы используете его внутри блока, блок захватит себя вместо самого Ивара. Предупреждение заключается в том, чтобы убедиться, что разработчик понимает это поведение.


подробности

Xcode: 9.2

предупреждения в Objective-C Pods

у меня есть проект swift. Предупреждение Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior появляется, когда я использую Objective-C pods:

  • болты
  • FBSDKCoreKit
  • FBSDKLoginKit

enter image description here

Решение 1 (ручная)

CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO

решение 2 (автоматическое)

добавить в конец Файл контейнера:

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


для тех из вас, кто получает эти предупреждения из-за Bolts/FBSDKCoreKit/FBSDKLoginKit, вы должны избегать ответа Василия и вместо этого молчать предупреждения для этих конкретных зависимостей.

1

упомянуть каждый стручки вместо просто 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

или тишина все стручки, добавив в ваш файл контейнера это:

inhibit_all_warnings!

вывод

вы все равно получите предупреждения для вашего собственный код. Не получить их может быть проблематично в какой-то момент, поэтому я считаю, что это лучшее решение.

в следующий раз, когда вы обновите Facebook sdk, посмотрите, можете ли вы удалить inhibit_warnings: true или inhibit_all_warnings!.


недавно я столкнулся с той же проблемой, и ответ @Vasily Bodnarchuk кажется полезным.

однако в средах непрерывной интеграции невозможно изменить CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF флаг NO во время выполнения. Поэтому, чтобы изолировать проблему, я попытался проверить все зависимые драгоценные камни, установленные Cocoapods, и выяснил, что gem XCODEPROJ версии 1.5.7 устанавливает CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF до YES, когда pod install команда выполнена. Решение это вернуть XCODEPROJ в более ранней версии 1.5.1-исполнителями sudo gem install xcodeproj -v 1.5.1 После возврата просто выполните pod install и флаг будет не всегда.


Это решает мою проблему для 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];
       }

   });
}