Post

Replies

Boosts

Views

Activity

Reply to List-like Selection for custom containers
From the documentation for this modifier: Use an item-based context menu with a container that supports selection, such as a List or Table. I don't think it is possible as there is no current API for selection in custom views as this is what the context menu is looking for.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to Time Wheel Picker
I asked a similar question a while back and it doesn't look like anything has changed. You definitely can't do this in SwiftUI, only with UIKit. You will have to manually position the hour and min text labels and set the width of the picker so that the scrolling numbers line up properly.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to Canceling an Edit: When to alert?
I believe NSManagedObject has a hasChanges property so you can check that boolean value, however this requires you to update the object directly whenever the user changes something. The other option would be doing what @Claude31 suggested, or manually checking each property for a change between the current stored value and the one the user is modifying.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to Canceling an Edit: When to alert?
Here's my attempt at using the hasChanges property. It sort of combines the two approaches. See what you think – I'm not sure how well it works though. There is an entity called Item with three attributes: name: String, detail: String, amount: Int16 (for reproducibility). I used the template PersistenceController struct to inject the managedObjectContext into the views. struct ContentView: View {     @Environment(\.managedObjectContext) private var viewContext     @FetchRequest(sortDescriptors: []) private var items: FetchedResults<Item>     @State private var selectedItem: Item?     var body: some View {         NavigationStack {             List(items) { item in                 Button {                     selectedItem = item                 } label: {                     LabeledContent(item.title ?? "No name", value: item.amount, format: .number)                 }             }             .sheet(item: $selectedItem, content: EditView.init)             .toolbar {                 Button(action: addItem) {                     Label("Add Item", systemImage: "plus")                 }             }         }     }     private func addItem() {         withAnimation {             let newItem = Item(context: viewContext)             newItem.title = "New Item"             do {                 try viewContext.save()             } catch {                 fatalError("Failed to save: \(error.localizedDescription)")             }         }     } } struct EditView: View {     @Environment(\.dismiss) private var dismiss     @State private var showingCancelAlert = false     @State private var title: String     @State private var detail: String     @State private var amount: Int     let item: Item     init(item: Item) {         self.item = item         _title = State(wrappedValue: item.title ?? "")         _detail = State(wrappedValue: item.detail ?? "")         _amount = State(wrappedValue: Int(item.amount))     }     var body: some View {         NavigationStack {             Form {                 Section {                     TextField("Title", text: $title)                         .onSubmit {                             item.title = title                         }                     TextField("Description", text: $detail)                         .onSubmit {                             item.detail = detail                         }                 }                 Stepper("Amount: \(amount)", value: $amount) { _ in                     item.amount = Int16(amount)                 }             }             .navigationTitle("Edit Item")             .navigationBarTitleDisplayMode(.inline)             .toolbar {                 ToolbarItem(placement: .cancellationAction) {                     Button("Cancel", role: .cancel) {                         if item.hasChanges {                             showingCancelAlert = true                         } else {                             dismiss()                         }                     }                     .confirmationDialog("You have unsaved changes", isPresented: $showingCancelAlert) {                         Button("Discard Changes", role: .destructive, action: dismiss.callAsFunction)                     }                 }                 ToolbarItem(placement: .confirmationAction) {                     Button("Done", action: dismiss.callAsFunction)                         .disabled(!item.hasChanges)                 }             }         }         .interactiveDismissDisabled()     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to placeholderText Color
If you want the placeholderText property for SwiftUI's Color, you can access it like this: Color(uiColor: .placeholderText) You can also wrap this inside of an extension on Color for simpler code.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to SwiftUI & Layout API. Extra trailing closure passed in call
The method behind the trailing closure accepts a closure as a parameter that can only return a single view. func callAsFunction<V>(_ content: () -> V) -> some View where V : View Since its not marked with @ViewBuilder, like most of the other SwiftUI view closures, you can only return one view. So your view will have to be declared like this if you want multiple views: MyStairsStack() { Group { Text("Hello, World!") Text("Hello, World!") Text("Hello, World!") } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to EditView Reference is Broken
The problem is that you have attached the .sheet modifier to the view inside of the ForEach, which means that every view has that sheet that presents its own version of EditView. Also the .contextMenu modifier should be attached to each view in the ForEach so it has access to the object that has been selected. I have changed your code so that this should (theoretically) work. // When the button in the context menu is tapped, the index of the corresponding object is stored in the selectedObjectIndex variable. // This triggers the sheet to appear with an unwrapped selectedObjectIndex which is used to get the object that is passed to the EditView. struct ContentView: View { @State private var objectList = [Object(title: "First", string: "Editor"), Object(title: "Second", string: "Addition"), Object(title: "Third", string: "Twelve")]     @State private var selectedObjectIndex: Int?         var body: some View {         NavigationView{             List{                 Section("Objects"){                     ForEach(objectList) { object in                         NavigationLink(destination: ObjectView(obj: object)){                             Text(object.title)                         } .contextMenu{ // move inside ForEach                     Button(action: {                         self.selectedObjectIndex = objectList.firstIndex(of: object)                     }){                         Text("Edit Item")                     }                 }                     }                 } .sheet(item: $selectedObjectIndex) { index in // move outside ForEach and use item initialiser                 EditView(obj: objectList[index])                 }             }             .listStyle(InsetGroupedListStyle())             .cornerRadius(10)             .navigationBarTitle("My List")         }     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to SwiftUI Textfield Alert for macOS
macOS 13 Beta Release Notes SwiftUI New Features • You can now place a TextField in an Alert by using alert modifiers that accept a ViewBuilder . (64819930) I haven't tested it yet as I'm still using Monterey, but it should work according to the release notes. If you are looking for macOS 12 and earlier solutions, you can do something like this: Button("Tap Me") { let alert = NSAlert() alert.messageText = "Alert with text field"     alert.addButton(withTitle: "OK") // You can customise this text field, this is just an example.     alert.accessoryView = NSTextField(string: "Text")                  alert.runModal() }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to NavigationStack Being Automatically dismissed
One thing that may be causing this is that fact that the FruitDetailView contains a NavigationStack, when it's parent, ContentView, already wraps it in one. If removing the inner NavigationStack doesn't work, then maybe it's a bug. I'm not sure how related this is but from the release notes: A view-based NavigationLink in a List fails to update the visible selection of the list. (92193873)
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to MyEqualWidthHStack WWDC example not working for me
A lot of people have been experiencing different behaviours with the new Layout API and they each have different solutions. Resolved in iOS & iPadOS 16 beta 2, passing multiple children to a custom Layout now compiles. This means that a Group or another container is no longer required. The other issue arises from how the layout views are created under the hood. Two solutions for this are either wrapping the layout name in parentheses: (CustomLayout()) { Text("Hello, World") Text("Hello, World") } or creating an initialiser for the custom Layout that accepts no parameters: init() {} ... CustomLayout { Text("Hello, World") Text("Hello, World") }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22