提问者:小点点

在IOS12上运行的类中是否可以使用@Available(IOS13)计算属性?


这里的答案是: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成为一个单一的?!


共1个答案

匿名用户

您需要将CryptoKit框架弱链接到您的项目。 即使没有执行访问cryptokit的codepath,您的文件中也有一个在较旧的iOS版本上执行的import语句。

弱链接解决了这个问题。 有关弱链接的更多信息,请参阅弱链接的官方文档。