这里的答案是:https://stackoverflow.com/a/51250282/1343140说,应该可以将lazyvar
标记为@available
,以高于运行时使用的iOS版本。
我正在编写一些代码,如果用户在iOS13上,他们的数据将被加密(因为它存储在云中)。 在iOS12中,他们的数据存储在本地,不加密。
下面是我正在做的工作的简化版本:
import CryptoKit
import Foundation
class DataStore {
@available(iOS 13.0, *)
fileprivate lazy var crypto = Crypto()
func store(data: Data) {
let url = URL(fileURLWithPath: "myfile.dat")
if #available(iOS 13.0, *) {
try! crypto.encrypt(data: data).write(to: url)
} else {
try! data.write(to: url)
}
}
}
@available(iOS 13.0, *)
class Crypto {
// SymetricKey is only available in iOS 13. In reality we may load this from keychain
lazy private var key: SymmetricKey = SymmetricKey(size: .bits256)
func encrypt(data: Data) -> Data {
// do encrpyion
return data
}
}
let store = DataStore()
store.store(data: "hello data".data(using: .utf8)!)
这编译很好,并且在iOS13中运行良好。
但是,在iOS 12中,当调用let store=DataStore()
时,我会在运行时看到以下崩溃:
dyld: lazy symbol binding failed: can't resolve symbol _$s9CryptoKit12SymmetricKeyVMa in [...] because dependent dylib #7 could not be loaded
dyld: can't resolve symbol _$s9CryptoKit12SymmetricKeyVMa in [...] because dependent dylib #7 could not be loaded
我不希望每次调用store
函数时都必须加载crypto
类,因为这有很大的开销(从钥匙串读取),但我不知道如何使crypto
成为一个属性,以便它在iOS 13中保留在内存中,而在iOS 12中根本不加载。
这可能吗? 如果没有,最好的办法是什么? 让Crypto成为一个单一的?!
您需要将CryptoKit
框架弱链接到您的项目。 即使没有执行访问cryptokit
的codepath,您的文件中也有一个在较旧的iOS版本上执行的import语句。
弱链接解决了这个问题。 有关弱链接的更多信息,请参阅弱链接的官方文档。