Post

Replies

Boosts

Views

Activity

Allow custom tap gesture in List but maintain default selection gesture
I'm trying to create a List that allows multiple selection. Each row can be edited but the issue is that since there's a tap gesture on the Text element, the list is unable to select the item. Here's some code: import SwiftUI struct Person: Identifiable { let id: UUID let name: String init(_ name: String) { self.id = UUID() self.name = name } } struct ContentView: View { @State private var persons = [Person("Peter"), Person("Jack"), Person("Sophia"), Person("Helen")] @State private var selectedPersons = Set<Person.ID>() var body: some View { VStack { List(selection: $selectedPersons) { ForEach(persons) { person in PersonView(person: person, selection: $selectedPersons) { newValue in // ... } } } } .padding() } } struct PersonView: View { var person: Person @Binding var selection: Set<Person.ID> var onCommit: (String) -> Void = { newValue in } @State private var isEditing = false @State private var newValue = "" @FocusState private var isInputActive: Bool var body: some View { if isEditing { TextField("", text: $newValue, onCommit: { onCommit(newValue) isEditing = false }) .focused($isInputActive) .labelsHidden() } else { Text(person.name) .onTapGesture { if selection.contains(person.id), selection.count == 1 { newValue = person.name isEditing = true isInputActive = true } } } } } Right now, you need to tap on the row anywhere but on the text to select it. Then, if you tap on the text it'll go in edit mode. Is there a way to let the list do its selection? I tried wrapping the tap gesture in simultaneousGesture but that didn't work. Thanks!
2
2
1.4k
Feb ’23
Can't set focus with tab key when text fields are in a form (iPadOS)
I don't know if this is a bug but when you put text fiels in a form, pressing the Tab key on a physical keyboard will just jump to the first field and stay there: import SwiftUI struct ContentView: View { enum FocusedField { case firstName, lastName } @State var name = "" @State var lastName = "" @FocusState private var focusedField: FocusedField? var body: some View { Form { TextField("Name", text: $name) .focused($focusedField, equals: .firstName) TextField("Last", text: $lastName) .focused($focusedField, equals: .lastName) } .padding() .onAppear { focusedField = .firstName } } } This is the result: Note that this works fine on macOS or when using the Tab key on the virtual keyboard. If you put the fields into a VStack instead, you'll be able to move through the fields via the Tab key.
2
1
1.5k
Feb ’23
Placeholders for text fields embedded in forms (macOS)
It seems like there's no way to set a placeholder in a text field when it is in a form on macOS. This is not an issue on iOS. import SwiftUI struct ContentView: View { @State private var textUp = "" @State private var textDown = "" var body: some View { VStack { Form { Text("In a form:") .fontWeight(.bold) TextField("placeholder", text: $textUp) } Text("Not in a form:") .fontWeight(.bold) TextField("placeholder", text: $textDown) } .padding() } } Am I missing something or is this just not supported?
1
0
933
Feb ’23
Buttons with label won't show in keyboard shortcuts list on iPad
Why won't a button using a Label show in the keyboard shortcuts list (holding ⌘ key)? struct ContentView: View { var body: some View { NavigationSplitView { SidebarView() } detail: { Text("Hello, world") } } } struct SidebarView: View { let items = [1, 2, 3, 4, 5, 6] var body: some View { List(items, id:\.self) { item in Text("\(item)") } .toolbar { Button { // Do something } label: { Label("New", systemImage: "plus") } .keyboardShortcut("n") // Will NOT show in shortcuts list Button("Play") { // Do something } .keyboardShortcut("p") // Will show in shortcuts list } } } Am I doing something wrong or is this just yet another SwiftUI shortcoming?
2
0
562
Dec ’22
macOS: Impossible to set focus on a textfield embedded in an alert
As of now, it seems impossible to set focus on a text field that is embedded in an alert on macOS. struct ContentView: View { @FocusState private var focusedField: FocusField? @State private var showingAlert = false @State private var name = "" enum FocusField { case folderName } var body: some View { VStack { Button { // focusedField = .folderName // Not working either showingAlert.toggle() } label: { Text("Show alert") } .alert("Alert", isPresented: $showingAlert, actions: { TextField("Name", text: $name) .font(.body) .autocorrectionDisabled() .focused($focusedField, equals: .folderName) Button("Cancel", role: .cancel, action: {}) }) #if os(macOS) .defaultFocus($focusedField, .folderName) #endif } .padding() } } When running this code on iOS, the text field does get focus automatically. Is it me that is doing something wrong or it's just a SwiftUI shortcoming on macOS?
1
0
579
Dec ’22
iOS: List selection is reset to nil when app is sent to background
For some reason, a List will reset its selection to nil when the app is in the background. Steps to reproduce the issue: Run attached sample project Once the app has launched, select a name in the sidebar Move the app to the background Wait a few seconds Bring back the app to the foreground Expected result: The list selection should still be valid Actual result: The list selection is set to nil Notes: I’m using a StateObject, which should be the way to ensure that data isn’t regenerated when views are rendered. Is this a bug or something else needs to be taken care of? class AppModel: ObservableObject {     @Published var selectedPerson: Person? } @main struct NilListSelectionApp: App {     @StateObject var appModel = AppModel()     var body: some Scene {         WindowGroup {             ContentView()                 .environmentObject(appModel)         }     } } struct Person: Identifiable, Hashable {     let id: UUID     let firstname: String     init(firstname: String) {         id = UUID()         self.firstname = firstname     } } struct ContentView: View {     @EnvironmentObject private var appModel: AppModel     var body: some View {         NavigationSplitView {             SidebarView()         } detail: {             PersonView(person: appModel.selectedPerson)         }     } } struct SidebarView: View {     @EnvironmentObject private var appModel: AppModel     private let persons = [Person(firstname: "Joe"), Person(firstname: "Jane")]     var body: some View {         List(persons, id:\.self, selection: $appModel.selectedPerson) { person in             Text(person.firstname).tag(person)         }         .listStyle(.sidebar)     } } struct PersonView: View {     let person: Person?     var body: some View {         if let person {             Text(person.firstname)         }         else {             Text("No Selection")         }     } }
10
2
2.4k
Dec ’22
SwiftUI window aspect ratio
Is there a way to force a window to resize according to an aspect ratio? This is possible in AppKit via the NSWindow.contentAspectRatio property but I cannot find something similar for SwiftUI. Basically, I want the window to maintain the aspect ratio of its contents.
4
2
2.1k
Dec ’22
Set filename to use for "Save to Files" with ShareLink?
Isn't there no way to set the default filename to use when we want to save a DataRepresentation to a file? If I export to JSON, the filename is "JSON.json" is used by iOS, even if I set the name to use in SharePreview. struct ContentView: View {     let car = Car(id: UUID(), name: "911", items:                     [Item(id: UUID(),date: .now, desc: "oil change"),                      Item(id: UUID(),date: .now, desc: "Battery")])     var body: some View {         VStack {             ShareLink(item: car, preview: SharePreview(car.name))         }         .padding()     } } extension UTType {     static var car: UTType = UTType(exportedAs: "com.acme.cararchive") } struct Car: Codable {     let id: UUID     let name: String     let items: [Item] } extension Car: Transferable {     static var transferRepresentation: some TransferRepresentation {         DataRepresentation(contentType: .json) { archive in             try JSONEncoder().encode(archive)         } importing: { data in             try JSONDecoder().decode(Car.self, from: data)         }     } } struct Item: Codable {     let id: UUID     let date: Date     let desc: String }
3
0
2.0k
Oct ’22
ShareLink and DataRepresentation
In my app, I'd like to be able to share a .csv file via ShareLink and Transferable. I watched the "Meet Transferable" WWDC22 video and it should be possible as the presenter demonstrated that use case. However, when I try this on my end, I am able to share the content but somehow it is treated by iOS as plaintext and when sharing by email or messages, it will just add the text content to the body. If I try to share via AirDrop, it creates a random filename with the .txt extension even though I specify .commaSeparatedText. The only way this somewhat works is when saving to files. It will save as a .csv file but the filename is set to "comma-separated values". Here's some code: struct MyArchive {     enum ValidationError: Error {         case invalid     }     var filename: String { return "myarchive.csv"     }          init(csvData: Data) throws {         //...     }     func convertToCSV() throws -> Data {         let test = "Name,Email\nPete,pete@example.com"         if let data = test.data(using: .utf8) {             return data         }         else {             throw ValidationError.invalid         }     }  } extension MyArchive: Transferable {     static var transferRepresentation: some TransferRepresentation {         DataRepresentation(contentType: .commaSeparatedText) { archive in             try archive.convertToCSV()         } importing: { data in             try MyArchive(csvData: data)         }     } } And in my View: struct View: View { var body: some View { //... let csv = MyArchive() ShareLink( item: csv, preview: SharePreview(                         csv.filename,                         image: Image(systemName: "doc.plaintext")                     ) ) } } I'm at the point that I wonder if I'm doing something wrong or this just doesn't work in iOS 16 beta 1. Any hints? Thanks!
5
0
3.6k
Jun ’22
TestFlight for Mac: review required every single time a new build is pushed?
So I've started using TestFlight for Mac but unlike its iOS counterpart, it seems like every single build uploaded and pushed to testers has to be reviewed by Apple. This is not how that works on the iOS side. Ex: MyApp 4.1 build 1 -> Review required for both iOS and Mac MyApp 4.1 build 2 -> Review required for Mac, not iOS Is this a bug or by design? If so, this is crazy!
0
0
612
Nov ’21
Drag via pasteboard changed on Monterey?
This code works fine on macOS 11: var body: some View {         VStack {             ActionControl()                 .padding()                 .onDrag { () -> NSItemProvider in                     let value = Action(string: "hello, world").string                     let p = ActionProfile(value: value)                     return NSItemProvider(item: p, typeIdentifier: ActionProfile.pasteboardType)                 }                          MyTextView()                 .padding()         }     } class ActionProfile: NSObject, NSCoding, NSSecureCoding { static var supportsSecureCoding: Bool = true static var pasteboardType = "com.my.app.action.profile" @objc var rawValue: String func encode(with aCoder: NSCoder) { aCoder.encode(rawValue, forKey: "value") } required init(value: String) { self.rawValue = value } required init?(coder aDecoder: NSCoder) { self.rawValue = aDecoder.decodeObject(of: NSString.self, forKey: "value")! as String } required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) { return nil } } extension ActionProfile: NSPasteboardWriting, NSPasteboardReading { static var nsPasteboardType: NSPasteboard.PasteboardType = .init(pasteboardType) static func readingOptions(forType type: NSPasteboard.PasteboardType, pasteboard: NSPasteboard) -> NSPasteboard.ReadingOptions { return .asKeyedArchive } func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] { return [ActionProfile.nsPasteboardType] } func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? { if type == ActionProfile.nsPasteboardType { return try! NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false) } return nil } static func readableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] { return [ActionProfile.nsPasteboardType] } } extension MyTextViewControl { override internal var writablePasteboardTypes: [NSPasteboard.PasteboardType] { return [ActionProfile.nsPasteboardType] + super.writablePasteboardTypes } override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool { return true } override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation { let location = self.characterIndexForInsertion(at: self.convert(sender.draggingLocation, from: nil)) self.setSelectedRange(NSRange(location: location, length: 0)) return sender.draggingSource is MyTextViewControl ? .move : .copy } override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { let pboard = sender.draggingPasteboard if pboard.availableType(from: [ActionProfile.nsPasteboardType]) == ActionProfile.nsPasteboardType { if let profiles = pboard.readObjects(forClasses: [ActionProfile.self], options: nil) as? [ActionProfile], !profiles.isEmpty { let alert = NSAlert() alert.messageText = "WORKS" alert.runModal() return true } else { let alert = NSAlert() alert.messageText = "FAILED" alert.runModal() return super.performDragOperation(sender) } } return super.performDragOperation(sender) } } On macOS 12 beta, when calling pboard.readObjects(...) I get this error when trying to drag the item into a NSTextView: Failed to initialize keyed unarchiver for pasteboard data: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is empty; did you forget to send -finishEncoding to the NSKeyedArchiver?" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is empty; did you forget to send -finishEncoding to the NSKeyedArchiver?} I've noticed that encode(with aCoder: NSCoder) isn't called at all on macOS 12 but is on macOS 11. Are there any changes in macOS 12 regarding NSCoding or NSSecureCoding or is this just a bug?
2
0
993
Jul ’21
onDrag conflicts with clicks on macOS
I have a list of navigation links that I want to be draggable. However, it seems like onDrag conflicts with mouse clicks on macOS (iOS is fine). Here's some sample code: swift import SwiftUI struct ContentView: View { var items = ["Peter", "Mark", "Joe", "Frank", "Tim"] @State var selected: String? var body: some View { NavigationView { List { ForEach(items, id: \.self) { item in NavigationLink(destination: Text(item), tag: item, selection: $selected, label: { Text(item) .onDrag { () - NSItemProvider in return NSItemProvider(object: String(item) as NSString) } }) } } Text("") } } } Here's the weird part: if you click on the text, the item doesn't get selected and the link seems disabled. However, if you click on a section of the item that is empty, then it works! Again, this works just fine on iOS. Is this a SwiftUI bug/limitation or am I doing it wrong? Thanks!
1
2
1.3k
May ’21