Given the following:
- (void) someMethod
{
dispatch_async(dispatch_get_main_queue(), ^{
myTimer = [NSTimer scheduledTimerWithTimeInterval: 60
target: self
selector: @selector(doSomething)
userInfo: nil
repeats: NO];
});
}
Where myTimer is declared in a private interface:
@interface MyClass()
{
NSTimer * myTimer;
}
@end
How would one fix the following warning:
Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior
From what I have found so far, most suggestions involve putting something such as:
- (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];
});
}
Except, that myTimer is an ivar, meaning wself
does not have access to any properties.
I guess my questions are:
- Do/should I care?
- Should I declare myTimer as a property?
I use ivars quite a bit through my code. I just added the -Weverything
flag to my project to see if I can find any underlying issues and this is by far the most common warning. I have no problem going though and fixing it by making my ivars properties, but I want to make sure I get a better understanding before I do that.
Replacing myTimer
by self->myTimer
would fix your warning.
When you use an iVar _iVar
in the code, the compiler will replace the code by self->_iVar
, and if you use it inside a block, the block will capture self instead of the iVar itself. The warning is just to make sure the the developer understand this behaviour.
Details
Xcode: 9.2
Warnings in Objective-C Pods
I have swift project. Warning Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior
appears when I use Objective-C pods:
- Bolts
- FBSDKCoreKit
- FBSDKLoginKit
Solution 1 (manual)
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO
Solution 2 (automatic)
Add to the end of your 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
Results
For those of you getting these warnings because of Bolts
/FBSDKCoreKit
/FBSDKLoginKit
, you should avoid Vasily's answer and instead silence the warnings for those specific dependencies.
Option 1
Mention each pods instead of just FacebookCore and add inhibit_warnings: true
pod 'FacebookCore', inhibit_warnings: true
pod 'Bolts', inhibit_warnings: true
pod 'FBSDKCoreKit', inhibit_warnings: true
pod 'FBSDKLoginKit', inhibit_warnings: true
Option 2
Or silence all pods, by adding to your Podfile this:
inhibit_all_warnings!
Conclusion
You'll still get warnings for your own code. Not getting those could be problematic at some point, that's why I believe it's a better solution.
Next time you update the Facebook sdk, see if you can remove the inhibit_warnings: true
or inhibit_all_warnings!
.
Recently I faced the same issue and @Vasily Bodnarchuk answer seems to be helpful.
However in Continuous integration environments its not possible to change the CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF
flag to NO
at run time.
So in order to isolate the issue i tried by checking all the dependent GEMS installed by Cocoapods and figured out that gem XCODEPROJ version 1.5.7 sets the CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF
to YES
whenever pod install
command is executed.
The solution for this is reverting the XCODEPROJ to earlier version 1.5.1 by executing sudo gem install xcodeproj -v 1.5.1
Once reverted just execute pod install
and the flag will be set to NO always.
This fixes my problem for 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];
}
});
}