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

标签 ios swift core-data fetch dispatch-async

我正在将 json 格式的信息从站点加载到本地核心数据。我创建了 NSManagedObject 的 2 个子类:

@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并告诉你我的结果。

最佳答案

您存钱太频繁了。尝试批量保存,例如插入 500 次左右后。

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

context.undoManager = nil

此外,您的 GCD 代码非常复杂。您查看过 NSManagedObjectContextperformBlockperformBlockAndWait API 吗?

关于ios - 从服务器数据库加载信息的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31619850/

相关文章:

c# - Xamarin.forms 自定义字体异常

ios - navigationBarItems "Type [view] cannot conform to ' View ';只有结构/枚举/类类型才能符合协议(protocol)”

ios - swift:如何在另一个 View Controller 中访问一个变量?

ios - 按属性值查找对象索引

ios - Firebase Google 登录 : get user location

iphone - Facebook IOS SDK 提要帖子可见性

ios - 在iOS上访问麦克风

ios - 如何在 Swift 中淡入和淡出 ActivityIndi​​cator?

iphone - 有适用于 MAC OS X 的免费 SQLite 管理器吗?

ios - 我可以在一个应用程序中创建一个 Core Data 对象图,然后以预设状态在另一个应用程序中使用它吗?