【问题标题】:Swift how to set cache tag value in UITableView for multiple sectionsSwift如何在UITableView中为多个部分设置缓存标记值
【发布时间】:2017-01-09 23:39:23
【问题描述】:

我是 Swift 的新手。我正在尝试在我的表格视图中显示图像。我正在关注这个tutorial

在我的UITableView中,如图所示tutorial。我将图像存储在缓存中。如果 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
      }   
    }

【问题讨论】:

  • 尝试使用tag - (一个整数,可用于识别应用程序中的视图对象。)而不是indexPath.row
  • @Rahul 抱歉,请您详细说明您的评论
  • 为什么不使用 URL 字符串作为缓存的键?这样如果同一张图片多行、多节或者行数发生变化,缓存就会有效
  • 为什么不使用 img_url 作为字典中图像的键。这样,您可以从 myList 获取 img_url,然后查看该 url 的缓存中是否存在图像。那么你就不用担心行和节了
  • @Paulw11 是的,谢谢你的想法。我将使用 URL 字符串。谢谢。

标签: ios swift uitableview caching


【解决方案1】:

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

  • 行号更改(不正确的缓存命中)
  • 有多个部分(只是您发现的一般恶心)
  • 同一图像用于多行(不必要的缓存未命中)。

您可以轻松修改 cellForRowAtIndexPath 以使用 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  
}

您的代码也不是很有防御性。如果数据不正确,有很多强制解包会给你一个异常

【讨论】:

    【解决方案2】:

    您也可以使用tag。这是使用标签值的代码。此外,您可能需要考虑代码中的错误处理。

    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
    }
    

    【讨论】:

      【解决方案3】:

      问题是您使用row 引用缓存所有图像,但如果您的UITableView 有多个部分,它将具有重复的行值。例如:

      第 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) 只需使用如下库:https://github.com/Haneke/HanekeSwift

      【讨论】:

        猜你喜欢
        • 2012-11-04
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-29
        相关资源
        最近更新 更多