我目前正在使用包含三个部分的tableview。每个部分从一个从后端加载的数组加载它的数据,并存储在本地数组中。数据下载和显示没有问题,但是一旦我滚动,单元格会重新加载它们以前的数据。在内存警告之外我抓住它的原因是单元格包含带阴影的图像,每个卷轴的阴影变暗。我觉得这个问题与我在indexPath上为每个部分调用单元格的方式有关,但似乎无法找到解决方案。我已经四处搜索,但还没能找到解决方案。
这些单元格共享相同的自定义类,并通过相同的插座重新加载它们各自的数据。 不确定这是否与问题相关,但是视图是从AppDelegate中的信息调用的。 这是我正在处理的代码,其中包含了部分行数。
覆盖func tableView(tableView:UITableView,numberOfRowsInSection section:Int) - > Int {
if section == 0 {
return likesName.count
} else if section == 1 {
return commentsName.count
} else if section == 2 {
return bookmarksName.count
}
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("toggleCell", forIndexPath:indexPath) as! RightToggleCell
cell.userAvatar.layer.cornerRadius = cell.userAvatar.frame.size.width/2
cell.userAvatar.clipsToBounds = true
cell.artworkImage.contentMode = UIViewContentMode.ScaleAspectFill
cell.artworkImage.clipsToBounds = true
cell.artistName.text = likesName[indexPath.row]
cell.information.text = "liked your artwork"
likesImage[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.artworkImage.image = downloadedImage
}
}
likesAvatar[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.userAvatar.image = downloadedImage
}
}
} else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("toggleCell", forIndexPath:indexPath) as! RightToggleCell
cell.userAvatar.layer.cornerRadius = cell.userAvatar.frame.size.width/2
cell.userAvatar.clipsToBounds = true
cell.artworkImage.contentMode = UIViewContentMode.ScaleAspectFill
cell.artworkImage.clipsToBounds = true
cell.artistName.text = commentsName[indexPath.row]
cell.information.text = commentsInformation[indexPath.row]
commentsImage[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.artworkImage.image = downloadedImage
}
}
commentsAvatar[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.userAvatar.image = downloadedImage
}
}
} else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCellWithIdentifier("toggleCell", forIndexPath:indexPath) as! RightToggleCell
cell.userAvatar.layer.cornerRadius = cell.userAvatar.frame.size.width/2
cell.userAvatar.clipsToBounds = true
cell.artworkImage.contentMode = UIViewContentMode.ScaleAspectFill
cell.artworkImage.clipsToBounds = true
cell.artistName.text = bookmarksName[indexPath.row]
cell.information.text = "bookmarked your artwork"
bookmarksImage[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.artworkImage.image = downloadedImage
}
}
bookmarksAvatar[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
cell.userAvatar.image = downloadedImage
}
}
}
return cell
}
答案 0 :(得分:1)
排队代码有点困难,但看起来你有:
let cell = ...
if ... {
let cell = ...
} else if ... {
let cell = ...
}
return cell
如果这是您所拥有的内容,则每个let cell
中的if
仅限定在if
内。因此,最后的return cell
将返回初始的空单元格。如果是这种情况,您应该将其更改为:
if ... {
let cell = ...
return cell
} else if ... {
let cell = ...
return cell
} else {
let cell = ...
return cell
}
请注意,最后一个条件必须是else
而不是else if
,否则编译器会告诉您并非所有代码路径都返回一个值(最后一个"如果"失败) 。但是,你说它基本上是有效的,所以有些事情没有意义。
无论哪种方式,一旦一行离开屏幕,单元格就会被重新用于新行。因此,当您的getDataInBackgroundWithBlock
返回时,该单元格可能属于另一行。鉴于阴影越来越暗,听起来像RightToggleCell
中的代码在重复使用单元格时会重新运行。
在后台加载数据时,应将其存储在单元格之外,并在加载完成后重新加载该行。某事(非常粗略地)沿着以下几点:
likesImage[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
artworkImages[indexPath.row] = downloadedImage
dispatch_async(dispatch_get_main_queue(), {
tableView.reloadRowsAtIndexPaths([indexPath.row], withRowAnimation: true)
})
}
}
cellForRowAtIndexPath
应显示相关的图片图像(如果可用),或者如果没有则使用上述代码。请注意,UI的任何更新都必须在主线程上完成,这就是上面调用dispatch_async
的原因。
答案 1 :(得分:0)
我建议您将此代码放入" RightToggleCell"。
而不是在TableViewController上执行所有操作。override func awakeFromNib() {
self.userAvatar.layer.cornerRadius = self.userAvatar.frame.size.width/2
self.userAvatar.clipsToBounds = true
self.artworkImage.contentMode = UIViewContentMode.ScaleAspectFill
self.artworkImage.clipsToBounds = true
}
通过这样做,iOS每次重新加载TableView时都不会修改cornerRadius和clipsToBounds
答案 2 :(得分:0)
在迈克尔的指导下,我在每个if语句中移动了返回单元格,并在语句之外返回了UITableViewCell()并解决了问题。再次感谢迈克尔,我投了你的回复,但我没有足够的声誉来发布。