iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Software Development

iOS 學習筆記系列 第 26

Day26 Data Storage in iOS 02 - Keychain & Property list (Plists)

Keychain

Apple Keychain 是一個非常流行且功能強大的 Swift 工具,每個 iOS 和 MacOS 用戶都在使用。 它可用於保存密碼、安全筆記、證書等。總的來說,Keychain 是一個加密數據庫,具有相當複雜和強大的 API,當您需要保存敏感的用戶數據(例如密碼)時,請使用Keychain。

範例 :

struct KeychainItemStorable {
    let service: String
    let account: String
}
extension KeychainItemStorable {
    enum Error: Swift.Error {
        case passwordNotFound
        case unknownError(String)
        case invalidData
    }
    func readPassword() throws -> String {
        var query: [String : Any] = [:]
        query[kSecClass as String] = kSecClassGenericPassword
        query[kSecAttrService as String] = service
        query[kSecAttrAccount as String] = account as AnyObject?
        query[kSecMatchLimit as String] = kSecMatchLimitOne
        query[kSecReturnAttributes as String] = kCFBooleanTrue
        query[kSecReturnData as String] = kCFBooleanTrue
        
        // Try to fetch the existing keychain item that matches the query.
        var queryResult: AnyObject?
        let status = withUnsafeMutablePointer(to: &queryResult) {
            SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
        }
        switch status {
        case noErr:
            guard let items = queryResult as? [String: Any],
                let valueData = items[kSecValueData as String] as? Data,
                let valueString = String(data: valueData, encoding: .utf8) else
            { throw Error.invalidData }
            return valueString
        case errSecItemNotFound:
            throw Error.passwordNotFound
        default:
            throw Error.unknownError(status.description)
        }
    }
}

優點 :

  • 保存在鑰匙串中的所有項目都是加密的(鑰匙串是iOS中最安全的數據持久層)
  • 有很多開源且好用的 Swift API 的wrappers
  • Thread safety

Property list (Plists) in Swift

Plist 文件允許使用鍵/值約定存儲序列化對象。 在 macOS 和 iOS 應用程序中,plist 最常見的用法示例是存儲應用程序設置值的 Info.plist 文件。 在 Info.plist 中,我們可以找到應用程序名稱、版本號、所需權限信息、Facebook 應用程序信息等。 在我們所有使用 Firebase 的 iOS 應用程序模板中實現的 .plist 文件的另一個示例是 GoogleService -Info.plist 文件,其中包含用戶身份驗證和數據庫訪問所需的所有 Firebase API 密鑰

在 plist 文件中,您可以存儲基本型態資料,例如:

  • Strings
  • Numbers (Int, Floats)
  • Bools
  • Dates (ISO 8601 formatted string)
  • Data (NSData, for Objective-C folks)
  • Arrays
  • Dictionaries

可以使用 Bundle.main.infoDictionary 讀取存儲在應用程序的 Info.plist 文件中的信息。

如下所示:

let bundleIdentifire = Bundle.main.infoDictionary[kCFBundleIdentifierKey] as? String

範例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>FirstName</key>
  <string>John</string>
  <key>SecondName</key>
  <string>Doe</string>
  <key>Age</key>
  <string>24</string>
</dict>
</plist>
class PlistReader {
    func read(fileNamed: String) throws -> [String: Any] {
        guard let path = bundle.path(forResource: fileNamed, ofType: "plist"),
            let plistData = FileManager.default.contents(atPath: path) else {
                throw Error.fileMissing
        }
        var format = PropertyListSerialization.PropertyListFormat.xml
        return try PropertyListSerialization.propertyList(from: plistData,
                                                          options: .mutableContainersAndLeaves,
                                                          format: &format) as! [String: Any]
    }
}

上一篇
Day25 Data Storage in iOS 01 - UserDefaults
下一篇
Day27 Data Storage in iOS 03 - File System & Sqlite
系列文
iOS 學習筆記30

尚未有邦友留言

立即登入留言