【问题标题】:Cloudkit Fetch very slowCloudkit 获取速度很慢
【发布时间】:2016-12-26 00:17:55
【问题描述】:

运行以下代码从 Cloudkit 获取数据,目前填充 tableView 需要很长时间,具体取决于有多少结果,但如果有超过 15 个结果,则需要 10 秒以上。他们有什么方法可以加快速度吗?

这是我的获取函数:

func loadData() {
        venues = [CKRecord]()
         let location = locationManager.location

        let radius = CLLocationDistance(500)

        let sort = CKLocationSortDescriptor(key: "Location", relativeLocation: location!)

        let predicate = NSPredicate(format: "distanceToLocation:fromLocation:(%K,%@) < %f", "Location", location!, radius)

        let publicData = CKContainer.defaultContainer().publicCloudDatabase

        let query = CKQuery(recordType: "Venues", predicate: predicate )

        query.sortDescriptors = [sort]

        publicData.performQuery(query, inZoneWithID: nil) { (results:[CKRecord]?, error:NSError?) in
            if let venues = results {
                self.venues = venues
                dispatch_async(dispatch_get_main_queue(), {
                    self.tableView.reloadData()
                    self.refreshControl.endRefreshing()
                    self.tableView.hidden = false
                })
            }
        }
    }

这是我的 tableView 函数:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! NearMe2ViewCell

        if venues.count == 0 {


            return cell
        }

        let venue = venues[indexPath.row]




        print(indexPath.row)


        let venueLocation = venue["Location"] as? CLLocation
        let venueTitle = (venue["Name"] as! String)
        let venueImages = venue["VenuePhoto"] as! CKAsset

        let userLocation = locationManager.location
        let distanceBetween: CLLocationDistance = (venueLocation!.distanceFromLocation(userLocation!))
        self.venueDistance = String(format: "%.f", distanceBetween)

        cell.venueDistance?.text = venueDistance
        cell.venueName.text = venueTitle
        cell.venueImage?.image = UIImage(contentsOfFile: venueImages.fileURL.path!)


        return cell


    }

【问题讨论】:

    标签: ios swift uitableview cloudkit


    【解决方案1】:

    您应该首先搜索记录键,因此 fetchOperation 将包含此指令。

    fetchOperation.desiredKeys = ["record.recordID.recordName"]
    

    那应该更快。将返回的密钥分解为可以在屏幕上显示的大小,然后只获取它们。显示它们后,在后台线程中获取下一批,当你在后台等上获得下一批时等等。

    也许应该补充一点,如果可能的话,获取资产也应该在单独的线程上完成,当您通过重复重新加载表来拉入资产时更新表。

    这是搜索和返回键的方法。

     func zap(theUUID:String) {
        var recordID2Zap: String!
        let predicate = NSPredicate(format: "(theUUID = %@)",theUUID)
        let query = CKQuery(recordType: "Blah", predicate: predicate)
        let searchOperation = CKQueryOperation(query: query)
        searchOperation.desiredKeys = ["record.recordID.recordName"]
        searchOperation.recordFetchedBlock = { (record) in
            recordID2Zap = record.recordID.recordName
        }
    
            if error != nil {
                print("ting, busted",error!.localizedDescription)
            } else {
                print("ok zapping")
                if recordID2Zap != nil {
                    self.privateDB.delete(withRecordID: CKRecordID(recordName: recordID2Zap), completionHandler: {recordID, error in
                        NSLog("OK or \(error)")
                    })
                }
            }
    
        }
    
        searchOperation.qualityOfService = .background
    
        privateDB.add(searchOperation)
        theApp.isNetworkActivityIndicatorVisible = true
    }
    
    }
    

    至于您的表格视图和图像...使用 icloud 代码中的完成向表格视图发送通知。

    database.fetchRecordWithID(CKRecordID(recordName: recordId), completionHandler: {record, error in
        let directDict = ["blah": "whatever"] as [String : String]
    NotificationCenter.default.post(name: Notification.Name("blahDownloaded"), object: nil, userInfo: directDict)
    }
    

    然后在 VC 中注册所说的通知。

    NotificationCenter.default.addObserver(self, selector: #selector(blahDownloaded), name: Notification.Name("blahDownloaded"), object: nil)
    
    func blahDownloaded(notification: NSNotification) {
         if let userInfo = notification.userInfo as NSDictionary? as? [String: Any] {
    
    //update you cell
    //reload your table
    }
    

    这一切都有意义吗?

    【讨论】:

    • 我对 cloudkit 很陌生。你有没有机会写一些关于我应该怎么做的示例代码?
    【解决方案2】:

    您的操作的qualityOfService 默认为.utility

    documentation for CKOperation 中有一条重要说明:

    CKOperation 对象具有 NSQualityOfServiceUtility 的默认服务质量级别(请参阅 qualityOfService)。此级别的操作被认为是随意的,系统会根据电池电量和其他因素安排最佳时间。

    因为CKOperation 继承自NSOperation,您可以在用户等待请求完成时配置qualityOfService 属性。以下是基于您上面的一些示例代码:

    let queryOperation = CKQueryOperation(query: query)
    queryOperation.recordFetchedBlock = ...
    queryOperation.queryCompletionBlock = ...
    
    queryOperation.qualityOfService = .userInteractive
    
    publicData.add(queryOperation)
    

    请注意,此示例显式创建 CKQueryOperation 而不是使用便捷 API,因为它使您可以灵活地在将操作排入队列以发送到服务器之前对其进行完全配置。

    在这种情况下,您可以将 qualityOfService 设置为 .userInteractive,因为您的用户正在积极等待请求完成,然后才能进一步使用您的应用。在https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html了解更多可能的值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 2012-06-25
      • 2015-04-19
      • 1970-01-01
      相关资源
      最近更新 更多