Swift Data конвертируется в UInt64 - PullRequest
0 голосов
/ 03 апреля 2020

Я прочитал несколько документов Apple, но я не могу сделать это в объекте. Я получаю через bluetooth значение unix timestamp в переменной типа Data, и я не хочу преобразовывать его в переменную UInt64 для заполнения UIDatePicker, но реализованная мною функция выдает ошибку: «Неустранимая ошибка: UnsafeRawBufferPointer. загрузить вне границ "

У вас есть какие-либо предложения? Я использую Swift 5.1

Это мой код:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var datePicker: UIDatePicker!

    private func setDate(value: Data) {
        let date = Date(timeIntervalSince1970: TimeInterval(value.uint64))
        datePicker.setDate(date, animated: true)
    }
}

extension Data {
    var uint64: UInt64 {
        withUnsafeBytes { $0.load(as: UInt64.self) }
    }
}

Ответы [ 2 ]

2 голосов
/ 03 апреля 2020

Я получаю эту ошибку, когда в данных недостаточно байтов для формирования UInt64 (меньше 8). Вполне вероятно, что это именно тот случай.

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

extension Data {
  var uint64: UInt64 {
        get {
            if count >= 8 {
                return self.withUnsafeBytes { $0.load(as: UInt64.self) }
            } else {
                return (self + Data(repeating: 0, count: 8 - count)).uint64
            }
        }
    }
}

Это предполагает, что устройство с прямым порядком байтов и данные с прямым порядком байтов. Если данные имеют старший порядковый номер:

extension Data {
  var uint64: UInt64 {
        get {
            if count >= 8 {
                return self.withUnsafeBytes { $0.load(as: UInt64.self).bigEndian }
            } else {
                return (Data(repeating: 0, count: 8 - count) + self).uint64
            }
        }
    }
}

Или, если можете, исправьте эту проблему на своем устройстве Bluetooth, чтобы оно всегда отправляло 8 байтов.

1 голос
/ 03 апреля 2020

Если вы знаете, что ваше устройство Bluetooth будет отправлять только байтовое значение с байтовым порядком байтов, то это всего лишь 32 бита. Я не уверен, почему вы пытаетесь извлечь UInt64 из того, что вы знаете, просто UInt32 (или другого 32-битного типа). Поэтому я бы предложил:

extension Data {
    var uint32: UInt32 { 
        withUnsafeBytes { $0.load(as: UInt32.self) }
    }
}

Или вы можете явно указать порядковый номер:

extension Data {
    var uint32: UInt32 { 
        withUnsafeBytes { $0.load(as: UInt32.self).littleEndian }
    }
}
...