Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from dkk/feature/performance-optimization
- Loading branch information
Showing
9 changed files
with
192 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import SwiftUI | ||
|
||
/// This class manages content and the calculation of their widths (reusing it). | ||
/// It should be reused whenever possible. | ||
class ContentManager { | ||
enum ViewType { | ||
case any(AnyView) | ||
case newLine | ||
|
||
init<V: View>(rawView: V) { | ||
switch rawView { | ||
case is NewLine: self = .newLine | ||
default: self = .any(AnyView(rawView)) | ||
} | ||
} | ||
} | ||
|
||
let items: [ViewType] | ||
lazy var widths: [Double] = { | ||
items.map { | ||
if case let .any(anyView) = $0 { | ||
return Self.getWidth(of: anyView) | ||
} else { | ||
return 0 | ||
} | ||
} | ||
}() | ||
|
||
init(items: [ViewType]) { | ||
self.items = items | ||
} | ||
|
||
@inline(__always) private static func getWidth(of anyView: AnyView) -> Double { | ||
#if os(iOS) | ||
let hostingController = UIHostingController(rootView: HStack { anyView }) | ||
#else | ||
let hostingController = NSHostingController(rootView: HStack { anyView }) | ||
#endif | ||
return hostingController.sizeThatFits(in: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width | ||
} | ||
|
||
func isVisible(viewIndex: Int) -> Bool { | ||
widths[viewIndex] > 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import Foundation | ||
|
||
/// This class is in charge of calculating which items fit on which lines. | ||
/// It should be reused whenever possible. | ||
class LineManager { | ||
private var contentManager: ContentManager! | ||
private var spacing: WrappingHStack.Spacing! | ||
private var width: CGFloat! | ||
|
||
lazy var firstItemOfEachLine: [Int] = { | ||
var firstOfEach = [Int]() | ||
var currentWidth: CGFloat = width | ||
for (index, element) in contentManager.items.enumerated() { | ||
switch element { | ||
case .newLine: | ||
firstOfEach += [index] | ||
currentWidth = width | ||
case .any where contentManager.isVisible(viewIndex: index): | ||
let itemWidth = contentManager.widths[index] | ||
if currentWidth + itemWidth + spacing.minSpacing > width { | ||
currentWidth = itemWidth | ||
firstOfEach.append(index) | ||
} else { | ||
currentWidth += itemWidth + spacing.minSpacing | ||
} | ||
default: | ||
break | ||
} | ||
} | ||
|
||
return firstOfEach | ||
}() | ||
|
||
var isSetUp: Bool { | ||
width != nil | ||
} | ||
|
||
func setup(contentManager: ContentManager, width: CGFloat, spacing: WrappingHStack.Spacing) { | ||
self.contentManager = contentManager | ||
self.width = width | ||
self.spacing = spacing | ||
} | ||
|
||
var totalLines: Int { | ||
firstItemOfEachLine.count | ||
} | ||
|
||
func startOf(line i: Int) -> Int { | ||
firstItemOfEachLine[i] | ||
} | ||
|
||
func endOf(line i: Int) -> Int { | ||
i == totalLines - 1 ? contentManager.items.count - 1 : firstItemOfEachLine[i + 1] - 1 | ||
} | ||
|
||
func hasExactlyOneElement(line i: Int) -> Bool { | ||
startOf(line: i) == endOf(line: i) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.