web-dev-qa-db-ja.com

ブロックは暗黙的に「自己」を保持します。これが意図された動作であることを示すために明示的に「自己」に言及する

次の場合:

- (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

次の警告をどのように修正しますか:

ブロックは暗黙的に「自己」を保持します。これが意図された動作であることを示すために明示的に「自己」に言及する

私がこれまでに発見したことから、ほとんどの提案には次のようなものを含めることが含まれます。

- (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をプロパティとして宣言する必要がありますか?

私はコードを通してivarをかなり使います。 -Weverythingプロジェクトにフラグを立てて、根本的な問題を見つけることができるかどうかを確認します。これは、最も一般的な警告です。私はivarsプロパティを作成して問題を修正しましたが、それを行う前に、より良い理解を得ることを確認したいと思います。

46
Kyle

myTimerself->myTimerに置き換えると、警告が修正されます。

コードでiVar _iVarを使用すると、コンパイラはコードをself->_iVarに置き換えます。ブロック内で使用すると、ブロックはiVar自体ではなくselfをキャプチャします。警告は、開発者がこの動作を理解していることを確認するためのものです。

60
bsarr007

詳細

Xcode:9.2、10.2

Objective-Cポッドの警告

Swiftプロジェクト。警告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(自動)

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

結果

enter image description here

67

Bolts/FBSDKCoreKit/FBSDKLoginKitが原因でこれらの警告が表示される場合、Vasilyの回答を避け、代わりにそれらの特定の依存関係の警告を黙らせる必要があります。

オプション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

または、Podfileに以下を追加して、すべてのポッドを無音にします。

inhibit_all_warnings!

結論

独自のコードに対する警告は引き続き表示されます。それらを取得しないことは、ある時点で問題になる可能性があります。だからこそ、より良い解決策だと思います。

次回Facebook SDKを更新するときは、inhibit_warnings: trueまたはinhibit_all_warnings!を削除できるかどうかを確認してください。

15
Nycen

これにより、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

最近、私は同じ問題に直面し、@ Vasily Bodnarchukの回答が役立つようです。

ただし、継続的統合環境では、実行時にCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELFフラグをNOに変更することはできません。したがって、問題を特定するために、Cocoapodsによってインストールされたすべての依存GEMSをチェックしてみました。gemXCODEPROJバージョン1.5.7は、CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELFコマンドが実行されるたびにpod installYESに設定します。これに対する解決策は、 XCODEPROJ Sudo gem install xcodeproj -v 1.5.1を実行することにより、以前のバージョン1.5.1に戻ります。復帰したら、pod installを実行するだけで、フラグは常にNOに設定されます。

2
bhuvan