Добавление элементов и запрос брелка для iOS с помощью Swift

У меня проблемы с преобразованием всехObjective C примеры кода, которые доступны для добавления данных и запроса данных изiOS Keychain встриж, Я пытаюсь сделать базовое хранение строки (токен доступа) и читаю его обратно. Я взглянул на некоторые другие вопросы о переполнении стека, но не могу заставить его работать. Я пытался собрать воедино решение из разных источников.

Изменить 1: Я попытался с более простой настройкой, потому что я думал, что мой self.defaultKeychainQuery, возможно, испортил вещи. Я обновил код ниже до последней версии.

Изменить 2: Получил это работает. Я не добавлял значение данных в запрос на сохранение правильно. Мне нужно было преобразовать строку в NSData. Я обновил код ниже до самой последней рабочей версии.

Изменить 3: Как указывает Xerxes ниже, этот код не работает с версиями Xcode выше Beta 1 из-за некоторых проблем со словарями. Если вы знаете, как это исправить, пожалуйста, дайте мне знать.

Обновление: я превратил это вбиблиотека брелка, написанная на Swift, называется Locksmith.

Сохранить

class func save(service: NSString, data: NSString) {
  var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
  // Instantiate a new default keychain query
  var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, dataFromString], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData])

  // Delete any existing items
  SecItemDelete(keychainQuery as CFDictionaryRef)

  // Add the new keychain item
  var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)

  // Check that it worked ok
  println("Saving status code is: \(status)")
}

нагрузка

  class func load(service: NSString) -> AnyObject? {
    // Instantiate a new default keychain query
    // Tell the query to return a result
    // Limit our results to one item
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, kCFBooleanTrue, kSecMatchLimitOne], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData, kSecMatchLimit])



    // I'm not too sure what's happening here...
    var dataTypeRef :Unmanaged<AnyObject>?

    // Search for the keychain items
    let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)


    println("Loading status code is: \(status)")

    // I'm not too sure what's happening here...
    let opaque = dataTypeRef?.toOpaque()

    if let op = opaque? {
      let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
      println("Retrieved the following data from the keychain: \(retrievedData)")
      var str = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
      println("The decoded string is \(str)")
    } else {
      println("Nothing was retrieved from the keychain.")
    }

    return nil
  }

Использование (просмотр контроллера)

KeychainService.saveToken("sometoken")
KeychainService.loadToken()

который использует эти удобные методы

class func saveToken(token: NSString) {
    self.save("service", data: token)
  }

class func loadToken() {
    var token = self.load("service")
    if let t = token {
      println("The token is: \(t)")
    }
  }

Это приводит к выводу в консоли:

Saving status code is: 0
Loading status code is: 0
Retrieved the following data from the keychain: <736f6d65 746f6b65 6e>
The decoded string is sometoken

Большое спасибо за вашу помощь. Я не слишком уверен, что делать с dataTypeRef, как только я его получу, или если у него есть какие-либо данные, приведенные выше.

Ответы на вопрос(5)

Ваш ответ на вопрос