Ios Swift如何在UITableView中为多个节设置缓存标记值

Ios Swift如何在UITableView中为多个节设置缓存标记值,ios,swift,uitableview,caching,Ios,Swift,Uitableview,Caching,我不熟悉斯威夫特。我正在尝试在我的tableview中显示图像。我正在关注这一点 在myUITableView中,如下图所示。我正在缓存中存储图像。如果tableview只有一个部分,则此操作非常有效。如果我的tableview中有多个分区,我应该如何设置forKey值 如何根据节和行设置该值self.cache.setObject(image!,forKey:indexPath.row)?谢谢 这是我的UITableView func numberOfSectionsInTableView(t

我不熟悉斯威夫特。我正在尝试在我的tableview中显示图像。我正在关注这一点

在my
UITableView
中,如下图所示。我正在缓存中存储图像。如果tableview只有一个部分,则此操作非常有效。如果我的tableview中有多个分区,我应该如何设置
forKey
值 如何根据节和行设置该值
self.cache.setObject(image!,forKey:indexPath.row)
?谢谢

这是我的
UITableView

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    if(tableView == tableview){
        return categoryArray.count
    }else{
        return 1
    }
}

func tableView(tableView : UITableView,  titleForHeaderInSection section: Int)->String
{
    if(tableView == tableview){
        return categoryArray.objectAtIndex(section) as! String
    }else{
        return ""
    }
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    if(tableView == tableview){
        print("Count = \(myList[section].count)")
        return myList[section].count
    }
    else{
        return 5
    }

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    if(tableView == tableview) {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomEventCell

cell.cellBackgroundImg.image = UIImage(named: "placeholder")


        if (self.cache.objectForKey(indexPath.row) != nil){
            print("Cached image used, no need to download it")
            cell.cellBackgroundImg?.image = self.cache.objectForKey(indexPath.row) as? UIImage
        }else{

            let img_url = myList[indexPath.section].objectAtIndex(indexPath.row).objectForKey("image") as? String

            if img_url != nil{
                print("Load the image from URL")
                let url = NSURL(string: img_url!)!
                let request = NSMutableURLRequest(URL:url)
                let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
                let task = defaultSession.dataTaskWithRequest(request, completionHandler: {(data:NSData?, response:NSURLResponse?, error: NSError?) in

        dispatch_async(dispatch_get_main_queue(), { () -> Void in

                        let image = UIImage(data: data!)
                        cell.cellBackgroundImg?.image = image
                        self.cache.setObject(image!, forKey:indexPath.row)
                    })
                })
                task.resume()

            }
        }
        return cell
      }   
    }

问题是您正在使用
引用缓存所有图像,但是如果
UITableView
包含多个节,则会重复行值。例如:

self.cache.setObject(image!, forKey:"\(indexPath.section)-\(indexPath.row")))
self.cache.objectForKey(indexPath.row)
第0节>第0行、第1行、第2行 第1节>第0行,第1行 第2节>第0行

所有部分都有“第0行”

要解决此问题,您必须执行以下操作:

1) 创建格式化键,如“SECTION-ROW”,例如:

self.cache.setObject(image!, forKey:"\(indexPath.section)-\(indexPath.row")))
self.cache.objectForKey(indexPath.row)

2) 只需使用lib,比如:

本教程的作者在选择使用
indexPath.row
作为缓存键时似乎犯了一个错误。行号与图像的链接非常微弱;标识图像的东西是它的URL。通过使用该行,将出现以下问题:

  • 行号更改(缓存命中错误)
  • 有多个部分(正如您所发现的,只是一般的不愉快)
  • 同一映像用于多行(不必要的缓存未命中)
您可以轻松修改
cellforrowatinexpath
以使用URL作为缓存键:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell = UITableViewCell()
    if(tableView == tableview) {
        let customCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomEventCell
        customCell.cellBackgroundImg.image = UIImage(named: "placeholder")

        if let img_url = myList[indexPath.section].objectAtIndex(indexPath.row).objectForKey("image") as? String {

            if let image = self.cache.objectForKey(img_url) as? UIImage {
                print("Cached image used, no need to download it")
                cell.cellBackgroundImg?.image = image
            } else {
                print("Load the image from URL")
                if let url = NSURL(string: img_url)
                    let request = NSMutableURLRequest(URL:url)
                    let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
                    let task = defaultSession.dataTaskWithRequest(request, completionHandler: {(data:NSData?, response:NSURLResponse?, error: NSError?) in

                        guard let downloadData= data && error == nil else {
                            print("error downloading image:\(error)"
                            return
                         }
                         dispatch_async(dispatch_get_main_queue(), { () -> Void in
                             if let image = UIImage(data: data) {
                                 customCell.cellBackgroundImg?.image = image
                                 self.cache.setObject(image, forKey:img_url)
                             }  
                          })
                    })
                    task.resume()
                }
           }
        }
        cell = customCell
    }
    return cell  
}

你的代码也不是很有防御性。有很多强制展开,如果数据不正确,会给你一个例外

你也可以使用
标签
。下面是使用标记值的代码。此外,您可能需要考虑代码中的错误处理。
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell = UITableViewCell()
    if(tableView == tableview) {
        let customCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomEventCell

      customCell.eventTitle.text = title
        customCell.cellBackgroundImg.image = UIImage(named: "placeholder")
        // calculate tagValue and set it to cache objectForKey
       // here I have taken big numbers so same number will not repeat 
        let tagValue = (indexPath.section * 100) + indexPath.row + 200

        if (self.cache.objectForKey(tagValue) != nil){
            print("Cached image used, no need to download it")
            customCell.cellBackgroundImg?.image = self.cache.objectForKey(tagValue) as? UIImage
        }else{

            let img_url = myList[indexPath.section].objectAtIndex(indexPath.row).objectForKey("image") as? String

            if img_url != nil{
                print("Load the image from URL")
                let url = NSURL(string: img_url!)!
                let request = NSMutableURLRequest(URL:url)
                let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
                let task = defaultSession.dataTaskWithRequest(request, completionHandler: {(data:NSData?, response:NSURLResponse?, error: NSError?) in

                    if error != nil {
                        print(error)
                        return
                    }else if(data != nil){
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            let image = UIImage(data: data!)
                            customCell.cellBackgroundImg?.image = image
                            self.cache.setObject(image!, forKey:tagValue)
                        })
                    }else {
                        print("Error : Image data is nil")
                    }
                })
                task.resume()
            }
            else {
                print("Error : Image URL is nil")
            }

        }
       cell = customCell
    }
    return cell
}

尝试使用
tag
-(一个可以用来标识应用程序中视图对象的整数)而不是
indexPath.row
@Rahul抱歉,请详细说明您的评论。为什么不使用URL字符串作为缓存的键?。这样,如果同一图像用于多行、多节或行数更改,而不使用img_url作为字典中图像的键,则缓存将有效。通过这种方式,您可以从myList获取img_url,然后查看该url的缓存中是否存在图像。这样你就不必担心行和行了sections@Paulw11是的,谢谢你的主意。我将使用URL字符串。谢谢