我的应用程序正在使用CoreLocation和CLLocationManager,在iOS 13和iOS 12中运行良好。
我使用Xcode 12在iOS 14中实现了精确定位的新功能,它在iOS 14、iOS 13和iOS 12中运行良好。
但是当我在Xcode 11版本(Xcode 11.7(中执行Xcode 12代码时,我会得到错误
无法推断引用成员"reducedAccuracy"的上下文基础
类型为"CLLocationManager"的值没有成员"accurcyAuthorization">
if #available(iOS 14.0, *) {
if authorizationStatus.accessLevel == .granted && locationManager.accuracyAuthorization == .reducedAccuracy {
return .locationAlwaysAllowPreciseLocationOff
}
if authorizationStatus.accessLevel == .denied && locationManager.accuracyAuthorization == .fullAccuracy {
return .locationDeniedPreciseLocationON
}
}
// MARK: iOS 14 location function.
@available(iOS 14.0, *)
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
// iOS 14 Location Delegate method, not available in iOS 13 version
}
这里的错误是
静态成员"authorizationStatus"不能用于类型为"CLLocationManager"的实例
据我所知,精确定位是iOS 14的功能,在以下版本中不可用;"准确性授权"&";。减少的精确度"&";。fullAccuracy"在iOS 13版本中不可用。
我的问题是如何使我的代码在Xcode 11版本中运行。我已经添加了isAvailable检查来检查设备版本。
提前感谢:(
在这种情况下,再多的#available
或@available
标记也无济于事。
为什么不呢?好吧,你正在做一件意想不到的事情:你正在Xcode 11中打开一个Xcode 12项目。您的代码最初是在Xcode 12中编译的,iOS 14就是其中的一部分。所以它编译成功了。但现在你在Xcode 11中打开了同一个项目,iOS 14是而不是。关于这个环境,没有任何人知道它的存在。因此,涉及iOS14特有内容的代码将不会编译。如果编译器看到了那个代码,你就完了。
那么,所有的希望都破灭了吗?不完全是!假设我们要向编译器隐藏代码。如果我们这样做——如果我们可以安排事情,使得在Xcode 11中,编译器根本看不到这个代码——那么我们将能够在Xcode 11中编译。
好吧,我们可以做到这一点!我们可以使用编译条件。我们所需要的只是一些允许我们检查的条件,这将区分这是什么版本的Xcode。有这样一个条件——Swift版本。
因此,我们可以这样写,例如:
class ViewController: UIViewController {
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
#if swift(>=5.3)
let status = manager.authorizationStatus
print(status.rawValue)
#endif
}
}
该代码在Xcode 12和Xcode 11中都进行编译,因为在Xcode 11中,编译条件失败,编译器甚至从不查看#if
块内部。
事实上,我们可以提供该代码的替代版本,用于Xcode 11中。为了使这项工作如我们所愿,我们还必须恢复您的#available
检查,因为我们必须使项目的部署目标为iOS 13,如果我们不保护iOS 14代码,Xcode 12编译器会抱怨:
class ViewController: UIViewController {
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
#if swift(>=5.3)
if #available(iOS 14.0, *) {
let status = manager.authorizationStatus
print(status.rawValue)
}
#else
let status = CLLocationManager.authorizationStatus()
print(status.rawValue)
#endif
}
}
该代码在Xcode 11中或Xcode 12中都能正确编译和运行。你明白为什么吗?让我们复习一下,因为这有点棘手。
在Xcode 11中,编译器永远看不到整个
#if
部分。它只看到这个:let status = CLLocationManager.authorizationStatus() print(status.rawValue)
这是很好的iOS 13代码,所以一切都很好。
在Xcode 12中,编译器永远看不到整个
#else
部分。它只看到这个:if #available(iOS 14.0, *) { let status = manager.authorizationStatus print(status.rawValue) }
这是一个很好的iOS 14代码,因为即使我们项目的部署目标是iOS 13,我们也通过保证此代码不会在iOS 13中执行(如果执行,它会崩溃(来安抚编译器的神经。
说了这么多,真正的答案是:不要。我刚才做的每件事都太麻烦了!一旦您在Xcode 12中编写了代码,就不要试图在Xcode 11中打开该项目。这不是测试向后兼容性的方法。