Saving the text inside a UITextView to iCloud.

I have created an app which uses Vision to extract text from an image and stores this text in a UITextView. What I would like to do is save the extracted text on iCloud so that it can be accessed across all the users devices.

I have created a swift file (shown below) which will save items to iCloud. I will attach my code for the text extraction in a new post below.

Any suggestions in how to merge the text in the UITextView and the items that are stored in iCloud in the code shown below would be greatly appreciated.

Many thanks for your help.

import CloudKit
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
    let tableView: UITableView = {
        let tableView = UITableView()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return tableView
    }()
    private let database = CKContainer(identifier: "iCloud.MyGroceryList").publicCloudDatabase
    var items = [String]()
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Grocery List"
        view.addSubview(tableView)
        tableView.dataSource = self
        let control = UIRefreshControl()
        control.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged)
        tableView.refreshControl = control
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add,
                                                            target: self,
                                                            action: #selector(didTapAdd))
        fetchItems()
    }
    @objc func fetchItems() {
        let query = CKQuery(recordType: "GroceryItem",
                            predicate: NSPredicate(value: true))
        database.perform(query, inZoneWith: nil) { [weak self] records, error in
            guard let records = records, error == nil else {
                return
            }
            DispatchQueue.main.async {
                self?.items = records.compactMap({ $0.value(forKey: "name") as? String })
                self?.tableView.reloadData()
            }
        }
    }
    @objc func pullToRefresh() {
        tableView.refreshControl?.beginRefreshing()
        let query = CKQuery(recordType: "GroceryItem",
                            predicate: NSPredicate(value: true))
        database.perform(query, inZoneWith: nil) { [weak self] records, error in
            guard let records = records, error == nil else {
                return
            }
            DispatchQueue.main.async {
                self?.items = records.compactMap({ $0.value(forKey: "name") as? String })
                self?.tableView.reloadData()
                self?.tableView.refreshControl?.endRefreshing()
            }
        }
    }
    @objc func didTapAdd() {
        let alert = UIAlertController(title: "Add Item",
                                        message: nil,
                                      preferredStyle: .alert)
        alert.addTextField { field in
            field.placeholder = "Enter Name..."
        }
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { [weak self] _ in
            if let field = alert.textFields?.first, let text = field.text, !text.isEmpty {
                self?.saveItem(name: text)
            }
        }))
        present(alert, animated: true)
    }
    @objc func saveItem(name: String) {
        let record = CKRecord(recordType: "GroceryItem")
        record.setValue(name, forKey: "name")
        database.save(record) { [weak self] record, error in
            if record != nil, error == nil {
                DispatchQueue.main.asyncAfter(deadline: .now()+2) {
                    self?.fetchItems()
                }
            }
        }
    }
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        tableView.frame = view.bounds
    }
    // MARK: - Table
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return items.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = items[indexPath.row]
        return cell
    }
}

Below I have attached the code for the text extraction. The extracted text is saved in the UITextView and it is this which I want stored on iCloud using the code from the previous post.

Many thanks for your help.

import SwiftUI
import UIKit
import Vision
class ViewController2: UIViewController {
    let stackView: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.alignment = .center
        stack.spacing = 20
        return stack
    }()
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var shareButton: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
        //setupUI()
        button.backgroundColor = .systemCyan // Background colour of the select photo button
        button.setTitle("Select Photo", for: .normal) // Button text
        button.setTitleColor(.white, for: .normal) // Button text Colour
        // Rounding the edges of the 'Select Photo' button:
        button.layer.cornerRadius = 25
        button.layer.borderWidth = 20
        button.layer.borderColor = UIColor.systemCyan.cgColor
        // Rounding the edges of the 'Share' button:
        shareButton.layer.cornerRadius = 25
        shareButton.layer.borderWidth = 10
        shareButton.layer.borderColor = UIColor.systemCyan.cgColor
        stopAnimating() // Activity indicator disappears
    }
    // Defining the activity indicators show and spin
    private func startAnimating() {
        self.activityIndicator.startAnimating()
    }
    // Defining the activity indicators stop and hide
    private func stopAnimating(){
        self.activityIndicator.stopAnimating()
    }
    @IBAction func selectPhotoButton(_ sender: Any) { // When selectPhoto button is pressed,
        SelectPhotoButtonPressed() // run the function SelectPhotoButtonPressed.
    }
    private func SelectPhotoButtonPressed(){
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
            let imageSelector = UIImagePickerController() // Apple's interface for taking pictures and loading items from camera roll
            imageSelector.sourceType = .photoLibrary // Opens the device's photo library
            imageSelector.delegate = self // Leaves the UIImagePickerController when a picture is selected
            self.present(imageSelector, animated: true, completion: nil) // Present the imageSelector  
        }
    }
    // Text Recognition
    // Create request
    var request = VNRecognizeTextRequest(completionHandler: nil)
    private func VisionOCR(image: UIImage?){
        var textString = "" // Variable textString = string
        // Create completion handler
        request = VNRecognizeTextRequest(completionHandler: { (request, error)in  // Locates all the text in the image.
            // Results are in the request
            guard let results = request.results as?[VNRecognizedTextObservation] else {fatalError("Recieved Invalid Observation")}
            for visionResult in results{
                guard let recognisedText = visionResult.topCandidates(1).first else{ // Text stored in chronological order.
                    print("No text")
                    continue
                }
                textString += "\n\(recognisedText.string)"
                DispatchQueue.main.async{ // FIFO queue
                    self.stopAnimating() // Hide the activityIndicator
                    self.textView.text = textString // Assign the textView the recoginsed text
                }
            }
        })
        // Properties
        request.minimumTextHeight = 0.03125 // Default mimnimum height for text to be recognised in comparison to image, (1/32).
        request.recognitionLevel = .accurate // Choice between accurate and fast.
        request.recognitionLanguages = ["en_UK", "en-US", "fr-FR", "it-IT", "de-DE", "es-ES", "pt-BR", "zh-Hans", "zh-Hant", "yue-Hans", "yue-Hant", "ko-KR", "ja-JP", "ru-RU", "uk-UA"] // Recognisable languages.
        request.usesLanguageCorrection = true // Applies language correction.
        let requests = [request]
        // Request handler
        DispatchQueue.global(qos: .userInitiated).async{  // FIFO queue, qos (quality of service) determines priotity for scheduling tasks
            guard let img = image?.cgImage else {fatalError("Missing image to scan")} // Variable image = computer generated image
            // Create request handler
            let requestHandler = VNImageRequestHandler(cgImage: img, options: [:])  // Performs Vision requests
            // Send request to request handler
            try? requestHandler.perform(requests) // Schedules Vision requests to be performed
        }
    }
}
extension ViewController2: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey :Any]){
        picker.dismiss(animated: true, completion: nil)
        startAnimating()
        self.textView.text = ""
        let image = info[UIImagePickerController.InfoKey.originalImage]as?UIImage
        self.imageView.image = image
        VisionOCR(image: image)
    }
}
public struct storyboardview2: UIViewControllerRepresentable{
    public func makeUIViewController(context content: Context) -> UIViewController {
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let controller = storyboard.instantiateViewController(identifier: "selectPhoto")
        return controller
    }
    public func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    }
}

Saving the text inside a UITextView to iCloud.
 
 
Q