- 问题:**
UIView更新导致MainViewController冻结,直到UI更改更新为止。我可以使用dispatchAsync避免MainViewController冻结吗?或者这完全设置错误?
我有一个MainViewController,它有一个通过故事板连接为IBOutlet的UIView。
class MainViewController: UITableViewController {
@IBOutlet weak var headerView: MettaHeaderView!
func loadCustomView() {
DispatchQueue.main.async {
self.headerView.populateViews()
}
}
}
UIView类**的设置如下
class MettaHeaderView: UIView {
//MARK: - Properties
weak var delegate: MettaTableVC!
let dataStore = DataStore.shared
//MARK: - Outlets
@IBOutlet weak var cardView: CurvedUIView!
@IBOutlet weak var dayStack: UIStackView!
@IBOutlet weak var plusBtn: UIButton!
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var streakLbl: UILabel!
@IBOutlet weak var todayImg: UIImageView!
@IBOutlet weak var todayLbl: UILabel!
@IBOutlet weak var yesterdayImg: UIImageView!
@IBOutlet weak var yesterdayLbl: UILabel!
@IBOutlet weak var twoDayAgoImg: UIImageView!
@IBOutlet weak var twoDayAgoLbl: UILabel!
@IBOutlet weak var threeDayAgoImg: UIImageView!
@IBOutlet weak var threeDayAgoLbl: UILabel!
@IBOutlet weak var fourDayAgoImg: UIImageView!
@IBOutlet weak var fourDayAgoLbl: UILabel!
@IBOutlet weak var fiveDayAgoImg: UIImageView!
@IBOutlet weak var fiveDayAgoLbl: UILabel!
@IBOutlet weak var sixDayAgoImg: UIImageView!
@IBOutlet weak var sixDayAgoLbl: UILabel!
//MARK: - Override Methods
override func layoutMarginsDidChange() {
super.layoutMarginsDidChange()
self.layoutIfNeeded()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.endEditing(true)
}
//MARK: - Methods
func initializeHeader(with delegate: MettaTableVC) {
self.delegate = delegate
styleCardView()
let font = UIFont.systemFont(ofSize: 12)
let selectedFont = UIFont.systemFont(ofSize: 12, weight: .medium)
segmentedControl.setTitleTextAttributes([NSAttributedString.Key.font: font],
for: .normal)
segmentedControl.setTitleTextAttributes([NSAttributedString.Key.font: selectedFont],
for: .selected)
}
func styleCardView() {
self.layoutIfNeeded()
self.layoutSubviews()
cardView.curvedPercent = 0.17
setFontSize()
}
func populateViews() {
let totalDays = self.totalDays()
let dayString = totalDays == 1 ? "Day" : "Days"
self.streakLbl.text = "\(totalDays) \(dayString) with a Session"
self.setDayLbls()
self.setDayImages(with: dataStore.sessions)
}
func totalDays() -> Int {
let grouped = dataStore.sessions.group { $0.dateString }
return grouped.count
}
func setStreak(with sessions: [MeditationSession]) {
streakLbl.text = "\(currentStreak(from: sessions)) day streak"
}
func currentStreak(from sessions: [MeditationSession]) -> Int {
var streak = 0
var lastDate: Date?
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy"
for sesh in sessions {
let date = sesh.date.dateValue()
// Check if first day check complete yet
if let last = lastDate {
let difference = daysBetween(start: date, end: last)
// Check if the same day
if difference == 0 {
continue
}
// Check if day before
if difference == 1 {
lastDate = date
streak += 1
} else {
return streak
}
// If first go through
} else {
let difference = daysBetween(start: date, end: Date())
// Check if today
if difference == 0 {
lastDate = date
streak += 1
continue
}
// Check if day before
if difference == 1 {
lastDate = date
streak += 1
} else {
return streak
}
}
}
return streak
}
func daysBetween(start: Date, end: Date) -> Int {
let cal = Calendar(identifier: .gregorian)
let date1 = cal.startOfDay(for: start)
let date2 = cal.startOfDay(for: end)
return Calendar.current.dateComponents([.day], from: date1, to: date2).day!
}
func setDayLbls() {
let lbls: [UILabel] = [sixDayAgoLbl, fiveDayAgoLbl, fourDayAgoLbl, threeDayAgoLbl, twoDayAgoLbl, yesterdayLbl, todayLbl]
let formatter = DateFormatter()
formatter.dateFormat = "EEEE"
let todayString = formatter.string(from: Date())
guard let today = Day(rawValue: todayString.lowercased()) else { return }
let week = past7Days(from: today)
for (index, val) in week.enumerated() {
lbls[index].text = val
}
}
func setFontSize() {
let labels: [UILabel] = [sixDayAgoLbl, fiveDayAgoLbl, fourDayAgoLbl, threeDayAgoLbl, twoDayAgoLbl, yesterdayLbl, todayLbl]
labels.forEach {
let size: CGFloat = ($0.superview?.frame.width)! * 0.42
$0.font = $0.font.withSize(size)
}
}
func past7Days(from day: Day) -> [String] {
var dayStrings: [String] = []
var currentIndex: Int = day.order
let days = Day.allCasesOrdered
for _ in 0..<7 {
print("here")
let day = days[currentIndex]
dayStrings.append(day.letter)
if currentIndex > 0 {
currentIndex -= 1
} else {
currentIndex = 6
}
}
return dayStrings.reversed()
}
func setDayImages(with sessions: [MeditationSession]) {
let dayImgViews: [UIImageView] = [todayImg, yesterdayImg, twoDayAgoImg, threeDayAgoImg, fourDayAgoImg, fiveDayAgoImg, sixDayAgoImg]
var date: Date = Date()
for index in 0...6 {
print(index)
let filtered = sessions.filter { $0.dateString == date.dateString() }
dayImgViews[index].image = filtered.count == 0 ? #imageLiteral(resourceName: "Lotus_Monochromatic") : #imageLiteral(resourceName: "Lotus")
date = Calendar.current.date(byAdding: .day, value: -1, to: date)!
}
}
在MainViewController中调用下面的函数会冻结整个VC,直到函数完成。有什么方法可以避免此问题或修复此问题吗?
自定义标题视图填充视图()
- 冻结:**
这意味着整个屏幕将被冻结,直到该功能完成。
所以我发现这个问题是因为这个功能,但我不确定为什么会发生冻结:
func setDayImages(with sessions: [MeditationSession]) {
let dayImgViews: [UIImageView] = [headerView.todayImg, headerView.yesterdayImg, headerView.twoDayAgoImg, headerView.threeDayAgoImg, headerView.fourDayAgoImg, headerView.fiveDayAgoImg, headerView.sixDayAgoImg]
var date: Date = Date()
for index in 0...6 {
print(index)
let filtered = sessions.filter { $0.dateString == date.dateString() }
dayImgViews[index].image = filtered.count == 0 ? #imageLiteral(resourceName: "Lotus_Monochromatic") : #imageLiteral(resourceName: "Lotus")
date = Calendar.current.date(byAdding: .day, value: -1, to: date)!
}
}
1条答案
按热度按时间vsaztqbk1#
func setDayImages(with sessions: [MeditationSession])
末尾概述的函数将图像插入UIImageViews,这意味着需要将每个图像作为位图加载到内存中,这是一个相当繁重的操作,您将在MainViewController的主线程上运行它。我的解决方案是在主线程外将图像加载到UIImage()中,然后在主线程上对其进行赋值,看看这是否能提高性能,通常建议使用GCD在主线程外执行与UI无关的计算(例如
DispatchQueue.global(.userInitiated).async
)。这是我最好的猜测,至少没有额外的性能诊断。