如何将 CloudKit 记录数据从“TableView-Controller B”传递到“View-Controller C”?

Posted

技术标签:

【中文标题】如何将 CloudKit 记录数据从“TableView-Controller B”传递到“View-Controller C”?【英文标题】:How to pass the CloudKit records data from "TableView-Controller B" to "View-Controller C"? 【发布时间】:2017-07-01 20:15:21 【问题描述】:

我已经从我的CloudKit 获得记录数据并成功显示在TableViewController-B,但是我如何将CloudKit's records(strings, images) 传递给下一个ViewController-Cps. not tableViewcontroller-C

我的第一个TableViewController-B

import UIKit  
import CloudKit  

class BTableViewControoler: UITableViewController 
       var myclouds:[CKRecord] = []
       var imageCache = NSCache<CKRecordID, NSURL>()
       var recordType: String!

    override func viewDidLoad() 
            super.viewDidLoad()

            recordsFromCloud()
        

func recordsFromCloud() 

    let cloudContainer = CKContainer.default()
     let publicDatabase = cloudContainer.publicCloudDatabase  
        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: recordType, predicate: predicate)
        query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

        let queryOperation = CKQueryOperation(query: query)

        queryOperation.desiredKeys = ["name", "address", "GpNumber"]
        queryOperation.queuePriority = .veryHigh
        queryOperation.resultsLimit = 50
        queryOperation.recordFetchedBlock =  (record) -> Void in
            self.myclouds.append(record)
        

        queryOperation.queryCompletionBlock =  (cursor, error) -> Void in
            if let error = error  print("Failed data - \(error.localizedDescription)")
                 return 
        print("Successfully data")  
        
        publicDatabase.add(queryOperation)     
    //fetchRecords End

    override func numberOfSections(in tableView: UITableView) -> Int 

        return 1
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

        return myclouds.count
    


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MainCell


        let newInFo = myclouds[indexPath.row]

        cell.mainLabel.text = newInFo.object(forKey: "name") as? String
        cell.mainNumber.text = newInFo.object(forKey: "GpNumber") as? String
        cell.mainLocation.text = newInFo.object(forKey: "address") as? String
        cell.mainImage.image = UIImage(named: "photoalbum")

        //get image
        if let imageFileURL = imageCache.object(forKey: myclouds.recordID) 

            if let imageData = try? Data.init(contentsOf: imageFileURL as URL)
                cell.mainImage?.image = UIImage(data: imageData)
                
            else

                let publicDatabase = CKContainer.default().publicCloudDatabase
                let fetchRecordsImageOperation =   CKFetchRecordsOperation(recordIDs: [newInFo.recordID])
                fetchRecordsImageOperation.desiredKeys = ["image"]
                fetchRecordsImageOperation.queuePriority = .veryHigh

                fetchRecordsImageOperation.perRecordCompletionBlock = 
                    (record, recordID, error) -> Void in

                    if let error = error 
                        print("Failed image:\(error.localizedDescription)")
                        return
                    

                    if let newinfoRecord = record 
                        OperationQueue.main.addOperation() 
                    if let image = newinfoRecord.object(forKey: "image") 
                                let imageAsset = image as! CKAsset


                    if let imageData = try? Data.init(contentsOf: imageAsset.fileURL) 
                                    cell.mainImage.image = UIImage(data: imageData)
                                

             self.imageCache.setObject(imageAsset.fileURL as NSURL, forKey: newInFo.recordID)

                            
                         
                    //record end
                  

             publicDatabase.add(fetchRecordsImageOperation)
          //else end

          return cell
          //cell end


//Segue To Next View 
       override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
            if segue.identifier == "showDetailSegue" 
                if let indexPath = tableView.indexPathForSelectedRow 
                   let toDetailVC = segue.destination as! showDetailVC
                        toDetailVC.DisData = newinfo[indexPath.row]       
                

我的 ViewController-C

import UIKit
import CloudKit

class showDetailVC: UIViewController 

    @IBOutlet weak var detailpic: UIImageView!

    @IBOutlet weak var containerView: UIView!

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var infoLabel: UILabel!
    @IBOutlet weak var mynumberLabel: UILabel!

    var DisData: CKRecord?
    var getType: String!

    override func viewDidLoad() 
        super.viewDidLoad()

        detailpic.image = UIImage(named: "photoalbum")
        infoLabel.text = DisData?.object(forKey: "address") as? String
        nameLabel.text = DisData?.object(forKey: "name") as? String
        mynumberLable.text = DisData?.object(forKey: "GpNumber") as? String   
    



我使用var DisDatatableViewController-B 获取CKRecord 但它不适用于DisData?.object(forKey: "name") as? String 的方法 并且图像也无法弄清楚如何显示它。 我应该再次在ViewController-C 中使用UITableViewController-B's func recordsFromCloud 吗???或任何其他获得Cloudkit's records的聪明方法,请帮忙。

【问题讨论】:

【参考方案1】:

创建一个名为 selectedRecord 的变量

var selectedRecord: CKRecord!

添加委托方法 didSelectRowatindexPath

func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: IndexPath) 

    selectedRecord = myclouds[indexPath.row]
performSegueWithIdentifier("showDetailSegue", sender: nil)


把prepareforsegue改成这个

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
                if segue.identifier == "showDetailSegue" 
                       let toDetailVC = segue.destination as! showDetailVC
                            toDetailVC.DisData = selectedRecord       
                    

showDetailVC中将DisData的类型从CKRecord?改为CKRecord!

var DisData: CKRecord!

如果你想得到你的钥匙,请声明queryOperation 外面 recordsFromCloud()

然后,在showDetailVC中为Keys创建一个变量

var forKeys: [String]!

然后将以下行添加到prepareforsegue

toDetailVC.forKeys = queryOperation.desiredKeys

【讨论】:

它仍然不工作,没有错误但不显示任何东西,仍在努力。谢谢你的想法 它现在正在工作。我需要使queryOperation.desiredKeys = ["name", "address", "GpNumber"] 匹配showDetailVC 字符串就是这样,但图像无法显示在showDetailVC 我想需要更改代码detailpic.image = UIImage(named: "photoalbum") 但不知道该怎么做,你能修复代码?非常感谢您的帮助。 能不能再解释一下,queryOperation.desiredKeys = ["name", "address", "GpNumber"] 匹配showDetailVC是什么意思 是的!在我的项目中,我的showDetailVC'infoLabel.text = DisData?.object(forKey: "Gpaddress") as? String`nameLabel.text = DisData?.object(forKey: "GpName") as? StringmynumberLable.text = DisData?.object(forKey: "Gpnumber") as? StringforKeyes 和我之前发的不一样,因为我想让我的问题代码更容易被助手阅读。 所以您想将键 queryOperation.desireyKeys 传递给 showDetailVC?

以上是关于如何将 CloudKit 记录数据从“TableView-Controller B”传递到“View-Controller C”?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 CloudKit 更新所有客户端记录?

Swift - 从 Cloudkit 公共数据库中获取所有记录

CloudKit:将记录从开发转移到生产

从 CloudKit 获取包括 CKReference 的数据

CloudKit 返回太多记录

如何在 CloudKit 中存储对共享记录的引用