Как получить PKDrawing из Firestore

#ios #swift #firebase #google-cloud-firestore

#iOS #swift #firebase #google-облако-firestore

Вопрос:

В настоящее время я пытаюсь реализовать функцию заметок в своем приложении, и способ, которым я реализовал сохранение PKDrawings , приведен ниже:

  func saveDrawingData() {
        var drawingDataArray = [String : Any]()
        let drawingData = convertImageToBase64String(img: canvasView.screenshot!)
        
        drawingDataArray["drawing_data"] = drawingData
        
        if let client = selectedClient, let fileNumber = selectedFileNumber {
            dbm.addCaseDataToDatabase(client, fileNumber, drawingDataArray)
        } else {
            print("Data not sent to Firestore")
        }
    }
 

Я делаю это, преобразуя чертеж в изображение, используя метод «скриншот» ниже:

 extension UIView {
    var screenshot : UIImage? {
    var screenshot :UIImage?
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
    guard let context = UIGraphicsGetCurrentContext() else {return nil}
    layer.render(in:context)
    screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return screenshot
    }
}
 

Хотя данные успешно сохраняются в Firestore, сейчас я пытаюсь извлечь их PKDrawing из базы данных и поместить обратно на холст, чтобы их можно было дополнительно отредактировать и сохранить.

Ниже приведен мой код для отображения данных, которые были загружены из базы данных:

     func displayDrawingFromDatabase(from data: [String: Any]) -> UIView {
        if let drawing = data["drawing_data"] {
            //convert downloaded key-value pair to image
            let downloadedImage = convertBase64StringToImage(imageBase64String: drawing as! String)
            //convert image to string
            let imageString = convertImageToBase64String(img: downloadedImage)
            //convert string to data
            let imageData = Data(base64Encoded: imageString, options: .ignoreUnknownCharacters)
            //Apply to canvasView
            canvasView.drawing = imageData
        }
        return canvasView
    }
 

Когда я это делаю, я получаю сообщение об ошибке:

 cannot assign value of type Data? to type PKDrawing
 

Я попытался извлечь данные из чертежа с помощью этого .dataRepresentation() метода, но мне не удалось успешно извлечь данные из пары ключ-значение displayDrawingDataFromDatabase() .
Что я должен сделать, чтобы исправить код?

Редактировать:

Я вызываю displayDrawingFromDatabase() с помощью:

   override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(animated)

       if let client = selectedClient, let fileNumber = selectedFileNumber {
           dbm.readDrawingDataFromDatabase(client, fileNumber) { (caseData, success) in
               self.displayDrawingFromDatabase(from: caseData)
       }
    }
 

и этот код основан на функции, приведенной ниже:

    func readDrawingDataFromDatabase(_ client: Client, _ fileNumber: FileNumber, completion: @escaping ((_ documentData: [String: Any], _ success: Bool) -> Void)) {
        guard let uid: String = Auth.auth().currentUser?.uid else { return print("Cannot retrieve uid")}

        let clientDocumentID = client.documentID
        let fileNumberDocumentID = fileNumber.documentID
        
        let clientRef = db.collection("users").document(uid).collection("clients")
        let fileNumberRef = clientRef.document(clientDocumentID).collection("file_numbers")
        
        let query = fileNumberRef.whereField("document_id", isEqualTo: fileNumberDocumentID as Any)
        
        query.getDocuments() { (querySnapshot, err) in
            if let err = err {
                print("Error getting documents: (err)")
            } else {
                for document in querySnapshot!.documents {
                    //print("(document.documentID) => (document.data())")
                    let documentData: [String: Any] = document.data()
                    completion(documentData, true)
                }
            }
        }
        
    }
 

Комментарии:

1. В вопросе много неизвестных, поэтому ответить как есть будет невозможно. Почему вы не сохраняете штрихи, составляющие рисунок, вместо снимка экрана? Что вы передаете displayDrawingFromDatabase ? И почему вы возвращаетесь return canvasView , когда он выглядит как класс var? Какая конкретная строка выдает ошибку? Добавили ли вы точку останова и пошагово просматривали код построчно, проверяя переменные, чтобы определить, какой из них идет не так? Пожалуйста, обновите и уточните вопрос и код, и мы посмотрим.

2. Во-первых, спасибо, что посмотрели на него. Что касается ваших вопросов: 1. Почему вы

3. Чтобы ответить на ваши вопросы: 1. Почему вы не сохраняете штрихи? Я понятия не имею, как это сделать. Я просто случайно нашел метод скриншота, и он, похоже, сработал. 2. Я вызываю displayingDrawingFromDatabase, используя if let client = selectedClient, let fileNumber = selectedFileNumber { dbm.readDrawingDataFromDatabase(client, fileNumber) { (caseData, success) in self.displayDrawingFromDatabase(from: caseData) } 3. Строка, которая выдает ошибку: canvasView.drawing = imageData . Ошибка cannot assign value of type Data to type PKDrawing .

4. Если вы хотите сохранить фактический чертеж (UIImage) или электронную таблицу .pdf или .numbers или действительно любой файл, перейдите по ссылке в моем комментарии, чтобы сохранить их в хранилище Firebase, поскольку для этого оно и предназначено. Поля Firestore не являются подходящим местом для хранения больших файлов (больших двоичных объектов). Имейте в виду, что PKDrawings состоят из массива отдельных PKStrokes — это то, что я бы сохранил в Firestore. Вам все равно нужно будет кодировать / декодировать их как NSData, но это гораздо более гибко, чем сохранение документа в виде файла, поскольку тогда у вас есть доступ к каждому штриху.

5. Я бы также предложил использовать NSKeyedArchiver и NSKeyedUnarchiver для хранения и извлечения данных из Firestore (например, Any, или String или PKStroke и т. Д.).