如何从 CKRecord 创建本地对象并将其附加到 NSTableView 数据的数组

How to create a local Object from a CKRecord and append it to an array for NSTableView data

我正在为具有云功能的 macOS 开发一个笔记应用程序项目,特别是在给定笔记“CloudID”的情况下下载另一个人的笔记,这只是笔记上传到时云数据库为记录提供的唯一名称云端。我使用 sqlite 数据库存储本地数据,使用 cloudKit 数据库存储 public 数据。当我测试下载功能时,它正确地将数据添加到 sqlite 数据库,但是我附加到我的 notesArray 的本地对象(用于填充我主页中的 NSTableView)没有被修改。

代码如下:

@IBAction func downloadNoteFromCloud(_ sender: Any) {
    // 1.) check to make sure text field isn't empty
    if (noteIDTextField.stringValue == "") {
        noteIDTextField.stringValue = "Please enter the desired note's cloudID"
    }
    
    // 2.) query the note with the given cloudID
    
    // make note object for the downloaded note bc of scope issues
    var downloadedNote = Note(0, "", "")
    
    //sets cloudDB to the public cloud database
    let container = CKContainer.default()
    let cloudDB = container.publicCloudDatabase
    
    let noteRecordID = CKRecord.ID(recordName: noteIDTextField.stringValue)
    
    // returns a CKRecord
    cloudDB.fetch(withRecordID: noteRecordID) { record, error in
        if let error = error {
            // Handle error
            print(error)
            return
        }
        // Record fetched successfully
        if let noteRecord = record {
            // set the values of the downloadedNote obj equal the the values of the noteRecord
            downloadedNote.setValues((notesArray.count), noteRecord["Title"] as! String, noteRecord["Body"] as! String)
            
            // add to local database ~ this works
            do {
                let path = NSSearchPathForDirectoriesInDomains(
                    .applicationSupportDirectory, .userDomainMask, true
                ).first! + "/" + Bundle.main.bundleIdentifier!

                // create parent directory iff it doesn’t exist
                try FileManager.default.createDirectory(
                atPath: path, withIntermediateDirectories: true, attributes: nil
                )
                
                //connect to DB
                let db = try Connection("\(path)/db.sqlite3")
                //Define the Notes Table and its Columns
                let notes = Table("Notes")
                //ID is primary key so it doesn't need to be defined for inserts
                let title = Expression<String>("Title")
                let body = Expression<String>("Body")
                
                try db.run(notes.insert(title <- downloadedNote.title, body <- downloadedNote.body))
            }
            catch {
                print(error)
            }
        }
    }
    // append downloadedNote to notesArray
    notesArray.append(downloadedNote)
    
    //Send Notification to reload the tableView data
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
    
    //Return to home page
    self.view.window?.close()
}

我假设这是一个范围问题,我尝试移动 append func 并且我尝试使原始的 downloadedNote 声明成为一个可选类型,它没有像这样初始化:var downloadedNote: Note?然后像这样在 fetch func 内部初始化它: downloadedNote = Note(id: notesArray.count, title: noteRecord["Title"] as! String, body: noteRecord["Body"] as! String) none 其中工作正常。我最接近它的工作是代码现在的样子。请让我知道我哪里出错了以及如何解决。非常感谢您的帮助!

CloudKit 异步工作。移动代码以通知并重新加载 table 到闭包

替换

           try db.run(notes.insert(title <- downloadedNote.title, body <- downloadedNote.body))
        }
        catch {
            print(error)
        }
    }
}
// append downloadedNote to notesArray
notesArray.append(downloadedNote)

//Send Notification to reload the tableView data
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)

//Return to home page
self.view.window?.close()

           try db.run(notes.insert(title <- downloadedNote.title, body <- downloadedNote.body))

           DispatchQueue.main.async {
               // append downloadedNote to notesArray
               notesArray.append(downloadedNote)

               //Send Notification to reload the tableView data
               NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)

               //Return to home page
               self.view.window?.close()
           }
        }
        catch {
            print(error)
        }
    }
}

并在闭包内创建新的注释。不再有 范围问题


旁注:

NSSearchPathForDirectoriesInDomains 闻起来 objective-c-ish 并且已经过时了。使用FileManagerURL相关API

do {
    let fm = FileManager.default
    let applicationSupportURL = try fm.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    let applicationSupportBundleURL = applicationSupportURL.appendingPathComponent(Bundle.main.bundleIdentifier!)
    
    if !fm.fileExists(atPath: applicationSupportBundleURL.path) {
        // create parent directory iff it doesn’t exist
        try fm.createDirectory(at: applicationSupportBundleURL, withIntermediateDirectories: true, attributes: nil)
    }
    let dbPath = applicationSupportBundleURL.appendingPathComponent("db.sqlite3").path
    
    //connect to DB
    let db = try Connection(dbPath)
    ...