Как обновить устаревший код NSKeyedArchiver / NSKeyedUnarchiver? - PullRequest
0 голосов
/ 12 апреля 2020

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

private func save(object: SKObject) throws {
    let fileManager = FileManager.default

    do {
      let cacheDirectory = try fileManager.url(for: .cachesDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
      let fileDirectory = cacheDirectory.appendingPathComponent("spacekit")

      var fileDir = fileDirectory.absoluteString
      let range = fileDir.startIndex..<fileDir.index(fileDir.startIndex, offsetBy: 7)
      fileDir.removeSubrange(range)

      try createFolderIfNeeded(atPath: fileDir, absolutePath: fileDirectory)

      let fileFormatedName = object.key.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? object.key

      let convertedFileName = convertToBase64(withString: fileFormatedName).suffix(45).map({ String($0) }).joined()

      let fileName = fileDirectory.appendingPathComponent(convertedFileName)

      if !fileManager.fileExists(atPath: fileName.absoluteString) || object.isUpdated {
        let data = NSKeyedArchiver.archivedData(withRootObject: object)

        try? data.write(to: fileName)
      }
    } catch {
      throw Operations.saveFail
    }
  }

Специально в этой строке :

let data = NSKeyedArchiver.archivedData(withRootObject: object)

Мне удалось придумать эту исправленную версию, но я не уверен, что она правильная:

let data = try NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)

Наконец,

private func load() throws {
    let fileManager = FileManager.default
    do {
      let cacheDirectory = try fileManager.url(for: .cachesDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
      let fileDirectory = cacheDirectory.appendingPathComponent("spacekit")

      var fileDir = fileDirectory.absoluteString
      let range = fileDir.startIndex..<fileDir.index(fileDir.startIndex, offsetBy: 7)
      fileDir.removeSubrange(range)

      try createFolderIfNeeded(atPath: fileDir, absolutePath: fileDirectory)

      let paths = try fileManager.contentsOfDirectory(atPath: fileDir)

      for path in paths {
        if let object = NSKeyedUnarchiver.unarchiveObject(withFile: fileDir + path) as? SKObject {
          if !object.isExpired {
            add(object: object)
          } else {
            try? fileManager.removeItem(atPath: fileDir + path)
          }
        }
      }
    } catch {
      throw Operations.loadFail
    }
  }

Конкретно в этой строке:

if let object = NSKeyedUnarchiver.unarchiveObject(withFile: fileDir + path) as? SKObject {

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

Обновлено:

private func load() throws {
    let fileManager = FileManager.default
    do {
      let cacheDirectory = try fileManager.url(for: .cachesDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
      let fileDirectory = cacheDirectory.appendingPathComponent("spacekit")

      var fileDir = fileDirectory.absoluteString
      let range = fileDir.startIndex..<fileDir.index(fileDir.startIndex, offsetBy: 7)
      fileDir.removeSubrange(range)

      try createFolderIfNeeded(atPath: fileDir, absolutePath: fileDirectory)

      let paths = try fileManager.contentsOfDirectory(atPath: fileDir)

      for path in paths {
        let objData = try Data(contentsOf: URL(fileURLWithPath: fileDir + path))
        if let object = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [SKObject.self], from: objData) as? SKObject {
          if !object.isExpired {
            add(object: object)
          } else {
            try? fileManager.removeItem(atPath: fileDir + path)
          }
        }
      }
    } catch {
      throw Operations.loadFail
    }
  }

1 Ответ

0 голосов
/ 18 апреля 2020

Что касается первой функции, вы обновили ее правильно.
Что касается второй функции,

fun c unarchivedObject (ofClasses classes: [AnyClass], from data: Данные) throws -> Any? теперь требуется Data param.
И у вас есть путь к файлу, в котором хранится это Data.

Таким образом, вы можете обновить код следующим образом:

let objData = try Data(contentsOf: URL(fileURLWithPath: fileDir + path))
if let object = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [MyClass.self], from: objData) {
    // check if object.isExpired, etc
}

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

...