Ios Swift如何在UITableView中为多个节设置缓存标记值
我不熟悉斯威夫特。我正在尝试在我的tableview中显示图像。我正在关注这一点 在myIos 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
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字符串。谢谢