Cloudkit Fetch非常慢

时间:2016-12-26 00:17:55

标签: ios swift uitableview cloudkit

运行以下代码从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


    }

2 个答案:

答案 0 :(得分:2)

您应首先搜索记录键,因此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
}

}

至于你的tableview和图片......使用你的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
}

这一切都有意义吗?

答案 1 :(得分: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

的可能值