Постоянное сохранение данных в KeychainAccess в Swift 5.0 - PullRequest
0 голосов
/ 06 мая 2019

Я хочу сохранять конфиденциальные данные пользователя в связке ключей постоянно, но проблема в том, что каждый раз, когда я перезапускаю приложение как на симуляторе, так и на устройстве, я теряю все данные. Согласно моему пониманию, данные цепочки для ключей должны продолжать жить в системе, если они явно не удалены. Я знаю, как сохранить данные в файл с помощью файлового менеджера, но это не подходит для этого сервиса. Я пытался найти ответ, но не повезло. Я специально ищу «Сохранение данных в связку ключей» и «Сохраняйте эти данные постоянно, чтобы при удалении и повторном запуске данных приложения все еще было». К вашему сведению, я сейчас использую упаковку KeychainAccess (https://github.com/kishikawakatsumi/KeychainAccess).

Пожалуйста, помогите мне сохранить данные с помощью связки ключей постоянно. Приложение Я работаю над хранением конфиденциальных данных, поэтому считаю, что это должна быть цепочка для ключей, но вы можете предложить любую другую, если это более уместно.

Ниже приведен мой тестовый код для достижения последовательной экономии, но не повезло.

  1. Это функции цепочки для ключей с оболочкой под названием KeychainAccess
import Foundation
import KeychainAccess

class Retriever {

    static let keychain = Keychain(service: "com.cochipcho.KeeperApp")

    // store
    static func saveToKeychain(data: Data) {
        keychain[data: "encoded"] = NSData(data: data) as Data

    }
    //retrieve
    static func loadFromKeychain() -> [String] {
        let retrievedData = keychain[data: "encoded"]
        let string = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(retrievedData!) as? [String]
        return string!
    }

}

Это контроллер представления, декларирующий сохранение / получение данных из класса цепочки для ключей.

import UIKit
import KeychainAccess

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    var array = [String]()

//saving into keychain
    @IBOutlet weak var textField: UITextField!
    @IBAction func buttonTapped(_ sender: Any) {
        array.append(textField.text!)
        let data = NSKeyedArchiver.archivedData(withRootObject: array)
        Retriever.saveToKeychain(data: data)
        }

//retrieving from keychain
    @IBOutlet weak var label: UILabel!
    @IBAction func retrieveButton(_ sender: Any) {
        label.text = "\(Retriever.loadFromKeychain())"
        print(Retriever.loadFromKeychain())
        print(Retriever.keychain[data: "encoded"])
    }
}

Ниже в консоли, где сохраняются входные данные, - но все это исчезло после переустановки и повторного запуска приложения на симуляторе.

["1"]
Optional(227 bytes)
["1", "2"]
Optional(235 bytes)
["1", "2"]
Optional(235 bytes)
["1", "2", "3"]
Optional(243 bytes)
["1", "2", "3", "4"]
Optional(251 bytes)
["1", "2", "3", "4", "5"]
Optional(259 bytes)

1 Ответ

1 голос
/ 17 мая 2019

Во-первых, мне пришлось настроить общий доступ к KeyChain в разделе «Возможности» и загрузить права.После установки все идет хорошо.Вот ссылка, которая помогла мне.

Невозможно сохранить данные в Keychain Xcode 8 GM (Swift 3)

Кроме того, это еще одна проблема, с которой я столкнулся при работе надмой настоящий проект.Хотя приведенный выше код использует массивы, которые были закодированы / декодированы с помощью NSKeyedArchiver, мой проект использует пользовательские типы классов и не работает с NSKeyedArchiver.Вместо этого я попытался PropertyList кодировать / декодировать его, и он наконец работает.Я успешно закодировал / расшифровал / связал ключи.Пожалуйста, ознакомьтесь с рабочим кодом ниже.

import Foundation
import KeychainAccess

class UserInformation: Codable {
    var isExpanded: Bool
    var isPinned: Bool
    var sectionName: String
    var userInformation: [String?]
    var indexPathSection: Int?

    init(isExpanded: Bool, isPinned: Bool, sectionName: String, userInformation: [String?], indexPathSection: Int?) {
        self.isExpanded = isExpanded
        self.isPinned = isPinned
        self.sectionName = sectionName
        self.userInformation = userInformation
        self.indexPathSection = indexPathSection
    }

}

extension UserInformation {
    static let propertyListEncoder = PropertyListEncoder()
    static let propertyListDecoder = PropertyListDecoder()
    static let keychain = Keychain(service: "com.cochipcho.KeeperApp-UserInfo")

    static func saveToKeychain(userInfo: [UserInformation]) {
        let data = try? propertyListEncoder.encode(userInfo)
        if let savingData = data {
            keychain[data: "encodedUserInfo"] = NSData(data: savingData) as Data
        }
    }

    static func loadFromKeychain() -> [UserInformation]? {
        guard let retrievedData = keychain[data: "encodedUserInfo"] else { return nil }
        let data = try? propertyListDecoder.decode(Array<UserInformation>.self, from: retrievedData)
        return data
    }

}

Осталась одна проблема - является ли PropertyListEncoder / PropertyList хорошим выбором здесь?Я думаю, что я не храню никаких данных, а просто кодирую / декодирую пользовательские типы с помощью PropertyListEncoder, а затем сохраняю их в связке ключей, так что я думаю, что это безопасно.Пожалуйста, кто-нибудь знает, про это помогите посоветовать?

...