Skip to content

Commit 2a176e0

Browse files
authored
Merge pull request #4952 from woocommerce/issue/4780-lazy-navigation-link
2 parents 7305fa4 + 6a1fd90 commit 2a176e0

File tree

4 files changed

+72
-2
lines changed

4 files changed

+72
-2
lines changed

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/EditAddressForm.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ struct EditAddressForm: View {
136136
.disabled(!viewModel.isDoneButtonEnabled))
137137

138138
// Go to edit country
139-
NavigationLink(destination: FilterListSelector(viewModel: viewModel.createCountryViewModel()), isActive: $showCountrySelector) {
139+
LazyNavigationLink(destination: FilterListSelector(viewModel: viewModel.createCountryViewModel()), isActive: $showCountrySelector) {
140140
EmptyView()
141141
}
142142

143143
// Go to edit state
144144
// TODO: Move `StateSelectorViewModel` creation to the VM when it exists.
145-
NavigationLink(destination: FilterListSelector(viewModel: StateSelectorViewModel()), isActive: $showStateSelector) {
145+
LazyNavigationLink(destination: FilterListSelector(viewModel: StateSelectorViewModel()), isActive: $showStateSelector) {
146146
EmptyView()
147147
}
148148
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import SwiftUI
2+
3+
/// `NavigationLink` wrapper that instantiates the `DestinationView` when the navigation occurs.
4+
///
5+
struct LazyNavigationLink<Destination: View, Label: View>: View {
6+
7+
/// Destination view builder
8+
///
9+
private let destination: () -> Destination
10+
11+
/// Set it to `true` to proceed with the desired navigation. Set it to `false` to remove the view from the navigation context.
12+
///
13+
@Binding var isActive: Bool
14+
15+
/// `NavigationLink` label
16+
///
17+
private let label: () -> Label
18+
19+
/// Creates a navigation link that creates and presents the destination view when active.
20+
/// - Parameters:
21+
/// - destination: A view for the navigation link to present.
22+
/// - isActive: A binding to a Boolean value that indicates whether `destination` is currently presented.
23+
/// - label: A view builder to produce a label describing the `destination` to present.
24+
init(destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>, label: @escaping () -> Label) {
25+
self.destination = destination
26+
self._isActive = isActive
27+
self.label = label
28+
}
29+
30+
var body: some View {
31+
NavigationLink(destination: LazyView(destination), isActive: $isActive, label: label)
32+
}
33+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import SwiftUI
2+
3+
/// Lazily loads a `View` using a closure as a builder function.
4+
/// Useful for cases when it's not desired to load the `View` at the view definition time. EG: `NavigationLink`
5+
///
6+
struct LazyView<Wrapped: View>: View {
7+
8+
/// Builder closure
9+
///
10+
private let wrapped: () -> Wrapped
11+
12+
/// Creates a wrapper for a view to be instantiated lazily.
13+
/// - Parameters:
14+
/// - wrapped: View builder function.
15+
init(_ wrapped: @autoclosure @escaping () -> Wrapped) {
16+
self.wrapped = wrapped
17+
}
18+
19+
/// Creates a wrapper for a view to be instantiated lazily.
20+
/// - Parameters:
21+
/// - wrapped: View builder closure.
22+
init(_ wrapped: @escaping () -> Wrapped) {
23+
self.wrapped = wrapped
24+
}
25+
26+
var body: Wrapped {
27+
wrapped()
28+
}
29+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@
446446
26C6E8E426E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E326E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift */; };
447447
26C6E8E626E6B5F500C7BB0F /* StateSelectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E526E6B5F500C7BB0F /* StateSelectorViewModel.swift */; };
448448
26C6E8E826E6B6AC00C7BB0F /* StateSelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E726E6B6AC00C7BB0F /* StateSelectorCommand.swift */; };
449+
26C6E8EA26E8FD3900C7BB0F /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E926E8FD3900C7BB0F /* LazyView.swift */; };
450+
26C6E8EC26E8FF4800C7BB0F /* LazyNavigationLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */; };
449451
26CCBE0B2523B3650073F94D /* RefundProductsTotalTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CCBE0A2523B3650073F94D /* RefundProductsTotalTableViewCell.swift */; };
450452
26CCBE0D2523C2560073F94D /* RefundProductsTotalTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 26CCBE0C2523C2560073F94D /* RefundProductsTotalTableViewCell.xib */; };
451453
26E0ADF12631D94D00A5EB3B /* TopBannerWrapperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E0ADF02631D94D00A5EB3B /* TopBannerWrapperView.swift */; };
@@ -1850,6 +1852,8 @@
18501852
26C6E8E326E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountrySelectorViewModelTests.swift; sourceTree = "<group>"; };
18511853
26C6E8E526E6B5F500C7BB0F /* StateSelectorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateSelectorViewModel.swift; sourceTree = "<group>"; };
18521854
26C6E8E726E6B6AC00C7BB0F /* StateSelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateSelectorCommand.swift; sourceTree = "<group>"; };
1855+
26C6E8E926E8FD3900C7BB0F /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = "<group>"; };
1856+
26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyNavigationLink.swift; sourceTree = "<group>"; };
18531857
26CCBE0A2523B3650073F94D /* RefundProductsTotalTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundProductsTotalTableViewCell.swift; sourceTree = "<group>"; };
18541858
26CCBE0C2523C2560073F94D /* RefundProductsTotalTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefundProductsTotalTableViewCell.xib; sourceTree = "<group>"; };
18551859
26E0ADF02631D94D00A5EB3B /* TopBannerWrapperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBannerWrapperView.swift; sourceTree = "<group>"; };
@@ -4367,6 +4371,8 @@
43674371
E10BC15D26CC06970064F5E2 /* ScrollableVStack.swift */,
43684372
DE126D0A26CA2331007F901D /* ValidationErrorRow.swift */,
43694373
DEE6437726D8DAD900888A75 /* InProgressView.swift */,
4374+
26C6E8E926E8FD3900C7BB0F /* LazyView.swift */,
4375+
26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */,
43704376
);
43714377
path = "SwiftUI Components";
43724378
sourceTree = "<group>";
@@ -7193,6 +7199,7 @@
71937199
024DF30B23742297006658FE /* AztecFormatBarCommand.swift in Sources */,
71947200
CC254F3426C4113B005F3C82 /* ShippingLabelPackageSelection.swift in Sources */,
71957201
AECD57D226DFDF7500A3B580 /* EditAddressForm.swift in Sources */,
7202+
26C6E8EC26E8FF4800C7BB0F /* LazyNavigationLink.swift in Sources */,
71967203
45E9A6E724DAE23300A600E8 /* ProductReviewsViewModel.swift in Sources */,
71977204
028BAC4222F30B05008BB4AF /* StoreStatsV4PeriodViewController.swift in Sources */,
71987205
740987B321B87760000E4C80 /* FancyAnimatedButton+Woo.swift in Sources */,
@@ -7413,6 +7420,7 @@
74137420
4506BD712461965300FE6377 /* ProductVisibilityViewController.swift in Sources */,
74147421
CE1F512B206985DF00C6C810 /* PaddedLabel.swift in Sources */,
74157422
26E0ADF12631D94D00A5EB3B /* TopBannerWrapperView.swift in Sources */,
7423+
26C6E8EA26E8FD3900C7BB0F /* LazyView.swift in Sources */,
74167424
7421344A210A323C00C13890 /* WooAnalyticsStat.swift in Sources */,
74177425
02A275BA23FE50AA005C560F /* ProductUIImageLoader.swift in Sources */,
74187426
02305353237454C700487A64 /* AztecInsertMoreFormatBarCommand.swift in Sources */,

0 commit comments

Comments
 (0)