Provide 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

Changing background colour of Button changes the container background
To change the background of a TextField, I simply apply: TextField("0.0", value: $p, format: .number) .textFieldStyle(PlainTextFieldStyle()) .background(.red) That does only work with plain style, but it works. Trying something similar on a button changes the container view background. The only solution I've found is to overlap with a Rectangle. How is it ? A SwiftUI bug ? A current limit of Swift ? A rationale for it ? There a better solution I've not found ?
3
0
192
Oct ’24
How to Play Timeline Animations via code
Hi everyone, I need to synchronize the playback of RealityKit Timelines via SharePlay. To do this I am trying to get the references of the timelines using "AnimationPlaybackController" and "AnimationResource". In my realitykit scene I have configured both an animation (with blender), and a timeline, the animation starts correctly when the realitykit scene starts, the timeline not. Below the code: struct ContentView: View { @State private var subscriptions = [EventSubscription]() @Environment(AppModel.self) private var appModel let rootEntity = Entity() @State var testEntity: Entity? @State var testAnimation: AnimationResource? @State var testController: AnimationPlaybackController? init() { CubeComponent.registerComponent() } var body: some View { RealityView { content in content.add(rootEntity) if let scene = try? await Entity(named: "Room", in: realityKitContentBundle) { rootEntity.addChild(scene) playAnimations(from: content) } } .gesture(SpatialTapGesture().targetedToAnyEntity() .onEnded({ value in _ = value.entity.applyTapForBehaviors() if let testEntity, let testAnimation { testController = testEntity.playAnimation(testAnimation.repeat()) } }) ) } func playAnimations(from content: RealityViewContent) { subscriptions.append(content.subscribe(to: ComponentEvents.DidAdd.self, componentType: AnimationLibraryComponent.self, { event in let entity = event.entity entity.components[AnimationLibraryComponent.self]?.animations.forEach({ (key, value) in if value.definition is AnimationGroup { if key == "/Room/TestTimeline" { let controller = entity.playAnimation(value.repeat()) testEntity = entity testAnimation = value appModel.syncronizedAnimations[key] = .init(name: key, animationController: controller, entityName: entity.name) } } else { if entity.name == "SphereInteractable" { let controller = entity.playAnimation(value.repeat()) appModel.syncronizedAnimations[key] = .init(name: key, animationController: controller, entityName: entity.name) } } }) })) } } the variables testEntity, testAnimation and testController are for testing purposes only. If I try to start the animations in the playAnimations function, only the animation created via blender starts (the one related to the object "SphereInteractable"), the Timeline starts only if I save a reference and I play it with a tap gesture or with a delay of ! seconds with DispatchQueue.asyncAfter called in the onAppear. is there a better way to handle this? The goal is to have a reference of the AnimationPlaybackController of the timeline, in order to sync the animation via shareplay. Thanks
3
0
249
3w
[Automaker App] Not able to display a keyboard
Hello community, I'm an iOS developer from VW group, I was doing some proof of concepts around an automaker app, and I've found a big blocker. When I was trying to summon a keyboard, it wasn't displayed. So is it even possible? Do I have to do some workaround with Carplay templates in order to be able to have the native keyboard from Carplay, or is there a special component that I need to introduce in my code to summon the keyboard? Thank you very much. David Cosialls.
1
0
136
3w
Is there a way to update Observable on the main thread but not to read from it?
I've been obsessed with this topic for the past couple of weeks and unfortunately there just isn't a good answer out there even from the community. Therefore I am hoping that I can summon Quinn to get an official Apple position (on what's seemingly a fairly fundamental part of using SwiftUI). Consider this simple example: import Foundation @MainActor @Observable class UserViewModel { var name: String = "John Doe" var age: Int = 30 // other properties and logic } // NetworkManager does not need to update the UI but needs to read/write from UserViewModel. class NetworkManager { func updateUserInfo(viewModel: UserViewModel) { Task { // Read values from UserViewModel prior to making a network call let userName: String let userAge: Int // Even for a simple read, we have to jump onto the main thread await MainActor.run { userName = viewModel.name userAge = viewModel.age } // Now perform network call with the retrieved values print("Making network call with userName: \(userName) and userAge: \(userAge)") // Simulate network delay try await Task.sleep(nanoseconds: 1_000_000_000) // After the network call, we update the values, again on the main thread await MainActor.run { viewModel.name = "Jane Doe" viewModel.age = 31 } } } } // Example usage let viewModel = UserViewModel() let networkManager = NetworkManager() // Calling from some background thread or task Task { await networkManager.updateUserInfo(viewModel: viewModel) } In this example, we can see a few things The ViewModel is a class that manages states centrally It needs to be marked as MainActor to ensure that updating of the states is done on the main thread (this is similar to updating @Published in the old days). I know this isn't officially documented in Apple's documentation. But I've seen this mentioned many times to be recommended approach including www.youtub_.com/watch?v=4dQOnNYjO58 and here also I have observed crashes myself when I don't follow this practise Now so far so good, IF we assume that ViewModel are only in service to Views. The problem comes when the states need to be accessed outside of Views. in this example, NetworkManager is some random background code that also needs to read/write centralized states. In this case it becomes extremely cumbersome. You'd have to jump to mainthread for each write (which ok - maybe that's not often) but you'd also have to do that for every read. Now. it gets even more cumbersome if the VM holds a state that is a model object, mentioned in this thread.. Consider this example (which I think is what @Stokestack is referring to) import Foundation // UserModel represents the user information @MainActor // Ensuring the model's properties are accessed from the main thread class UserModel { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } @MainActor @Observable class UserViewModel { var userModel: UserModel init(userModel: UserModel) { self.userModel = userModel } } // NetworkManager does not need to update the UI but needs to read/write UserModel inside UserViewModel. class NetworkManager { func updateUserInfo(viewModel: UserViewModel) { Task { // Read values from UserModel before making a network call let userName: String let userAge: Int // Jumping to the main thread to safely read UserModel properties await MainActor.run { userName = viewModel.userModel.name userAge = viewModel.userModel.age } // Simulate a network call print("Making network call with userName: \(userName) and userAge: \(userAge)") try await Task.sleep(nanoseconds: 1_000_000_000) // After the network call, updating UserModel (again, on the main thread) await MainActor.run { viewModel.userModel.name = "Jane Doe" viewModel.userModel.age = 31 } } } } // Example usage let userModel = UserModel(name: "John Doe", age: 30) let viewModel = UserViewModel(userModel: userModel) let networkManager = NetworkManager() // Calling from a background thread Task { await networkManager.updateUserInfo(viewModel: viewModel) } Now I'm not sure the problem he is referring still exists (because I've tried and indeed you can make codeable/decodables marked as @Mainactor) but it's really messy. Also, I use SwiftData and I have to imagine that @Model basically marks the class as @MainActor for these reasons. And finally, what is the official Apple's recommended approach? Clearly Apple created @Observable to hold states of some kind that drives UI. But how do you work with this state in the background?
6
0
272
Oct ’24
SwipeAction in For Each
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") } } }
3
0
150
Oct ’24
Text with standard font style appears smaller on iPadOS than on iOS
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)
0
0
162
Oct ’24
What Is The Recommended View Hierarchy for SwiftData Many-Many Relationships?
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?
1
0
156
Oct ’24
SwiftUI withAnimation flickering with clipShape
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?
0
0
162
Oct ’24
Any way to force-refresh @Query properties in SwiftUI?
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).
0
0
233
Oct ’24
Is dismissWindow actually asynchronous?
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?
0
0
192
Oct ’24
TabView doesn't support scrollClipDisabled
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?
0
0
132
Oct ’24
ValueTransformer currently crashes XCode SwiftUI preview
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)
2
0
276
Oct ’24
SimultaneousGesture.updating(_:body:) does not always reset
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)
3
0
231
Oct ’24
@Observation: Best way of handling binding after injecting a View-Model
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?
0
0
278
Oct ’24
Center alignment in row of LazyVGrid
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) } } } }
0
0
234
Oct ’24
visionOS pushWindow being dismissed on app foreground
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
0
1
160
Oct ’24
SwiftUI FocusState seems to 'misbehave' when Scene contains a DocumentGroup...
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.
0
0
156
Oct ’24
VideoPlayer crashes in Xcode Preview for macOS app
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
2
0
300
Oct ’24