I’m creating an app in Swift for MacOS and I’m adding a settings view.
Here where is defined:
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
Settings {
SettingsView()
}
}
}
Here is the SettingsView:
struct SettingsView: View {
var body: some View {
TabView {
GeneralSettingsView()
.tabItem {
Label("General", systemImage: "gear")
}
}
.scenePadding()
.frame(maxWidth: 350, minHeight: 100)
}
}
GeneralSettingsView:
struct GeneralSettingsView: View {
enum FolderSelection: Hashable {
case predefined(URL)
case other
var url: URL? {
switch self {
case .predefined(let url):
return url
case .other:
return nil
}
}
}
@AppStorage("destinationFolder") private var destinationFolder: URL = {
if let downloadsDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first {
return downloadsDirectory
}
return URL(fileURLWithPath: "")
}()
@State private var destinationFolders: [(name: String, url: URL)] = [
("Downloads", FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!)
]
@State private var selectedFolder: FolderSelection = .predefined(FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!)
var body: some View {
VStack {
HStack {
Picker("Destination folder:", selection: $selectedFolder) {
ForEach(destinationFolders, id: .url) { folder in
Text(folder.name).tag(FolderSelection.predefined(folder.url))
}
Text("Other...").tag(FolderSelection.other)
}
.onChange(of: selectedFolder) { newSelection in
handleFolderSelection(newSelection)
}
}
}
.padding()
}
private func handleFolderSelection(_ newSelection: FolderSelection) {
switch newSelection {
case .predefined(let url):
destinationFolder = url
case .other:
selectFolder()
}
}
private func selectFolder() {
let panel = NSOpenPanel()
panel.canChooseFiles = false
panel.canChooseDirectories = true
panel.allowsMultipleSelection = false
panel.prompt = "Select folder"
if panel.runModal() == .OK, let selectedURL = panel.url {
let newFolderSelection = FolderSelection.predefined(selectedURL)
if !destinationFolders.contains(where: { $0.url == selectedURL }) {
destinationFolders.append((selectedURL.lastPathComponent, selectedURL))
}
selectedFolder = newFolderSelection
destinationFolder = selectedURL
} else {
selectedFolder = .predefined(destinationFolder)
}
}
}
The problem happens when, once the new folder is chosen, the settings view disappears, instead of remaining (like when you choose the Downloads folder in the Safari settings).
What is the problem?
2