Post

Replies

Boosts

Views

Created

TipKit popover inside ForEach Loop
I've encountered a problem when placing a tip on an element in a ForEach loop. As long as there is only one element in the list the tip will be shown. But if there are more than one element the tip does not appear on iOS and iPadOS. How do I get the tip to be displayed when several elements are displayed? Is it allowed to use the popoverTip() modifier in a ForEach loop or should it be avoided? Interestingly, it works if you run the attached sample code on macOS. Then the tip is displayed on the “Third” element. import SwiftUI import TipKit struct ContentView: View { private var elements: [String] = ["First", "Second", "Third"] let tip = DemoTip() var body: some View { NavigationStack { List { Section { ForEach(elements, id: \.self) { element in Text(element) .popoverTip(tip) } } } } } } struct DemoTip: Tip { var title: Text { Text("Demo Tip") } } @main struct TipKitTestApp: App { init() { #if DEBUG Tips.showAllTipsForTesting() #endif try? Tips.configure([.displayFrequency(.immediate)]) } var body: some Scene { WindowGroup { ContentView() } } }
3
0
221
Jun ’25
Reset NavigationStack when changing selection of NavigationSplitView
I'm trying to build an app that has a NavigationSplitView and a NavigationStack in the detail View. The normal flow works fine, but if I navigate to the second page on the detail view and then select another menu item (i.e. the second item), I'm still on the detail page of the first menu item. The underlying view of the second detail view changes. This can be observed by the change of the back button label. How do I ensure that my NavigationStack is also reset when I change the selection? import SwiftUI enum Option: String, Equatable, Identifiable {     case first     case second     var id: Option { self } } struct ContentView: View {     @State private var selection: Option?     var body: some View {         NavigationSplitView {             List(selection: $selection) {                 NavigationLink(value: Option.first) {                     Text("First")                 }                 NavigationLink(value: Option.second) {                     Text("Second")                 }             }         } detail: {             switch selection {             case .none:                 Text("Please select one option")             case .some(let wrapped):                 NavigationStack {                     DetailView(title: wrapped.rawValue)                 }             }         }         .navigationSplitViewStyle(.balanced)     } } struct DetailView: View {     private var title: String     init(title: String) {         self.title = title     }     var body: some View {         List {             NavigationLink {                 Text(title)             } label: {                 Text("Show \(title) detail")             }         }         .navigationTitle(title)     } }
2
1
3.4k
Jan ’23
LazyVGrid inside ScrollView not pinning section header
If I place a LazyVGrid inside a ScrollView with other views inside another ScrollView. The pinnedViews option of the LazyVGrid stops working. The section header scrolls out of the viewport like it's not pinned. The complete view should scroll horizontally without another horizontal scrolling on the grid. The grid itself is wider than than the device width so it should scroll horizontally. The problem is now that the pinnedViews option of the LazyVGrid is not working. If I remove the inner ScrollView and set the scroll mode of the outer to [.vertical, .horizontal] the pinned header works, except that now the view above and below the grid are also the same width of the LazyVGrid, which is not wat I want. Is it possible to pin the section header to the outer ScrollView and not to the direct parent ScrollView of the LazyVGrid? struct ContentView: View { var body: some View { ScrollView(.vertical) { Text("Other content") .frame(maxWidth: .infinity, minHeight: 100) .background(Color.yellow) ScrollView(.horizontal) { LazyVGrid( columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9), spacing: 16, pinnedViews: [.sectionHeaders] ) { Section(header: header) { ForEach(1..<500) { Text("Cell #\($0)") } } } } Text("Other content") .frame(maxWidth: .infinity, minHeight: 100) .background(Color.yellow) } } var header: some View { LazyVGrid( columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9), spacing: 16 ) { ForEach(1..<10) { Text("Header \($0)") } } .padding(.vertical) .background(Color.blue) .foregroundColor(.white) } } The example is complete so you can test it easily. It works as expected, except that the pinned section header is not working.
1
0
4.2k
Jul ’21
TipKit popover inside ForEach Loop
I've encountered a problem when placing a tip on an element in a ForEach loop. As long as there is only one element in the list the tip will be shown. But if there are more than one element the tip does not appear on iOS and iPadOS. How do I get the tip to be displayed when several elements are displayed? Is it allowed to use the popoverTip() modifier in a ForEach loop or should it be avoided? Interestingly, it works if you run the attached sample code on macOS. Then the tip is displayed on the “Third” element. import SwiftUI import TipKit struct ContentView: View { private var elements: [String] = ["First", "Second", "Third"] let tip = DemoTip() var body: some View { NavigationStack { List { Section { ForEach(elements, id: \.self) { element in Text(element) .popoverTip(tip) } } } } } } struct DemoTip: Tip { var title: Text { Text("Demo Tip") } } @main struct TipKitTestApp: App { init() { #if DEBUG Tips.showAllTipsForTesting() #endif try? Tips.configure([.displayFrequency(.immediate)]) } var body: some Scene { WindowGroup { ContentView() } } }
Replies
3
Boosts
0
Views
221
Activity
Jun ’25
Reset NavigationStack when changing selection of NavigationSplitView
I'm trying to build an app that has a NavigationSplitView and a NavigationStack in the detail View. The normal flow works fine, but if I navigate to the second page on the detail view and then select another menu item (i.e. the second item), I'm still on the detail page of the first menu item. The underlying view of the second detail view changes. This can be observed by the change of the back button label. How do I ensure that my NavigationStack is also reset when I change the selection? import SwiftUI enum Option: String, Equatable, Identifiable {     case first     case second     var id: Option { self } } struct ContentView: View {     @State private var selection: Option?     var body: some View {         NavigationSplitView {             List(selection: $selection) {                 NavigationLink(value: Option.first) {                     Text("First")                 }                 NavigationLink(value: Option.second) {                     Text("Second")                 }             }         } detail: {             switch selection {             case .none:                 Text("Please select one option")             case .some(let wrapped):                 NavigationStack {                     DetailView(title: wrapped.rawValue)                 }             }         }         .navigationSplitViewStyle(.balanced)     } } struct DetailView: View {     private var title: String     init(title: String) {         self.title = title     }     var body: some View {         List {             NavigationLink {                 Text(title)             } label: {                 Text("Show \(title) detail")             }         }         .navigationTitle(title)     } }
Replies
2
Boosts
1
Views
3.4k
Activity
Jan ’23
LazyVGrid inside ScrollView not pinning section header
If I place a LazyVGrid inside a ScrollView with other views inside another ScrollView. The pinnedViews option of the LazyVGrid stops working. The section header scrolls out of the viewport like it's not pinned. The complete view should scroll horizontally without another horizontal scrolling on the grid. The grid itself is wider than than the device width so it should scroll horizontally. The problem is now that the pinnedViews option of the LazyVGrid is not working. If I remove the inner ScrollView and set the scroll mode of the outer to [.vertical, .horizontal] the pinned header works, except that now the view above and below the grid are also the same width of the LazyVGrid, which is not wat I want. Is it possible to pin the section header to the outer ScrollView and not to the direct parent ScrollView of the LazyVGrid? struct ContentView: View { var body: some View { ScrollView(.vertical) { Text("Other content") .frame(maxWidth: .infinity, minHeight: 100) .background(Color.yellow) ScrollView(.horizontal) { LazyVGrid( columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9), spacing: 16, pinnedViews: [.sectionHeaders] ) { Section(header: header) { ForEach(1..<500) { Text("Cell #\($0)") } } } } Text("Other content") .frame(maxWidth: .infinity, minHeight: 100) .background(Color.yellow) } } var header: some View { LazyVGrid( columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9), spacing: 16 ) { ForEach(1..<10) { Text("Header \($0)") } } .padding(.vertical) .background(Color.blue) .foregroundColor(.white) } } The example is complete so you can test it easily. It works as expected, except that the pinned section header is not working.
Replies
1
Boosts
0
Views
4.2k
Activity
Jul ’21