web-dev-qa-db-fra.com

Block conserve implicitement «soi»; mentionner explicitement «soi» pour indiquer qu'il s'agit d'un comportement voulu

Compte tenu des éléments suivants:

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

Où myTimer est déclaré dans une interface privée:

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

Comment corriger l'avertissement suivant:

Block conserve implicitement "soi"; mentionner explicitement "soi" pour indiquer qu'il s'agit d'un comportement voulu

D'après ce que j'ai trouvé jusqu'à présent, la plupart des suggestions impliquent de mettre quelque chose comme:

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

Sauf que myTimer est un ivar, ce qui signifie que wself n'a accès à aucune propriété.

Je suppose que mes questions sont:

  1. Dois/devrais-je m'en soucier?
  2. Dois-je déclarer myTimer comme une propriété?

J'utilise beaucoup d'ivars via mon code. Je viens d'ajouter le -Weverything signaler à mon projet pour voir si je peux trouver des problèmes sous-jacents et c'est de loin l'avertissement le plus courant. Je n'ai aucun problème à le faire et à le réparer en faisant mes propriétés d'ivars, mais je veux m'assurer d'avoir une meilleure compréhension avant de le faire.

46
Kyle

Remplacement de myTimer par self->myTimer résoudrait votre avertissement.

Lorsque vous utilisez un iVar _iVar dans le code, le compilateur remplacera le code par self->_iVar, et si vous l'utilisez dans un bloc, le bloc se capturera lui-même au lieu de l'iVar lui-même. L'avertissement est juste pour s'assurer que le développeur comprend ce comportement.

60
bsarr007

Détails

Xcode: 9.2, 10.2

Avertissements dans les pods Objective-C

J'ai un projet Swift. Avertissement Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior apparaît lorsque j'utilise des modules Objective-C:

  • Boulons
  • FBSDKCoreKit
  • FBSDKLoginKit

enter image description here

Solution 1 (manuel)

CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO

Solution 2 (automatique)

Ajoutez à la fin de votre 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

Résultats

enter image description here

67
Vasily Bodnarchuk

Pour ceux d'entre vous qui reçoivent ces avertissements en raison de Bolts/FBSDKCoreKit/FBSDKLoginKit, vous devez éviter la réponse de Vasily et au lieu de cela, mettre en garde les avertissements pour ces dépendances spécifiques.

Option 1

Mentionnez chaque module au lieu de simplement FacebookCore et ajoutez 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

Ou désactivez tous les pods en ajoutant à votre podfile ceci:

inhibit_all_warnings!

Conclusion

Vous recevrez toujours des avertissements pour votre propre code. Ne pas les obtenir pourrait être problématique à un moment donné, c'est pourquoi je pense que c'est une meilleure solution.

La prochaine fois que vous mettrez à jour le SDK Facebook, voyez si vous pouvez supprimer le inhibit_warnings: true ou inhibit_all_warnings!.

15
Nycen

Cela résout mon problème pour 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];
       }

   });
}
3
Pooja Gupta

Récemment, j'ai rencontré le même problème et la réponse @Vasily Bodnarchuk semble être utile.

Cependant, dans les environnements d'intégration continue, il n'est pas possible de changer l'indicateur CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF En NO au moment de l'exécution. Donc, afin d'isoler le problème, j'ai essayé en vérifiant tous les GEMS dépendants installés par Cocoapods et j'ai compris que la gemme XCODEPROJ version 1.5.7 définit le CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF Sur YES chaque fois que pod install la commande est exécutée. La solution à cela est de XCODEPROJ à la version antérieure 1.5.1 en exécutant Sudo gem install xcodeproj -v 1.5.1 Une fois rétabli, exécutez simplement pod install et l'indicateur sera toujours défini sur NO.

2
bhuvan