Блок неявно сохраняет "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
не имеет доступа к каким-либо свойствам.
Я думаю, мои вопросы:
- сделать / должен ли я уход?
- должен ли я объявить 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
Решение 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
результаты
для тех из вас, кто получает эти предупреждения из-за Bolts
/FBSDKCoreKit
/FBSDKLoginKit
, вы должны избегать ответа Василия и вместо этого молчать предупреждения для этих конкретных зависимостей.
упомянуть каждый стручки вместо просто 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];
}
});
}