从CoreData加载TableView图像时出现错误和慢速滚动

时间:2015-04-11 14:52:52

标签: core-data uiimage tableview nsurlsession nsurlsessiondatatask

问题: 使用存储在Core Data DB中的路径将图像加载到表视图的过程工作正常,但用户体验不顺利。卷轴很慢而且有错误。

进口商备注:

  • 对于我的本地数据库,我使用核心数据
  • 我没有将图像保存在Core Data中,只保存它们的路径(图像名称)
  • 对于表视图DataSource,我使用Person类型的数组,其中包含ID和Img名称(TableView行等于array.Count)。 - 这是我的Json(查看) - Json Link
  • 的网址
  • Core Data DB中的所有对象
  • 据我所知,我在Main theard中完成了所有UI更新
  • 每次检查后重新加载tableview。

这是采取正确顺序的步骤:

使用NSURLSession - DataTask获取数据。之后"解析"它并检查Core Data DB中是否存在每个对象(在for循环中),并将其变量附加到TableView数据源数组,然后重新加载数据

1)

let request = NSMutableURLRequest(URL: dataSourceURL!)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
    data, response, error in

    if error != nil {
        println("error=\(error)")
        return
    }
    if data != nil {
        let datasourceDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSDictionary

        var  DataArray =  datasourceDictionary["descisions"] as NSArray

//Convert it to useable array

        for var i = 0 ; i < DataArray.count ; i++ {
            let ID_s = DataArray[i]["ID"]! as Int

//For each Object from the Json array i'm check if he is exisitng in the local DB
            var ConvertetdID = Int32(ID_s)
            let object : Lockdown? =        self.CheckIfObjectExistInDBbyID(ConvertetdID)

//CheckIfExists - if it does , it return an object with the correct values

            if  object != nil  {
                //exists - load file from Core Data
                let imgname = object!.imgPath
                let photoRecord = PhotoRecord(name:"\(ConvertetdID)", url:imgname)
                self.photos.append(photoRecord)

//TableView object array (photos)

                dispatch_async(dispatch_get_main_queue())  {
                self.tableView.reloadData()

//After each check reload the tableView   
            }
        }
    }
}
task.resume()

检查Core Data DB中是否存在的方法(该方法接收ID并返回对象(如果存在),否则返回nil:

 func CheckIfObjectExistInDBbyID(id : Int32) -> Lockdown? {
        let appDelegate =
        UIApplication.sharedApplication().delegate as AppDelegate

        let managedContext = appDelegate.managedObjectContext!
        var request : NSFetchRequest = NSFetchRequest(entityName: "Lockdown")
        request.predicate = NSPredicate(format: "id = %d", id)
        var error : NSError?
        request.fetchLimit = 1
        var count : Int = managedContext.countForFetchRequest(request,error: &error)
        if count == 0 {
           // println("Error : \(error?.localizedDescription)")
            println("Object \(id) Dosent exist in CoreData")

            return nil

        }
        println("Object \(id)  exist in CoreData")


        let result = managedContext.executeFetchRequest(request, error: &error) as NSArray!
        let lockdown = result.objectAtIndex(0) as Lockdown
        println(lockdown.id)
        return lockdown




    }

cellForRowAtIndexPath方法

 let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as UITableViewCelllet photoDetails = photos[indexPath.row]





  cell.textLabel.text = photoDetails.name as String
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
        var myPathList : NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true)

        var myPath = myPathList[0] as String
        myPath = myPath.stringByAppendingPathComponent("\(photoDetails.name).png")
        var image : UIImage = UIImage(contentsOfFile: myPath)!

        dispatch_async(dispatch_get_main_queue()) {

            cell.imageView.image = image
        }
    }

return cell

有什么建议是什么原因造成的?

1 个答案:

答案 0 :(得分:0)

您不应该总是从磁盘加载图像,它很慢。而是首次从磁盘加载映像,然后将其存储在缓存中(在内存中)。在从磁盘加载图像之前检查图像是否被缓存。

如果缓存太大或者出现内存警告,则需要清空缓存。

高级版本可以为当前滚动位置正下方的单元格预先缓存一些图像。

你可能可以使用一个库,也许是带有文件URL的SDWebImage(我没试过这个)。

错误部分是因为您的异步块在加载图像之前未检查该单元格是否未被重用。如果有,那么错误的图像将出现在重用的单元格上(直到它被另一个图像替换)。要修复,请捕获块中的indexPath,并在加载图像后获取indexPath的单元格 - 如果表格视图返回nil,则单元格不再可见除了缓存图像以备将来使用外,还需要做任何其他事情。