在我的 iOS 项目中,我使用带有自定义单元格的常规 UICollectionView
。
该单元格接收一些属性,当其中一个对象被设置时,我对该单元格执行一些 UI 更新。
虽然当我滚动时我感觉到滚动有轻微的故障,但我不知道如何改进我的代码以使其运行更流畅。
我运行了 Intruments 并运行了 Time Profiler,当出现这些滞后时,主线程 CPU 使用率达到 100%,如您在此图中所见:
跟踪它在工具中的使用百分比:
进一步追踪到 png_read_IDAT_data
现在看代码:
在我的 UICollectionViewController cellForItem(:_)
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: homeCellId, for: indexPath) as! HomePostCollectionViewCell
cell.post = self.posts[indexPath.item]
cell.delegate = self
cell.layer.cornerRadius = 5
cell.layer.borderWidth = 0.7
cell.layer.borderColor = UIColor.rgb(red: 204, green: 204, blue: 204).cgColor
cell.layer.masksToBounds = true
return cell
}
在我的 UICollectionViewCell
中,每当设置 post
变量时,我都会执行以下 UI 更新:
public var post: Post? {
didSet {
guard let post = self.post else { return }
userProfileImageView.image = post.user.profileImage
nameLabel.text = post.user.name
titleTextView.text = post.title
creationDateLabel.text = post.creationDate.timeAgoDisplay()
thumbnailImageView.image = post.thumbnail
if backgroundImageOffset != nil {
setBackgroundImageOffset(imageOffset: backgroundImageOffset)
} else {
setBackgroundImageOffset(imageOffset: CGPoint.zero)
}
}
}
你能帮我追踪这个问题以及如何改进它吗?
谢谢。
编辑
我已经注释掉了 cell.post=
行,这样做主线程 CPU 使用率下降到大约 10%,因此可以确保问题出在 post { didSet{} }
构造函数。
你能看到有什么有用的改进吗?
编辑2
这里是timeAgoDisplay()
函数的代码
func timeAgoDisplay() -> String {
let secondsAgo = Int(Date().timeIntervalSince(self))
let minute = 60
let hour = 60 * minute
let day = 24 * hour
let week = 7 * day
let month = 4 * week
let quotient: Int
let unit: String
if secondsAgo < minute {
quotient = secondsAgo
unit = "second"
} else if secondsAgo < hour {
quotient = secondsAgo / minute
unit = "min"
} else if secondsAgo < day {
quotient = secondsAgo / hour
unit = "hour"
} else if secondsAgo < week {
quotient = secondsAgo / day
unit = "day"
} else if secondsAgo < month {
quotient = secondsAgo / week
unit = "week"
} else {
quotient = secondsAgo / month
unit = "month"
}
return "\(quotient) \(unit)\(quotient == 1 ? "" : "s") ago"
}
最佳答案
我也遇到过像你这样的问题,认为 UIImage(data:)
可以在后台线程上使用,然后将结果图像应用到 UIImageView
在 main
队列上。
然而事实并非如此,引用了关于这个主题的一个很好的答案 UIImage initWithData: blocking UI thread from async dispatch? :
UIImage doesn't read and decode the image until the first time it's actually used/drawn. To force this work to happen on a background thread, you have to use/draw the image on the background thread before doing the main thread -setImage: call. Many folks find this counter-intuitive. I explained this in considerable detail in another answer.
如上所示,链接中的答案表明您必须在使用图像之前在后台线程上use/draw
图像。
这是我发现如何在后台线程上强制解压的示例:
希望这有帮助:)
关于ios - UICollectionView 滚动故障/滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49979263/