Skip to content

Commit 98d5b77

Browse files
committed
Optimize TopTotalsCell to add rows only when the cell loads
TopTotalsCell was calling addRows on every configuration of cell which in turn created and added a hierarchy of UIStackView-based views. Optimizing TopTotalsCell to only add rows once and then make manipulations on existing rows.
1 parent 935b373 commit 98d5b77

File tree

2 files changed

+100
-24
lines changed

2 files changed

+100
-24
lines changed

WordPress/Classes/ViewRelated/Stats/Extensions/UITableViewCell+Stats.swift

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,84 @@ extension UITableViewCell {
7171
}
7272

7373
}
74+
75+
extension UITableViewCell {
76+
struct StatsTotalRowConfiguration {
77+
let limitRowsDisplayed: Bool
78+
let rowDelegate: StatsTotalRowDelegate?
79+
let referrerDelegate: StatsTotalRowReferrerDelegate?
80+
let viewMoreDelegate: ViewMoreRowDelegate?
81+
}
82+
83+
func addDefaultTotalRows(toStackView rowsStackView: UIStackView) {
84+
for _ in 0..<StatsDataHelper.maxRowsToDisplay {
85+
let row = StatsTotalRow.loadFromNib()
86+
rowsStackView.addArrangedSubview(row)
87+
}
88+
89+
let emptyRow = StatsNoDataRow.loadFromNib()
90+
rowsStackView.addArrangedSubview(emptyRow)
91+
92+
let viewMoreRow = ViewMoreRow.loadFromNib()
93+
rowsStackView.addArrangedSubview(viewMoreRow)
94+
}
95+
96+
func configureTotalRows(_ dataRows: [StatsTotalRowData],
97+
inStackView rowsStackView: UIStackView,
98+
forType statType: StatType,
99+
configuration: StatsTotalRowConfiguration) {
100+
101+
guard !dataRows.isEmpty else {
102+
configureForNoData(inStackView: rowsStackView, forType: statType)
103+
return
104+
}
105+
106+
let numberOfRowsToAdd = calculateNumberOfRowsToAdd(from: dataRows, withConfiguration: configuration)
107+
108+
rowsStackView.arrangedSubviews.enumerated().forEach { index, view in
109+
configure(view: view, at: index, in: dataRows, numberOfRowsToAdd: numberOfRowsToAdd, configuration: configuration)
110+
}
111+
}
112+
113+
private func configureForNoData(inStackView rowsStackView: UIStackView, forType statType: StatType) {
114+
rowsStackView.arrangedSubviews.forEach { view in
115+
if let emptyRow = view as? StatsNoDataRow {
116+
emptyRow.isHidden = false
117+
emptyRow.configure(forType: statType)
118+
} else {
119+
view.isHidden = true
120+
}
121+
}
122+
}
123+
124+
private func calculateNumberOfRowsToAdd(from dataRows: [StatsTotalRowData], withConfiguration configuration: StatsTotalRowConfiguration) -> Int {
125+
if configuration.limitRowsDisplayed {
126+
return min(dataRows.count, StatsDataHelper.maxRowsToDisplay)
127+
}
128+
return dataRows.count
129+
}
130+
131+
private func configure(view: UIView, at index: Int, in dataRows: [StatsTotalRowData], numberOfRowsToAdd: Int, configuration: StatsTotalRowConfiguration) {
132+
switch view {
133+
case let view as StatsNoDataRow:
134+
view.isHidden = true
135+
case let view as ViewMoreRow:
136+
configureViewMoreRow(view, at: index, in: dataRows, withConfiguration: configuration)
137+
case let view as StatsTotalRow where index < dataRows.count:
138+
view.isHidden = false
139+
let dataRow = dataRows[index]
140+
view.configure(rowData: dataRow, delegate: configuration.rowDelegate, referrerDelegate: configuration.referrerDelegate)
141+
view.showSeparator = index != (numberOfRowsToAdd - 1)
142+
default:
143+
view.isHidden = true
144+
}
145+
}
146+
147+
private func configureViewMoreRow(_ viewMoreRow: ViewMoreRow, at index: Int, in dataRows: [StatsTotalRowData], withConfiguration configuration: StatsTotalRowConfiguration) {
148+
let shouldShowViewMore = configuration.limitRowsDisplayed && dataRows.count > StatsDataHelper.maxRowsToDisplay
149+
viewMoreRow.isHidden = !shouldShowViewMore
150+
if shouldShowViewMore {
151+
viewMoreRow.configure(statSection: dataRows.first?.statSection, delegate: configuration.viewMoreDelegate)
152+
}
153+
}
154+
}

WordPress/Classes/ViewRelated/Stats/Shared Views/TopTotalsCell.swift

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class TopTotalsCell: StatsBaseCell, NibLoadable {
4242
private weak var postStatsDelegate: PostStatsDelegate?
4343
private typealias Style = WPStyleGuide.Stats
4444

45+
override func awakeFromNib() {
46+
super.awakeFromNib()
47+
48+
addDefaultTotalRows(toStackView: rowsStackView)
49+
}
50+
4551
// MARK: - Configure
4652

4753
func configure(itemSubtitle: String? = nil,
@@ -71,41 +77,30 @@ class TopTotalsCell: StatsBaseCell, NibLoadable {
7177
self.forDetails = forDetails
7278

7379
if !forDetails {
74-
addRows(dataRows,
75-
toStackView: rowsStackView,
76-
forType: siteStatsPeriodDelegate != nil ? .period : .insights,
80+
if rowsStackView.arrangedSubviews.isEmpty {
81+
addDefaultTotalRows(toStackView: rowsStackView)
82+
}
83+
configureTotalRows(
84+
dataRows,
85+
inStackView: rowsStackView,
86+
forType: siteStatsPeriodDelegate != nil ? .period : .insights,
87+
configuration: .init(
7788
limitRowsDisplayed: limitRowsDisplayed,
7889
rowDelegate: self,
7990
referrerDelegate: self,
80-
viewMoreDelegate: self)
81-
91+
viewMoreDelegate: self
92+
)
93+
)
8294
initChildRows()
95+
} else {
96+
rowsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
8397
}
8498

8599
setSubtitleVisibility()
86100
applyStyles()
87101
prepareForVoiceOver()
88102
}
89103

90-
override func prepareForReuse() {
91-
super.prepareForReuse()
92-
93-
rowsStackView.arrangedSubviews.forEach { subview in
94-
95-
// Remove granchild rows
96-
if let row = subview as? StatsTotalRow {
97-
removeChildRowsForRow(row)
98-
}
99-
100-
// Remove child rows
101-
if let childView = subview as? StatsChildRowsView {
102-
removeRowsFromStackView(childView.rowsStackView)
103-
}
104-
}
105-
106-
removeRowsFromStackView(rowsStackView)
107-
}
108-
109104
private enum Metrics {
110105
static let topAccessoryViewSpacing: CGFloat = 32.0
111106
}

0 commit comments

Comments
 (0)