Hi,
Im trying to use ForEach without list to get rid of the navigation chevron , but the sipe to delete modifier stop working, is there a some solution ?
Kind Regards
Button(role: .destructive) {
deletePatient(patient: patient)
} label: {
VStack {
Label("Delete", systemImage: "trash")
Image(systemName: "Trash")
}
}
}
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I used standard font styles in an iOS app. For example .font(.headline). I hoped that developing this way would allow the adoption of the app to other platforms, relatively easy.
However, when trying to run for iPadOS, the text did not increase in size to occupy the more abundant space offered by larger screen, but it actually shrank. Overall, the app does not look great "automatically".
Why does it happen?
What is the best practice for cross platform development with SwiftUI (with regards to font sizes). I want to make as little as possible human interface design decisions on my own and just let SwiftUI take care of everything. (But I also want the results to look as Apple would consider great looking)
I am building an app where tasks can be shown on multiple selected days. The user will select a day and the available tasks should be shown. I am struggling to build a view hierarchy where the visible tasks will update when added to the currently shown day.
A simplified model looks like the below:
@Model final class Day
{
private(set) var dayID: UUID = UUID()
var show: [Item]?
}
@Model final class Item
{
private(set) var itemID: UUID = UUID()
@Relationship(inverse: \Day.show) var showDays: [Day]?
}
I have a view representing a day, and I would like it to display a list of associated tasks below.
The view doesn't update if I list a day's tasks directly, e.g. List(day.show) {}
I get a compile error if I build a sub view that queries Item using the day's show array:
let show = day.show ?? []
let predicate = #Predicate<Item> { item in
show.contains(where: { $0.itemID == item.itemID }) }
I get runtime error if I flip the predicate:
let dayID = day.dayID
let predicate: Predicate<Item> = #Predicate<Item> { item in
item.showDays.flatMap { $0.contains(where: { $0.dayID == dayID }) } ?? false }
I'm at a loss of how to approach this, other that just forcing the whole view hierarchy to update every time a make a change.
Is there a recommended approach to this situation please?
Does anyone have any idea why withAnimation is buggy when you apply a clip shape to an image? I've attached a screenshot of what happens below. Sometimes when hovering, it looks like the item gets drawn at the wrong location for a frame or two and then is placed back into position and the animation starts. It doesn't happen when the hover state ends, only the very initial hover event. This also doesn't happen without the .clipShape. I've also tried using .mask, but the same issue occurs. Has anyone ran into this?
When first opening my app, the first view navigated to loads and then a second later reloads. When navigating away and back to the view, it only loads once as designed.
Has anyone ever experienced this before and knows of any obvious reasons?
I can upload code snippets later, the views are wrapped in navigation links.
Thanks for any help
I'm wondering if there is a way to force a re-fetch of a @Query property inside of a SwiftUI view so I could offer a pull-to-refresh mechanism for users to force-refresh a view.
Why would I want this?
iOS 18.0 and 18.1 currently contain some regressions that prevent SwiftData from properly gathering model updates caused by ModelActor's running on background threads and the suggested workarounds (listening for .NSManagedObjectContextDidSave) don't work well in most scenarios and do not cause queries in the current view to be fully re-evaluated (see Importing Data into SwiftData in the Background Using ModelActor and @Query).
On visionOS, I have discovered that if dismissWindow is followed immediately by a call to openWindow, the new window does not open where the user is looking at. Instead, it appears at the same location as the dismissed window. However, if I open the new window after a small delay, or after UIScene's willDeactivateNotification, the new window correctly opens in front of the user. (I tested this within a opened immersive space.)
Does this imply that dismissWindow is actually asynchronous, in the sense that it requires extra time to reset certain internal states before the next openWindow can be called? What is the best practice to close a window, then open a new window in front of the user's current head position?
I’m trying to use TabView as a page view, but I’m having some trouble. When I select a tab, the content gets cut off. I tried setting scrollClipDisabled, but that didn’t help.
var body: some View {
TabView {
Button {
} label: {
AsyncImage(
url: URL(
string:
"https://plus.unsplash.com/premium_photo-1693227521269-d90b70e3ee06?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
)
) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
} placeholder: {
Color.red
}
}
.buttonStyle(.borderless)
}
.scrollClipDisabled()
.tabViewStyle(.page(indexDisplayMode: .always))
.indexViewStyle(.page(backgroundDisplayMode: .always))
Button("Button") {
}
}
If you switch between tab content and the button, you will notice that the bottom corner radius is clipped.
Does anyone have any idea how to avoid this action?
I have a working ValueTransformer that runs fine in simulator/device, but crashes in SwiftUI Preview. Even though they are the same code.
Here is my code
import Foundation
final class StringBoolDictTransformer: ValueTransformer {
override func transformedValue(_ value: Any?) -> Any? {
guard let stringBoolDict = value as? [String: Bool] else { return nil }
let nsDict = NSMutableDictionary()
for (key, bool) in stringBoolDict {
nsDict[key] = NSNumber(value: bool)
}
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: nsDict, requiringSecureCoding: true)
return data
} catch {
debugPrint("Unable to convert [Date: Bool] to a persistable form: \(error.localizedDescription)")
return nil
}
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else { return nil }
do {
guard let nsDict = try NSKeyedUnarchiver.unarchivedDictionary(ofKeyClass: NSString.self, objectClass: NSNumber.self, from: data) else {
return nil
}
var result = [String: Bool]()
for (key, value) in nsDict {
result[key as String] = value.boolValue
}
return result
} catch {
debugPrint("Unable to convert persisted Data to [Date: Bool]: \(error.localizedDescription)")
return nil
}
}
override class func allowsReverseTransformation() -> Bool {
true
}
override class func transformedValueClass() -> AnyClass {
NSDictionary.self
}
}
and here is the container
public struct SwiftDataManager {
public static let shared = SwiftDataManager()
public var sharedModelContainer: ModelContainer
init() {
ValueTransformer.setValueTransformer(
StringBoolDictTransformer(), forName: NSValueTransformerName("StringBoolDictTransformer")
)
let schema = Schema([,
Plan.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
sharedModelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}
}
and the model
@Model
final class Plan {
@Attribute(.transformable(by: StringBoolDictTransformer.self))
var dict: [String: Bool] = [:]
}
I would get that container and pass it in appdelegate and it works fine. I would get that container and pass it inside a #Preview and it would crash with the following:
Runtime: iOS 17.5 (21F79) - DeviceType: iPhone 15 Pro
CoreFoundation:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "dict"; desired type = NSDictionary; given type = _NSInlineData; value = {length = 2, bytes = 0x7b7d}.'
libsystem_c.dylib:
abort() called
Version 16.0 (16A242d)
Hey there,
Is there a way to launch another view by tapping on the preview of a context menu? Something like the behavior of the Photos app where tapping on the preview navigates to the details view.
Tap gesture handlers on the preview don't seem to get called, even as high priority gestures.
Thanks for the help!
Gab
I've got another issue with Gesture.updating(_:body:).. This looks a bit like this thread, but it's different. My problem occurs when creating a simultaneous gesture combining a RotateGesture with a MagnifyGesture.
struct ManipulationState: Equatable {
var magnification: CGFloat?
var rotation: Angle?
}
@GestureState var state: ManipulationState? = nil
var gesture: GestureStateGesture<SimultaneousGesture<RotateGesture, MagnifyGesture>, ManipulationState?> {
SimultaneousGesture(
RotateGesture(minimumAngleDelta: .degrees(5)),
MagnifyGesture(minimumScaleDelta: 0.1)
)
.updating($state) { value, state, transaction in
state = ManipulationState(
magnification: value.second?.magnification,
rotation: value.first?.rotation
)
}
}
When rotating and magnifying quite a bit, at some point, something happens, the gesture stops working altogether and the state never resets to the initial value any more.
When adding an onChange handler to some view in the body, you can watch state never gets nil again.
.onChange(of: state, { oldValue, newValue in
print("\(oldValue) \(newValue)")
})
I noticed the same happening when using ExclusiveGesture instead of SimultaneousGesture.
Full code example here: https://github.com/teameh/GestureIssueTester/blob/main/GestureTester/ContentView.swift
Video demonstrating issue here: https://github.com/teameh/GestureIssueTester/raw/refs/heads/main/screen-recording.mov
I've tried using Gesture.onChanged(_:) and Gesture.onEnded(_:)as well, butonEnded` is also not always called.
Is there anyone here who ran into the same problem or perhaps someone can share tips on a workaround or a fix?
Tested using Xcode 16.0 (16A242d)
In WWDC 2023 there was a good summary of how to handle the iOS 17 Observation capability.
But despite the clear graphics, it was still ambiguous (for me.)
I want to inject a class (view-model) so that it can be used in the complete view heirarchy, and used in bindings to allow bi-directional communication.
As far as I can tell there are 2 ways of declaring the VM (alternatives 1 and 2 in my code), and 2 ways of consuming the VM in a view (alternatives 3 and 4 in my code). Using the flow-diagram I can't determine which is best.
Here's the crux of my #Observable problem.
import SwiftUI
// MARK: - Model
struct MyMod {
var title = "Hello, World!"
}
// MARK: - MVV
@Observable
class MyMVV {
var model: MyMod
init() {
self.model = MyMod()
}
}
// MARK: - App
@main
struct MyApp: App {
@Bindable var myGlobalMVV = MyMVV() // Alternative 1
// @State var myGlobalMVV = MyMVV() // Alternative 2
var body: some Scene {
WindowGroup {
ContentView()
.environment(myGlobalMVV) // inject
}
}
}
struct ContentView: View {
var body: some View {
ContentDeepHierarchyView()
}
}
struct ContentDeepHierarchyView: View {
@Environment(MyMVV.self) var myGlobalMVV // digest
var body: some View {
@Bindable var myLocalMVV = myGlobalMVV // Alternative 3
TextField("The new title", text: $myLocalMVV.model.title) // Alternative 3
TextField("The new title", text: Bindable(myGlobalMVV).model.title) // Alternative 4
}
Opinions?
I am creating a LazyVGrid with 2 columns. I want it so that if there is only one item in a row, then it goes to the center of the row. I tried using an HStack with a Spacer, but it doesn't push it to the center. How do I do it?
ForEach(pets) { pet in
VStack {
Image(pet.species.rawValue)
.resizable()
.frame(width: 80, height: 80)
Text(pet.name)
.poppinsBold(size: 16)
}
}
HStack {
if pets.hasEvenNumber {
Spacer(minLength: 0)
}
Button {
addPetSheet = true
} label: {
VStack {
ZStack {
Circle()
.frame(width: 70, height: 70)
.foregroundStyle(.gray)
Image(systemName: "plus")
.foregroundStyle(.white)
.font(.title)
}
Text("Add")
.poppinsBold(size: 16)
}
}
}
}
We seen to have found an issue when using the pushWindow action on visionOS. The issue occurs if the app is backgrounded then reopened by selecting the apps icon on the home screen. Any window that is opened via the pushWindow action is then dismissed. We've been able to replicate the issue in a small sample project.
Replication steps
Open app
Open window via the push action
Press the digital crown
On the home screen select the apps icon again
The pushed window will now be dismissed.
There is a sample project linked here that shows off the issue, including a video of the bug in progress
I have a view containing either a TextField or a SecureField. I'm hoping I can use a single FocusState value that will apply to either the TextField or SecureField. (I'm using FocusState to ensure the cursor will be in the field when it initially loads)
I've verified this works in a sample project when the view is in a WindowGroup. But when I instead use a DocumentGroup ~50% of the time when the view loads/launches, it does not have focus.
Here is my ContentView:
struct ContentView: View {
let coinFlip: Bool = .random() // used to choose between the TextField and the SecureField
@State var fieldContent: String = "" // bound to the Field value
@FocusState var focus: Bool
var body: some View {
VStack {
Text("Coin Flip: \(coinFlip)")
actualField
.focused($focus, equals: true)
}
.onAppear() {
focus = true
}
}
@ViewBuilder var actualField: some View {
if coinFlip {
TextField("Enter text here", text: $fieldContent)
} else {
SecureField("Enter secure text here", text: $fieldContent)
}
}
}
and here is my App swift file
@main
struct ModernTurtleApp: App {
var body: some Scene {
// WindowGroup {
// ContentView()
// }
DocumentGroup(newDocument: ModernTurtleDocument()) { file in
ContentView()
}
}
}
When this code runs, the Field has focus about 50% of the time on initial launch. When I uncomment the WindowGroup and comment the DocumentGroup, the field always has focus on initial launch.
I realize I can work around this behaviour by using an optional enum for FocusState. I would be ok going this route, but I first want to try to understand the behaviour I'm seeing, and possibly keep my simpler FocusState implementation.
Thanks, in advance for any help.
I think I have the simplest possible Mac app trying to see if I can have VideoPlayer work in an Xcode Preview. It works in an iOS app project. In a Mac app project it builds and runs. But if I preview in Xcode it crashes.
The diagnostic says:
| [Remote] Unknown Error: The operation couldn’t be completed. XPC error received on message reply handler
|
| BSServiceConnectionErrorDomain (3):
| ==NSLocalizedFailureReason: XPC error received on message reply handler
| ==BSErrorCodeDescription: OperationFailed
The code I'm using is the exact code from the VideoPlayer documentation page. See this link.
Any ideas about this XPC error, and how to work around?
I'm using Xcode 16.0 on macOS 14.6.1
Hi, I have a project that uses SwiftUI, where we have a TabView, and in one of the tabs, I have a NavigationStack(path:). And created a logic to clear the NavigationStack path everytime you change to another Tab.
But found a bug, that if for some reason when doing a navigation in the NavigationStack, and rapidly tapping to another Tab, the NavigationStack doesn't gets clean up, or even if you have for some reason something allocated in the view you were navigation, doesn't get deinit if you have the logic for deinit a object when dismissing the view.
The environment I have is:
iPhone 12 Pro Max with iOS 17.6.1
This is the code that I have:
struct TabBarView: View {
@ObservedObject var tabBarVC = TabBarViewController()
var body: some View {
TabView(selection: $tabBarVC.selectedTab) {
Text("HomeView")
.tabItem {
Label("Home", systemImage: "house")
}
.tag(TabBarViewController.Tab.home)
SettingsView(settingsVC: tabBarVC.settingsVC)
.tabItem {
Label("Settings", systemImage: "gear")
}
.tag(TabBarViewController.Tab.settings)
}
.onChange(of: tabBarVC.selectedTab) { oldValue, newValue in
tabBarVC.settingsVC.clearNavigationPath()
}
}
}
class TabBarViewController: ObservableObject {
enum Tab {
case home
case settings
}
@Published var selectedTab: Tab = .home
@Published var settingsVC: SettingsViewController = .init()
}
class SettingsViewController: ObservableObject {
enum Destination {
case viewOne
case viewTwo
case viewThree
}
@Published var navigationPath: NavigationPath = .init()
func navigateTo(destination: Destination) {
self.navigationPath.append(destination)
}
func clearNavigationPath() {
self.navigationPath = .init()
}
}
The expected I am looking for is that everytime you change your tab, it cleans up the navigation stack, even if you change the tab when there is a navigation animation in process.
Does anyone know any workaround for this? FB15522331
Even on iOS 18 (16-17 also repo) we are seeing a crash on the FamilyActivityPicker when users tap on "Other" or just at random times. We see the follow debug message but no other way of identifying the issue in code.
[u 3C8AF272-DC4E-55C4-B8C6-34826D2BEB5B:m (null)] [com.apple.FamilyControls.ActivityPickerExtension(1150.1)] Connection to plugin invalidated while in use.
Even with the most basic implementation of FamilyActivityPicker (example below) we can repro this crash consistently.
Big applications (think Opal) see the same issue but it seems like they see it less, and are able to intercept the disconnect in order to show an error to the user. My two questions are
How can we intercept this crash/disconnect in order to alert our user and restart the experience?
Is this EVER gonna get fixed properly?
Usage Example:
var body: some View {
NavigationView {
ZStack {
familyPickerErrorView
.opacity(isHidden ? 0 : 1)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
isHidden = false
}
}
}
VStack {
Color.clear
.frame(height: 1)
.background(Color(UIColor.systemBackground))
FamilyActivityPicker(
headerText: "Select Apps To Be Blocked (Maximum of 50)",
footerText: "Want to block Safari? Check our FAQs",
selection: $familySelection)
.ignoresSafeArea(.all)
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
isPresented = false
}) {
Text("Cancel")
.foregroundColor(.black)
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
isPresented = false
}) {
Text("Done")
}
}
}
.navigationBarTitleDisplayMode(.inline)
.alert(isPresented: $showAlert) {
Alert(title: Text("Family Activity Picker Issue"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
}
.onAppear {
isPresented = true
}
}
Hello, my app uses vibrancy effects thanks to SwiftUI's materials and hierarchical shape style. While they work flawlessly on iOS and iPadOS, on Mac Catalyst they seem to be pretty broken.
I'm attaching some screenshots.
iPad
Mac
This is the same code, with the same background behind the material. The colors are already pretty different, but my concern is about the text, which clearly looks broken
Here a sample code:
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: 2) {
Text(event.label)
.font(.subheadline.weight(.semibold))
.foregroundStyle(.secondary)
Text(event.info(for: currentDestination))
.font(.system(.title2, design: .rounded, weight: .semibold))
.foregroundStyle(.primary)
}
Spacer(minLength: 0)
InfoIcon(isCustom: event.isCustomIcon, icon: event.icon, renderingMode: .palette, size: iconSize)
.font(.body.weight(.semibold))
}
.padding(.horizontal, 24)
.padding(.vertical, 12)
.background(.quaternary, in: .rect(cornerRadius: 16, style: .continuous))
.clipShape(.rect(cornerRadius: 16, style: .continuous))
.padding(.all, 16)
.background(.ultraThinMaterial, in: .rect)