Last active
May 15, 2024 07:09
-
-
Save audrl1010/dd41f7d5910f3e4ead747ea73c5f6a6e to your computer and use it in GitHub Desktop.
Revisions
-
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 11 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,23 +1,23 @@ # LazyDisplayStackScrollView ## What? - ScrollView에 StackView를 감싸서, 많은 양의 subviews들을 처음에 추가할 때 rendering 과부하가 걸리게 됩니다. scrolling시 화면에 보이는 영역의 subviews만 render할 수 있다면 굉장히 퍼포먼스가 좋을 것입니다. SwiftUI에서는 이러한 문제점을 인식했는 지 LazyStack이라는 것을 제공합니다. 하지만 UIKit에서는 그러한 것을 제공하지 않습니다. 이 라이브러리는 해당 이슈를 해결하기 위해 만들어졌습니다. ## Description - on-demand subviews render를 지원합니다. - Note) subview(LazyDisplayView)를 추가할 때 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. ## Implement ```swift class LazyDisplayStackScrollView: UIView { // 위 아래, 허용 var distance: CGFloat = 100 private(set) var lazyDisplayViews: [LazyDisplayView] = [] private lazy var scrollView = UIScrollView() @@ -68,21 +68,21 @@ class LPLazyDisplayStackScrollView: UIView { } } func addArrangedSubview(_ view: LazyDisplayView) { self.lazyDisplayViews.append(view) self.contentStack.addArrangedSubview(view) self.contentStack.setNeedsLayout() self.contentStack.layoutIfNeeded() } func insertArrangedSubview(_ view: LazyDisplayView, at index: Int) { self.lazyDisplayViews.insert(view, at: index) self.contentStack.insertArrangedSubview(view, at: index) self.scrollView.setNeedsLayout() self.scrollView.layoutIfNeeded() } func removeArrangedSubview(_ view: LazyDisplayView) { let index = self.lazyDisplayViews.firstIndex { $0 === view } if let index = index { self.lazyDisplayViews.remove(at: index) @@ -125,7 +125,7 @@ class LPLazyDisplayStackScrollView: UIView { } } class LazyDisplayView: UIView { fileprivate(set) var isPending: Bool = true @@ -165,7 +165,7 @@ class LPLazyDisplayView: UIView { ```swift class ViewController: UIViewController { private let contentView = LazyDisplayStackScrollView() override func viewDidLoad() { super.viewDidLoad() @@ -219,7 +219,7 @@ import UIKit import SnapKit import Then class ItemView: LazyDisplayView { let label = UILabel() -
audrl1010 revised this gist
Oct 15, 2022 . No changes.There are no files selected for viewing
-
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -7,6 +7,7 @@ - Note) subview(LPLazyDisplayView)를 추가할 때 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. ## Implement ```swift -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ # LPLazyDisplayStackScrollView ## What? - ScrollView에 StackView를 감싸서, 많은 양의 subviews들을 처음에 추가할 때 rendering 과부하가 걸리게 됩니다. scrolling시 화면에 보이는 영역의 subviews만 render할 수 있다면 굉장히 퍼포먼스가 좋을 것입니다. SwiftUI에서는 이러한 문제점을 인식했는 지 LazyStack이라는 것을 제공합니다. 하지만 UIKit에서는 그러한 것을 제공하지 않습니다. 이 라이브러리는 해당 이슈를 해결하기 위해 만들어졌습니다. ## Description - on-demand subviews render를 지원합니다. -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ ## What? - ScrollView에 StackView를 감싸서 사용할 때, 많은 양의 subviews들을 처음에 추가할 때 rendering 과부하가 걸리게 됩니다. scrolling시 화면에 보이는 영역의 subviews만 render할 수 있다면 굉장히 퍼포먼스가 좋을 것입니다. SwiftUI에서는 이러한 문제점을 인식했는 지 LazyStack이라는 것을 제공합니다. 하지만 UIKit에서는 그러한 것을 제공하지 않습니다. 이 라이브러리는 해당 이슈를 해결하기 위해 만들어졌습니다. ## Description - on-demand subviews render를 지원합니다. - Note) subview(LPLazyDisplayView)를 추가할 때 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -160,9 +160,8 @@ class LPLazyDisplayView: UIView { } ``` ## Example ```swift class ViewController: UIViewController { private let contentView = LPLazyDisplayStackScrollView() -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ # LPLazyDisplayStackScrollView ## What? - ScrollView에 StackView를 감싸서 사용할 때, 많은 양의 subviews들을 처음에 추가할 때 rendering 과부하가 걸리게 됩니다. scrolling시 화면에 보이는 영역의 subviews만 render할 수 있다면 굉장히 퍼포먼스가 좋을 것입니다. SwiftUI에서는 이러한 문제점을 인식했는 지 LazyStack이라는 것을 제공합니다. 하지만 UIKit에서는 그러한 것을 제공하지 않습니다. 이 라이브러리는 해당 이슈를 해결하기 위해 만들어졌습니다. ## Define - on-demand subviews render를 지원합니다. -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,9 @@ # LPLazyDisplayStackScrollView ## What? - ScrollView에 StackView를 감싸서 사용할 때, 많은 양의 subviews들을 처음에 추가할 때 rendering 과부하가 걸리게 됩니다. scrolling시 화면에 보이는 영역의 subviews만 render할 수 있다면 굉장히 퍼포먼스가 좋을 것입니다. 이 라이브러리는 해당 이슈를 해결하기 위해 만들어졌습니다. ## Define - on-demand subviews render를 지원합니다. - Note) subview(LPLazyDisplayView)를 추가할 때 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 120 additions and 120 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,126 +1,8 @@ ## Define - LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. - Note) subview(LPLazyDisplayView)를 추가할 때 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. ## Implement ```swift @@ -273,3 +155,121 @@ class LPLazyDisplayView: UIView { } } ``` ```swift // Example) class ViewController: UIViewController { private let contentView = LPLazyDisplayStackScrollView() override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = .white self.view.addSubview(self.contentView) self.contentView.snp.makeConstraints { $0.top.equalTo(self.view.safeAreaLayoutGuide) $0.left.right.bottom.equalToSuperview() } let item0 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "0" $0.tag = 0 } let item1 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "1" $0.tag = 1 } let item2 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "2" $0.tag = 3 } let item5 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "3" $0.tag = 5 } self.contentView.addArrangedSubview(item0) self.contentView.addArrangedSubview(item1) self.contentView.addArrangedSubview(item2) self.contentView.addArrangedSubview(item5) DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [unowned self] in self.contentView.insertArrangedSubview(ItemView().then { $0.backgroundColor = .gray $0.label.text = "11" $0.tag = 11 }, at: 1) } } } import UIKit import SnapKit import Then class ItemView: LPLazyDisplayView { let label = UILabel() let stack = UIStackView().then { $0.axis = .vertical $0.alignment = .fill $0.distribution = .fill } let button = UIButton().then { $0.setTitle("Toggle", for: .normal) } override init(frame: CGRect) { super.init(frame: frame) self.setup() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setup() { self.setEstimatedHeight(500) } override func display() { super.display() self.layer.borderColor = UIColor.red.cgColor self.layer.borderWidth = 1.0 print("display ", self.tag) self.button.setTitle("\(self.tag)", for: .normal) self.addSubview(self.button) self.button.addTarget(self, action: #selector(didTap), for: .touchUpInside) self.button.snp.makeConstraints { $0.height.equalTo(500) $0.edges.equalToSuperview() } } var isToggle: Bool = false @objc func didTap() { let generator = UIImpactFeedbackGenerator(style: .light) generator.impactOccurred() self.isToggle = !self.isToggle self.button.snp.updateConstraints { $0.height.equalTo(self.isToggle ? 1000 : 250) } } } ``` -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 62 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -57,6 +57,68 @@ class ViewController: UIViewController { } } import UIKit import SnapKit import Then class ItemView: LPLazyDisplayView { let label = UILabel() let stack = UIStackView().then { $0.axis = .vertical $0.alignment = .fill $0.distribution = .fill } let button = UIButton().then { $0.setTitle("Toggle", for: .normal) } override init(frame: CGRect) { super.init(frame: frame) self.setup() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setup() { self.setEstimatedHeight(500) } override func display() { super.display() self.layer.borderColor = UIColor.red.cgColor self.layer.borderWidth = 1.0 print("display ", self.tag) self.button.setTitle("\(self.tag)", for: .normal) self.addSubview(self.button) self.button.addTarget(self, action: #selector(didTap), for: .touchUpInside) self.button.snp.makeConstraints { $0.height.equalTo(500) $0.edges.equalToSuperview() } } var isToggle: Bool = false @objc func didTap() { let generator = UIImpactFeedbackGenerator(style: .light) generator.impactOccurred() self.isToggle = !self.isToggle self.button.snp.updateConstraints { $0.height.equalTo(self.isToggle ? 1000 : 250) } } } ``` ## Implement -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -59,6 +59,8 @@ class ViewController: UIViewController { } ``` ## Implement ```swift class LPLazyDisplayStackScrollView: UIView { -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 5 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,8 @@ ## Define LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. Note) addArrangedSubview 하려는 LPLazyDisplayView의 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. ```swift // Example) @@ -55,9 +60,6 @@ class ViewController: UIViewController { ``` ```swift class LPLazyDisplayStackScrollView: UIView { -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 57 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,59 @@ ```swift // Example) class ViewController: UIViewController { private let contentView = LPLazyDisplayStackScrollView() override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = .white self.view.addSubview(self.contentView) self.contentView.snp.makeConstraints { $0.top.equalTo(self.view.safeAreaLayoutGuide) $0.left.right.bottom.equalToSuperview() } let item0 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "0" $0.tag = 0 } let item1 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "1" $0.tag = 1 } let item2 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "2" $0.tag = 3 } let item5 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "3" $0.tag = 5 } self.contentView.addArrangedSubview(item0) self.contentView.addArrangedSubview(item1) self.contentView.addArrangedSubview(item2) self.contentView.addArrangedSubview(item5) DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [unowned self] in self.contentView.insertArrangedSubview(ItemView().then { $0.backgroundColor = .gray $0.label.text = "11" $0.tag = 11 }, at: 1) } } } ``` ```swift // LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. // Note) addArrangedSubview 하려는 LPLazyDisplayView의 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, @@ -115,9 +171,7 @@ class LPLazyDisplayStackScrollView: UIView { } } } class LPLazyDisplayView: UIView { fileprivate(set) var isPending: Bool = true @@ -152,58 +206,4 @@ class LPLazyDisplayView: UIView { } } } ``` -
audrl1010 revised this gist
Oct 15, 2022 . No changes.There are no files selected for viewing
-
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -5,7 +5,7 @@ class LPLazyDisplayStackScrollView: UIView { // 위 아래, 허용 var distance: CGFloat = 100 private(set) var lazyDisplayViews: [LPLazyDisplayView] = [] -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -5,6 +5,7 @@ class LPLazyDisplayStackScrollView: UIView { // 허용 거리 var distance: CGFloat = 100 private(set) var lazyDisplayViews: [LPLazyDisplayView] = [] -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,8 @@ ```swift // LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. // Note) addArrangedSubview 하려는 LPLazyDisplayView의 estimatedHeight(추측 높이)값을 대략적으로 정확히 설정해주지 않으면, // LPLazyDisplayStackScrollView가 좋은 성능을 내기 힘듭니다. class LPLazyDisplayStackScrollView: UIView { var distance: CGFloat = 100 -
audrl1010 renamed this gist
Oct 15, 2022 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
audrl1010 renamed this gist
Oct 15, 2022 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
audrl1010 revised this gist
Oct 15, 2022 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,4 @@ ```swift // LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. // Note) addArrangedSubview 하려는 LPLazyDisplayView의 Height 값을 설정 해주지 않으면, LPLazyDisplayStackScrollView가 잘 작동 되지 않습니다. class LPLazyDisplayStackScrollView: UIView { @@ -111,7 +112,9 @@ class LPLazyDisplayStackScrollView: UIView { } } } ``` ```swift class LPLazyDisplayView: UIView { fileprivate(set) var isPending: Bool = true @@ -199,4 +202,5 @@ class ViewController: UIViewController { } } } ``` -
audrl1010 created this gist
Oct 15, 2022 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,202 @@ // LPLazyDisplayStackScrollView는 on-demand subviews render를 지원합니다. // Note) addArrangedSubview 하려는 LPLazyDisplayView의 Height 값을 설정 해주지 않으면, LPLazyDisplayStackScrollView가 잘 작동 되지 않습니다. class LPLazyDisplayStackScrollView: UIView { var distance: CGFloat = 100 private(set) var lazyDisplayViews: [LPLazyDisplayView] = [] private lazy var scrollView = UIScrollView() private let contentStack = UIStackView().then { $0.axis = .vertical $0.distribution = .fill $0.alignment = .fill } private var scrollViewBoundsToken: NSKeyValueObservation? private var scrollViewContentSizeToken: NSKeyValueObservation? deinit { self.scrollViewBoundsToken?.invalidate() self.scrollViewContentSizeToken?.invalidate() } override init(frame: CGRect) { super.init(frame: frame) self.setup() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setup() { self.scrollViewBoundsToken = self.scrollView.observe(\UIScrollView.bounds, options: [.new]) { [weak self] scrollView, change in guard let self = self else { return } self.displayPendingViewsIfNeeded() } self.scrollViewContentSizeToken = self.scrollView.observe(\UIScrollView.contentSize, options: [.new]) { [weak self] scrollView, change in guard let self = self else { return } self.displayPendingViewsIfNeeded() } self.addSubview(self.scrollView) self.scrollView.snp.makeConstraints { $0.edges.equalToSuperview() } self.scrollView.addSubview(self.contentStack) self.contentStack.snp.makeConstraints { $0.edges.equalToSuperview() $0.width.equalToSuperview() } } func addArrangedSubview(_ view: LPLazyDisplayView) { self.lazyDisplayViews.append(view) self.contentStack.addArrangedSubview(view) self.contentStack.setNeedsLayout() self.contentStack.layoutIfNeeded() } func insertArrangedSubview(_ view: LPLazyDisplayView, at index: Int) { self.lazyDisplayViews.insert(view, at: index) self.contentStack.insertArrangedSubview(view, at: index) self.scrollView.setNeedsLayout() self.scrollView.layoutIfNeeded() } func removeArrangedSubview(_ view: LPLazyDisplayView) { let index = self.lazyDisplayViews.firstIndex { $0 === view } if let index = index { self.lazyDisplayViews.remove(at: index) self.contentStack.removeArrangedSubview(view) view.removeFromSuperview() self.contentStack.setNeedsLayout() self.contentStack.layoutIfNeeded() } } func removeAllArrangedSubviews() { self.lazyDisplayViews.removeAll() for subview in self.contentStack.arrangedSubviews { self.contentStack.removeArrangedSubview(subview) subview.removeFromSuperview() } self.contentStack.setNeedsLayout() self.contentStack.layoutIfNeeded() } private func displayPendingViewsIfNeeded() { let topPendingRect = CGRect( origin: .init(x: self.scrollView.contentOffset.x, y: self.scrollView.contentOffset.y - self.distance), size: self.scrollView.frame.size ) let bottomPendingRect = CGRect( origin: .init(x: self.scrollView.contentOffset.x, y: self.scrollView.contentOffset.y + self.distance), size: self.scrollView.frame.size ) for lazyDisplayView in self.lazyDisplayViews { if lazyDisplayView.isPending { if topPendingRect.intersects(lazyDisplayView.frame) || bottomPendingRect.intersects(lazyDisplayView.frame) { lazyDisplayView.isPending = false lazyDisplayView.display() } } } } } class LPLazyDisplayView: UIView { fileprivate(set) var isPending: Bool = true private(set) var estimatedHeight: CGFloat = 50 override init(frame: CGRect) { super.init(frame: frame) self.setup() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setup() { self.snp.makeConstraints { $0.height.equalTo(self.estimatedHeight) } } // Override 해서 사용하세요. func display() { // 기본 estimated height 설정 삭제 self.snp.remakeConstraints { _ in } } func setEstimatedHeight(_ height: CGFloat) { self.estimatedHeight = height self.snp.updateConstraints { $0.height.equalTo(height) } } } // Example) class ViewController: UIViewController { private let contentView = LPLazyDisplayStackScrollView() override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = .white self.view.addSubview(self.contentView) self.contentView.snp.makeConstraints { $0.top.equalTo(self.view.safeAreaLayoutGuide) $0.left.right.bottom.equalToSuperview() } let item0 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "0" $0.tag = 0 } let item1 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "1" $0.tag = 1 } let item2 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "2" $0.tag = 3 } let item5 = ItemView().then { $0.backgroundColor = .gray $0.label.text = "3" $0.tag = 5 } self.contentView.addArrangedSubview(item0) self.contentView.addArrangedSubview(item1) self.contentView.addArrangedSubview(item2) self.contentView.addArrangedSubview(item5) DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [unowned self] in self.contentView.insertArrangedSubview(ItemView().then { $0.backgroundColor = .gray $0.label.text = "11" $0.tag = 11 }, at: 1) } } }