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

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

- (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 как свойство?

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

Ответы

Ответ 1

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

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

Ответ 2

Подробнее

Xcode: 9,2, 10,2, 11,0 (11A420a)

Предупреждения в модулях Objective-C

У меня быстрый проект. Предупреждение Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior появляется при использовании модулей Objective C:

  • Болты
  • 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

Ответ 3

Для тех из вас, кто получает эти предупреждения из-за Bolts/FBSDKCoreKit/FBSDKLoginKit, вы должны избегать ответа Василия и вместо этого 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!

Вывод

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

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

Ответ 4

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

   });
}

Ответ 5

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

Однако в средах с непрерывной интеграцией невозможно изменить флаг CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF на NO во время выполнения. Поэтому, чтобы изолировать проблему, которую я попытался проверить все зависимые GEMS, установленные 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 и флаг будет всегда установлен как NO.

Ответ 6

Ребята, пожалуйста, не заглушайте предупреждение, как уже упоминали другие!

Это указывает на проблему в вашем коде с сохранением объекта, которая может привести к серьезным проблемам с памятью, особенно когда этот объект большой. У меня были сохранены целые контроллеры представления, и вы, как правило, никогда не должны игнорировать большинство предупреждений, кроме, возможно, соглашений кода.

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    __strong typeof(self) strongSelf = weakSelf;
    strongSelf->myClassesIVar --;
});