从服务器数据库加载信息的更好方法

时间:2015-07-24 21:12:03

标签: ios swift core-data fetch dispatch-async

我正在从json中的网站加载信息到本地Core Data。我创建了两个NSManagedObject的子类:

@objc(Category)
class Category: NSManagedObject {
    @NSManaged var id: NSNumber
    @NSManaged var name: String
}

@objc(Event)
class Event: NSManagedObject {
    @NSManaged var category: String
    @NSManaged var date: String
    @NSManaged var event: String
    @NSManaged var location: String
    @NSManaged var time: String
}

以下是我在后台加载信息的代码:

func loadAllData(){
    println("loading all data")

    progressCounter = 0

    let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());

    dispatch_source_set_event_handler(source) {
        [unowned self] in
        self.progressCounter += dispatch_source_get_data(source)
        self.progressView.setProgress(Float(self.progressCounter) / Float(self.maxValue), animated: true)
    }

    dispatch_resume(source)

    let params = ServerConstants.infoParam + "=true"

    // creating request, set its method to POST and append params to request
    var request = NSMutableURLRequest(URL: NSURL(string: ServerConstants.getInfoURL)!)
    request.HTTPMethod = "POST"
    request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    //request.setValue("Basic \(base64LoginString!)", forHTTPHeaderField: "Authorization")

    //start loading data in background
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
        var session = NSURLSession.sharedSession()
        var task = session.dataTaskWithRequest(request){ (data, response, error) -> Void in
            if error == nil {
                let json = JSON(data: data)

                //println(json)
                self.maxValue = Float(json["categories"].count + json["events"].count)
                println("maxself. - \(self.maxValue)")

                var array = json["categories"]
                var maxIndex = array.count

                var error: NSError?
                for var i: Int = 0; i < maxIndex; i++ {
                    if let moc = self.context {
                        let newItem = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: self.context!) as! Category

                        newItem.id = array[i]["id"].string!.toInt()!
                        newItem.name = array[i]["name"].string!

                        dispatch_source_merge_data(source, 1);
                        moc.save(&error)
                    }
                }

                array = json["events"]
                maxIndex = array.count

                for var i: Int = 0; i < maxIndex; i++ {
                    if let moc = self.context {
                        let newItem = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: moc) as! Event

                        newItem.category = array[i]["category"].string!
                        newItem.event = array[i]["event"].string!
                        newItem.location = array[i]["location"].string!
                        newItem.date = array[i]["date"].string!
                        newItem.time = array[i]["time"].string!

                        dispatch_source_merge_data(source, 1);
                        moc.save(&error)
                    }
                }                
                println("done")
                dispatch_async(dispatch_get_main_queue()){
                    self.showScreenElements()
                }
            }
        }
        task.resume()
    }
}

我的服务器数据库大约有3600行,下载过程需要大约30-40秒才能加载。

有没有更好的方法来更快地获取服务器的json?

当我试图在200次迭代时只保存一次时,它会抛出一个错误

  

EXC_BAD_ACCESS

for var i: Int = 0; i < maxIndex; i++ {
    if let moc = self.context {
        let newItem = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: moc) as! Event
        newItem.category = array[i]["category"].string!
        ...
        dispatch_source_merge_data(source, 1);
        if i % 200 == 0 {
            moc.save(&error)
        }
    }
}
self.context!.save(&error)
println("done")

我会尝试使用performBlock并告诉你我的结果。

1 个答案:

答案 0 :(得分:0)

你经常保存。尝试分批保存,比如500次左右插入后。

此外,尝试切换此操作的上下文的撤消管理器。假设您有一个可以丢弃的子环境:

context.undoManager = nil

此外,您的GCD代码非常复杂。您是否查看了performBlock的{​​{1}}和performBlockAndWait API?