use*_*008 21 objective-c ios availability xcode9
Objective-C 在XCode 9+/LLVM 5+中有一个@available表达式,它允许您将代码块保护到至少某个操作系统版本,这样如果您使用仅在该范围内可用的API,它就不会发出无人看守的可用性警告操作系统版本
问题在于,这种可用性保护是它只有在它是条件的唯一表达时才有效if.如果您在任何其他上下文中使用它,您会收到警告:
@available does not guard availability here; use if (@available) instead
Run Code Online (Sandbox Code Playgroud)
因此,例如,如果您尝试将可用性检查与以下其他条件进行对比,则它不起作用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
}
Run Code Online (Sandbox Code Playgroud)
任何在if块内或在块内使用iOS 11 API的代码some_condition都会产生无人看守的可用性警告,即使可以保证只有在iOS 11+上才能访问这些代码.
我可以把它变成两个嵌套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
}
Run Code Online (Sandbox Code Playgroud)
我可以通过将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();
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以提出更好的解决方案吗?
如果在函数中间有复杂的条件代码使流程变得复杂,那么就可以执行常规操作:将其提升到另一个函数中.
- (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
}
Run Code Online (Sandbox Code Playgroud)
或者你将检查提升为通用代码(参见Josh Caswell的;它比我最初编写的更好).
#define SUPPRESS_AVAILABILITY_BEGIN \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wunsupported-availability-guard\"")\
_Pragma("clang diagnostic ignored \"-Wunguarded-availability-new\"")
#define SUPPRESS_AVAILABILITY_END \
_Pragma("clang diagnostic pop")
#define AVAILABLE_GUARD(platform, os, future, conditions, codeIfAvailable, codeIfUnavailable) \
SUPPRESS_AVAILABILITY_BEGIN \
if (__builtin_available(platform os, future) && conditions) {\
SUPPRESS_AVAILABILITY_END \
if (@available(platform os, future)) { \
codeIfAvailable \
} \
} \
else { \
SUPPRESS_AVAILABILITY_END \
codeIfUnavailable \
}
Run Code Online (Sandbox Code Playgroud)
用法:
AVAILABLE_GUARD(iOS, 11.0, *, true, {
printf("IS AVAILABLE");
},
{
printf("NOT AVAILABLE");
});
Run Code Online (Sandbox Code Playgroud)
它通过使用@available作为具有附加可选条件的条件来工作.由于你失去了"守卫"的能力,我压制了无人防守的警告,但我还在那里添加了一个额外的守卫以保护其余的代码..这使得你基本上没有失去任何东西..
你得到了警卫,你得到了警告,你获得了额外的条件..
将 AND 封装在一个函数中怎么样?
typedef BOOL (^Predicate)();
BOOL elevenAvailableAnd(Predicate predicate)
{
if (@available(iOS 11.0, *)) {
return predicate();
}
return NO;
}
Run Code Online (Sandbox Code Playgroud)
那么你只有一个分支:
if (elevenAvailableAnd(^{ return someCondition })) {
// 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
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您愿意,也可以不使用 Block:
BOOL elevenAvailableAnd(BOOL condition)
{
if (@available(iOS 11.0, *)) {
return condition;
}
return NO;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8877 次 |
| 最近记录: |