57

実行時に最新のAPIを選択することで、10.4以降をサポートしています。

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
    [fileManager removeItemAtPath:downloadDir error:NULL];
else
    [fileManager removeFileAtPath:downloadDir handler:nil];

この場合、10.5以降が使用されremoveItemAtPath:error:、10.4が使用されますremoveFileAtPath:handler:。すばらしいですが、古いメソッドに対してコンパイラの警告が表示されます。

warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]

if([… respondsToSelector:@selector(…)]){ … } else { … }コンパイラ(Clang)がその行で警告しないようにヒントを与える構文はありますか?

そうでない場合、無視されるその行にタグを付ける方法はあり-Wdeprecated-declarationsますか?


いくつかの答えを見た後、コンパイラーを混乱させて、私が何をしているのかわからないようにすることは、有効な解決策ではないことを明確にしておきます。

4

5 に答える 5

118

Clangコンパイラのユーザーズマニュアルで、警告を無視できるを見つけました。

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)]) {
    [fileManager removeItemAtPath:downloadDir error:NULL];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [fileManager removeFileAtPath:downloadDir handler:nil];
#pragma clang diagnostic pop
}
于 2009-12-14T16:54:13.913 に答える
8

非推奨のメソッドを呼び出すために指定された別のファイルを宣言し、Xcodeでファイルごとのコンパイラフラグを無視するように設定でき-Wdeprecated-declarationsます。次に、そのファイルにダミー関数を定義して、非推奨のメソッドを呼び出すことができます。これにより、実際のソースファイルでの警告を回避できます。

于 2009-12-14T16:57:58.447 に答える
6

clangがこれをキャッチするのに十分賢いかどうかはわかりませんが、そうでない場合はperformSelector:withObject:withObject:、NSInvocationオブジェクトを使用または構築して呼び出すことができます。

于 2009-12-14T17:35:28.777 に答える
5

fileManagerにキャストするだけでidids任意のObjective-Cオブジェクトを参照できるため、コンパイラは1つで呼び出されるメソッドをチェックすることは想定されていません。

[(id)fileManager removeItemAtPath:downloadDir error:NULL];

警告やエラーを発生させるべきではありません。

もちろん、これにより他の問題が発生します。つまり、で呼び出されたメソッドのコンパイル時チェックがすべてid失われます。したがって、メソッド名などのスペルを間違えると、そのコード行が実行されるまでキャッチされません。

于 2009-12-14T20:33:33.230 に答える
3

コンパイラを「混乱させる」何らかの形を無効な解決策と見なす場合は、おそらく警告に耐えなければならないでしょう。(私の本では、警告を取り除く方法を尋ねる場合、贈り物の馬を口の中で見て、期待したように見えないという理由だけで何かが無効であると言うのは賢明ではありません。)

実行時に機能する答えには、動的ディスパッチで発生している操作をマスクして、コンパイラーが非推奨の呼び出しについて文句を言わないようにすることが含まれます。このアプローチが気に入らない場合は、Xcodeプロジェクトまたはターゲット設定で「非推奨の関数について警告」をオフにすることができますが、これは一般的に悪い考えです。非推奨のAPIについて知りたいが、この場合は警告なしに使用したい。これを行うには簡単な方法と難しい方法があり、それらすべてが何らかの形で「無効」であるとみなされる可能性がありますが、それでも効果が妨げられることはなく、正しい方法でもあります。;-)

警告を回避し、実行時に選択する方法の1つは、objc_msgSend()直接使用することです。

objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];

これはとにかくObjective-Cランタイムがカバーの下で行うことであり、最小限の手間で必要な結果を達成する必要があります。わかりやすくするために、元の行をその上にコメントのままにしておくこともできます。ドキュメントには、「コンパイラはメッセージング関数への呼び出しを生成します。作成したコードで直接呼び出すことは絶対にしないでください」と書かれていることは知っています。ルールを曲げても大丈夫なのはあなただけです。

于 2009-12-15T16:32:09.523 に答える