【问题标题】:Unable to refresh core data and display it in tableview using UIRefreshControl无法使用 UIRefreshControl 刷新核心数据并将其显示在 tableview 中
【发布时间】:2015-02-12 06:56:22
【问题描述】:

我正在从博客中获取 json 数据并将其存储在核心数据中。现在我想添加拉刷新,这样如果博客上有任何更新,它们也会反映在应用程序中。我发现了一个类似问题的帖子,它建议添加此代码

 override func viewDidLoad() {
    refresher = UIRefreshControl()
    refresher.attributedTitle = NSAttributedString(string: "Pull to Refresh")
    refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refresher)
}

func refresh() {
    NSFetchedResultsController.deleteCacheWithName("Master")
    var error: NSError? = nil
    self.fetchedResultsController.performFetch(&error)
    self.tableView.reloadData()
    println("refreshed")

       }

问题是下拉刷新后coredata和tableview都没有更新。

核心数据中获取和保存json数据的代码如下:

func animalSelected(animal: Animal) {

var appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
var context: NSManagedObjectContext = appDel.managedObjectContext!
let session = NSURLSession.sharedSession()
var error : NSError?

let task = session.dataTaskWithURL(animal.url!, completionHandler: {data, response, error -> Void in

    if (error != nil){
        println(error)

    }else{

        var request = NSFetchRequest(entityName: "MIBlog")
        request.returnsObjectsAsFaults = false
        var results = context.executeFetchRequest(request, error: nil)

        for result in results!
        {
            context.deleteObject(result as NSManagedObject)
            context.save(nil)

        }


        let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

        var posts = [[String:String]()]

        var post:AnyObject

        var authorDictionary:AnyObject
        var newBlogItem:NSManagedObject
        for var i = 0; i < jsonResult["posts"]!.count; i++
        {
            posts.append([String:String]())
            post = jsonResult["posts"]![i] as NSDictionary
            posts[i]["title"] = post["title"] as? NSString
            posts[i]["publishedDate"] = post["date"] as? NSString
            posts[i]["content"] = post["content"] as? NSString
            authorDictionary = post["author"] as NSDictionary
            posts[i]["author"] = post["name"] as? NSString


            newBlogItem = NSEntityDescription.insertNewObjectForEntityForName("MIBlog", inManagedObjectContext: context) as NSManagedObject
            newBlogItem.setValue(posts[i]["title"], forKey: "title")
            newBlogItem.setValue(posts[i]["publishedDate"], forKey: "publishedDate")  
            newBlogItem.setValue(posts[i]["content"], forKey: "content")
            newBlogItem.setValue(posts[i]["author"], forKey: "author")

            context.save(nil)

        }
        request = NSFetchRequest(entityName: "MIBlog")
        request.returnsObjectsAsFaults = false
        results = context.executeFetchRequest(request, error: nil)

    }

})

task.resume()

delegate?.collapseSidePanels?()

}

我的 fetchResultController 代码:

 // MARK: - Fetched results controller

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
        }
        var appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        self.managedObjectContext = appDel.managedObjectContext

        let fetchRequest = NSFetchRequest()
        // Edit the entity name as appropriate.
        let entity = NSEntityDescription.entityForName("MIBlog", inManagedObjectContext: self.managedObjectContext!)
        fetchRequest.entity = entity

        // Set the batch size to a suitable number.
        fetchRequest.fetchBatchSize = 20

        // Edit the sort key as appropriate.
        let sortDescriptor = NSSortDescriptor(key: "publishedDate", ascending: false)
        let sortDescriptors = [sortDescriptor]

        fetchRequest.sortDescriptors = [sortDescriptor]

        // Edit the section name key path and cache name if appropriate.
        // nil for section name key path means "no sections".
        let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
        aFetchedResultsController.delegate = self
        _fetchedResultsController = aFetchedResultsController

        var error: NSError? = nil
        if !_fetchedResultsController!.performFetch(&error) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            //println("Unresolved error \(error), \(error.userInfo)")
            abort()
        }

        return _fetchedResultsController!
}
var _fetchedResultsController: NSFetchedResultsController? = nil

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    self.tableView.beginUpdates()


}

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
    switch type {
    case .Insert:
        self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
    case .Delete:
        self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
    default:
        return
    }
}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath) {
    switch type {
    case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    case .Update:
        self.configureCell(tableView.cellForRowAtIndexPath(indexPath)!, atIndexPath: indexPath)
    case .Move:
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
    default:
        return
    }
        }

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    self.tableView.endUpdates()
           activityIndicator.stopAnimating()
}

我不知道在刷新时应该如何更新核心数据。

请帮忙。

【问题讨论】:

    标签: swift core-data nsfetchedresultscontroller pull-to-refresh uirefreshcontrol


    【解决方案1】:

    当您使用NSFetchedResultsController 时,您只需要正确实现NSFetchedResultsControllerDelegate 方法。那么你所要做的就是保存。

    context.save(nil)
    

    一些备注:

    我认为在循环内保存不是一个好主意。插入所有对象后最好在最后保存。

    全部删除再重新插入没有太大意义。相反,您应该只更改那些有变化的对象。

    当完成块返回时,变量results 将被丢弃。不清楚你想用这个获取结果来完成什么。

    如果您没有实现获取结果控制器委托,则需要再次调用performFetch,或者简单地将获取结果控制器设置为nil,然后让它懒惰地重新创建自己。然后只需更新应该从获取的结果控制器自动获取数据的 UI

    self.tableView.reloadData()
    

    【讨论】:

    • 我是 iOS 开发新手,我实施的方法是在 Udemy 的在线课程中提出的。但是,您是否建议我只需在刷新函数中添加context.save(nil)??
    • 这就是NSFetchedResultsControllerDelegate 的工作原理。使用您在创建新项目并检查“核心数据”时会找到的 Xcode 样板代码。
    • 是的,先生。我在创建项目时检查了核心数据。我已经更新了我的问题以显示 FetchedResultsController 。我想知道在 Refresh 函数中应该做些什么,以便核心数据和 tableView 在 pull to refresh 时都得到更新。
    • 看答案。 nil 出 FRC 和 reloadData()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    相关资源
    最近更新 更多