Post

Replies

Boosts

Views

Activity

ContentsOfDirectory for FileProvider URLs
I'm developing an iOS app. Through a .fileImporter I get access to a directory URL which might be provided by an external service like Dropbox (using a FileProvider). As the user picked the URL I have full access to it. I want to get the contents of the directory: FileManager.default.contentsOfDirectory( at: url, includingPropertiesForKeys: keys, options: [.skipsHiddenFiles] ) Unfortunately I only get whatever files the system is currently aware of, which in case of external providers is often not much. If the user opens the Apple Files app and navigates to the folder then the system gets the content from the external provider and back in my app contentsOfDirectory would show everything. What can I do to get a list of the URLs? Can I somehow trigger the system to update from the external provider? Or is there another way of handling this situation?
2
0
361
Jul ’24
NavigationStack inside NavigationSplitView on Mac
I've seen several posts regarding NavigationStack in a NavigationSplitView. All had specific issues and some were marked as resolved. I couldn't get any of the suggested solutions working on macOS so I'll present some stripped down examples, all part of FB11842563: 1. Sidebar Selection struct SidebarSelection: View {     @State var selection: Int?     @State var path: [Int] = []     var body: some View {         NavigationSplitView {             List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 VStack {                     Image(systemName: "x.squareroot")                         .imageScale(.large)                         .foregroundColor(.accentColor)                     Text("This is the NavigationStack root")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     Text("You chose \(number)")                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } If we run this and click: „I like 5“ „I like 6“ „I like 7“ We would expect the detail view to show: „You chose 5“ „You chose 6“ „You chose 7“ And the console to show: You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [5, 6] You clicked Optional(7) Path changed to [5, 6, 7] What we actually see in the detail view is: „You chose 5“ „This is the NavigationStack root“ „You chose 7“ And the console shows: Update NavigationRequestObserver tried to update multiple times per frame. You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [] You clicked Optional(7) Path changed to [7] 2. Sidebar and Stack Selection Now we copy the list to the navigationDestination: struct SidebarAndStackSelection: View {     @State var selection: Int?     @State var path: [Int] = []     var body: some View {         NavigationSplitView {             List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 VStack {                     Image(systemName: "x.squareroot")                         .imageScale(.large)                         .foregroundColor(.accentColor)                     Text("This is the NavigationStack root")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     VStack {                         Text("You chose \(number)")                         List(1...20, id: \.self, selection: $selection) { number in                             Text("I like \(number)")                         }                     }                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } We repeat our test from above, clicking either on the sidebar or in the detail view and we expect the same outcome. This time the detail view shows the expected screen and the path is not completely wiped out but it is also not appended: Update NavigationRequestObserver tried to update multiple times per frame. You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [6] You clicked Optional(7) Path changed to [7] 3. Sidebar and Stack Selection, initialized Same as before, but now we initialize the view with a non-empty path: SidebarAndStackSelection(path: [1]) The app freezes on launch, CPU is at 100 percent and the console shows only: Update NavigationRequestObserver tried to update multiple times per frame. Update NavigationRequestObserver tried to update multiple times per frame. The SwiftUI instruments seem to show heavy activity of the Stack and the SplitView: 4. Selection only in Stack Once we remove the selection from the sidebar everything works as expected (adding the NavigationStack to the root view to be able to click on a number): struct SidebarWithoutSelectionButStack: View {          @State var selection: Int?     @State var path: [Int] = []          var body: some View {         NavigationSplitView {             List(1...20, id: \.self) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     VStack {                         Text("You chose \(number)")                         List(1...20, id: \.self, selection: $selection) { number in                             Text("I like \(number)")                         }                     }                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } Problem of course is, that now the sidebar is useless.
6
2
1.6k
Dec ’22