Objective-Cには@available
表現XCode 9+ / LLVM 5+ では、特定の OS バージョン以上に対してコード ブロックをガードできるため、その OS バージョンでのみ使用可能な API を使用する場合に、ガードされていない可用性の警告が発行されなくなります。
問題は、この可用性ガードは、 の条件で唯一の式である場合にのみ機能することですif
。他のコンテキストで使用すると、警告が表示されます。
@available does not guard availability here; use if (@available) instead
たとえば、可用性チェックを他の条件と AND で結合しようとしても機能しませんif
。
if (@available(iOS 11.0, *) && some_condition) {
// code to run when on iOS 11+ and some_condition is true
} else {
// code to run when on older iOS or some_condition is false
}
if
ブロック内または still 内で iOS 11 API を使用するコードは、some_condition
それらのコード部分に iOS 11 以降でのみアクセスできることが保証されているにもかかわらず、保護されていない可用性の警告を生成します。
これを 2 つのネストされた に変更することもできますif
が、その場合、else
コードを複製する必要があり、これは良くありません (特にコードが大量にある場合)。
if (@available(iOS 11.0, *)) {
if (some_condition) {
// code to run when on iOS 11+ and some_condition is true
} else {
// code to run when on older iOS or some_condition is false
}
} else {
// code to run when on older iOS or some_condition is false
}
else
ブロック コードを匿名関数にリファクタリングすることで重複を回避できますが、else
の前にブロックを定義する必要がありif
、コード フローがわかりにくくなります。
void (^elseBlock)(void) = ^{
// code to run when on older iOS or some_condition is false
};
if (@available(iOS 11.0, *)) {
if (some_condition) {
// code to run when on iOS 11+ and some_condition is true
} else {
elseBlock();
}
} else {
elseBlock();
}
誰かもっと良い解決策を思いつくでしょうか?
ベストアンサー1
関数の途中に複雑な条件コードがあり、フローが複雑になる場合は、いつものように、それを別の関数に持ち上げます。
- (void)handleThing {
if (@available(iOS 11.0, *)) {
if (some_condition) {
// code to run when on iOS 11+ and some_condition is true
return;
}
}
// code to run when on older iOS or some_condition is false
}
または、チェックを汎用コードに昇格します (Josh Caswell のコードを参照してください。これは私が最初に書いたものよりも優れています)。