web-dev-qa-db-ja.com

Objective-Cの@availableキーワードの否定

here のように、現在のデバイスのiOSバージョンが特定のバージョンよりも低い場合にのみ、コードを実行します。 Appleによって提供されるコード例は次のようになります:

if (@available(iOS 10.0, *)) {
  // iOS 10.0 and above
} else {
  // below 10.0
}

ただし、現在のiOSバージョンが特定のバージョンよりも低い場合にのみコードを実行するシナリオがあります。次のコードが機能すると想定しました。

if (!@available(iOS 10.0, *)) {
  // below 10.0
}

しかし、これは機能しないようで、Xcodeから次の警告が表示されます。

@available does not guard availability here; use if (@available) instead

ここ は、私が見ている診断を追加したLLVMコミットです。

その問題には2つのフォールバックが考えられます。

  1. ifブロックにコードを追加せずにif-elseバリアントを使用します(あまりエレガントではありません)。
  2. -[NSProcessInfo isOperatingSystemAtLeastVersion:]などの古いアプローチを引き続き使用します。

@availableを使用する別の目的の方法はありますか?

15
StatusReport

@availableの考え方は、特定のシステムでのみ利用可能なAPIを使用することです。他のシステムでは、機能がアプリに欠落しているか、代替機能を提供しています。特定のOSバージョン以外のコードが必要ない場合に、以下を使用する場合の正しい使用方法は次のとおりです。

if (@available(iOS 10.0, *)) {
    // Happens automatically on on iOS 10 and beyond
} else {
    someOtherCode();
}

その理由は、コンパイラが@availableで保護されたコードに対して特別な魔法を実行する必要がある場合があるため、これが当てはまる場合を明確に認識する必要があるためです。したがって、実際には明示的に検索します

if (@available(...)) {

スペースと改行のバリエーションのみが許可されています。はい、1つではない(!)は本当に複雑であるだけでなく、どこに線を引くのでしょうか。何について:

if ((todayIsTuesday() && @available(iOS 9.0, *)) 
    || (self.theWeatherIsNice && !@available(iOS 11.0, *)) {

したがって、コンパイラーにコードを強制的に2つのセクションに分割させる単純なステートメントのみが許可され、常に1つのセクションのみが確実に実行されます。もちろん、「残り」は再び細分割でき、else ifが許可されます。 elseセクションのみが欠落している場合に自動生成できるため、次のように記述します。

if (@available(...)) {
    someCode();
} // There is no else

コンパイラーも同じです。

if (@available(...)) {
     someCode();
} else {
    // Nothing to do here
}
6
Mecki

アプリケーション全体で使用できる独自のカスタムマクロを定義できます。例:-

#define isIOS11() ([[UIDevice currentDevice].systemVersion doubleValue]>= 11.0 && [[UIDevice currentDevice].systemVersion doubleValue] < 12.0)

または

#define SinceIOS9_2 ([[UIDevice currentDevice].systemVersion doubleValue]>= 4.2 && [[UIDevice currentDevice].systemVersion doubleValue] < 9.2)

以下のように使用してください:

if (isIOS11()) {
    // Do something for iOS 11 
} else {
    // Do something iOS Versions below 11.0
}

これで問題が解決するかどうかお知らせください。

1
Jitendra
if (@available ...) {
   ...
} else {
   ...
}

許可される唯一のフォームです。 if-partとelse-partには異なるルールが適用されるため、このようにする必要があります。 if部分では、1つのSDKで利用可能なメソッドを呼び出すことができ、else部分では、別のSDKからのメソッドを呼び出すことができます。同じ呼び出しは、あるブランチでは合法で別のブランチでは違法になる場合があります。または、あるブランチでは非推奨になり、別のブランチでは非推奨になります。

1
gnasher729