I am new to the TCA world and I am trying to build a list that has a NavigationLink for opening a detail view. Now by default SwiftUI puts the detail disclosure item (chevron right icon) which can be removed using different techniques in vanilla SwiftUI, I used to tackle this issue by adding .opacity(0) to the NavigationList inside a ZStack, but I am unable to figure out how to remove it using NavigationLink inside a ForEachStore?
Hi @saifullahsajid, I believe that whatever tricks you use in vanilla SwiftUI to hide the chevron would equally apply to TCA. Can you share some code to show us what the vanilla SwiftUI code looks like and why it is not working in TCA?
Here is how I did it in vanilla SwiftUI. This is a pretty old snippet btw.
List {
ForEach(self.conversations, id: \.id) { conversation in
ZStack {
ChatsListView()
NavigationLink(destination: MessagesView() {
EmptyView()
}.opacity(0)
}
}
.listRowBackground(Colors.primary)
.listRowSeparator(.hidden)
}
.listStyle(.plain)
Hi @saifullahsajid, I would expect that technique to work just as well in TCA. What troubles did you have?
Alright so here goes my current implementation of the List:
List {
ForEachStore(
self.store.scope(
state: { $0.filteredItems },
action: HomeViewFeature.Action.itemDetail(id:action:)
)
) { itemsStore in
ItemRowView(store: itemsStore)
}
.listRowBackground(Colors.primary)
.listRowSeparator(.hidden)
}
.listStyle(.plain)
And here is my ItemRowView:
public var body: some View {
WithViewStore(self.store) { viewStore in
NavigationLink(
unwrap: Binding(get: { viewStore.route }, set: { _ in }),
case: /ItemRowFeature.State.Route.itemDetail,
onNavigate: { viewStore.send(.setEditNavigation(isActive: $0)) },
destination: { itemViewModel in
IfLetStore<ItemDetailFeature.State, ItemDetailFeature.Action, ItemDetailView?>(
self.store.scope(
state: { state in
guard case .itemDetail(let itemDetailState) = state.route else {
return nil
}
return itemDetailState
},
action: { .edit($0) }
),
then: { ItemDetailView(store: $0) }
)
}
) {
ZStack {
RoundedRectangle(cornerRadius: 15.0)
.fill(Color(UIColor.systemGray6))
HStack {
VStack(alignment: .leading, spacing: 9) {
Text(viewStore.item.name ?? "")
.font(.body)
}
}
}
.padding(.vertical, 9)
}
}
.opacity(0)
}
}
If I add the opacity here it uses the opacity for the whole view, which hides the whole row. I don't know which is the appropriate location for the opacity in this case.
In your first code snippet (in vanilla SwiftUI) you had structured the row like this:
That is, the ZStack
contained both the ChatsListView
and the NavigationLink
.
Whereas in the TCA code you just posted, the ZStack
is inside the NavigationLink
.
Is there any reason you can't restructure the view hierarchy to be more similar to what you did for vanilla SwiftUI?
You are right! it totally makes sense now. I just followed the same arrangement as I did in vanilla SwiftUI and it worked like a charm. Thank you so much @mbrandonw.