Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

Posts under SwiftUI tag

200 Posts

Post

Replies

Boosts

Views

Activity

Toolbar symbol rendering does not behave as expected
Hello everyone, I've been having a bit of trouble with the .symbolRenderingMode(_:) modifier. When trying to apply it to a single button in a toolbar, it does not work at all. The symbol is always rendered as monochrome. However, I've realised that with this little hack I can achieve the expected results, but this is not ideal. .toolbar { HStack { Button("", action: {}) // The hack Button("Button", systemImage: "line.3.horizontal.decrease.circle.fill", action: {}) .symbolRenderingMode(.hierarchical) .foregroundStyle(.blue) } } I've submitted a bug report (FB16129223) but in the meantime, is this my only solution ? Side note: the foregroundStyle(_:) modifier is ignored as well.
1
0
401
Dec ’24
Using if statement in .overlay causes app to freeze when using withAnimation
I have an issue where a very specific configuration of .overlay, withAnimation, and a bindable state can freeze the app when the state changes. I've isolated the problematic source code into a sample project can be found here that demonstrates the issue: https://github.com/katagaki/IcyOverlay Steps to Reproduce To reproduce the issue, tap the 'Simulate Content Load' button. Once the progress bar has completed, a switch is toggled to hide the progress view, which causes the overlay to disappear, and the app to freeze. Any help and/or advice will be appreciated! Development Environment Xcode Version 16.2 (16C5032a), macOS 15.2(24C101) iOS SDK: 18.2 (22C146), Simulator: 18.2 (22C150)
1
0
422
Dec ’24
How to animate substring in a Text?
Currently, I am using multiple Texts in a horizontal stackview, to achieve animation of substring. As you can see in the above animation, the text - conversation - meeting - lecture are animated. However, there shortcoming of such an approach. Text size is not consistent among different Text block. The following Text block are having different text size. - Transform - conversation/ meeting/ lecture - to Quick Note Any idea how we can achieve, so that all text blocks have same text size so that they appear like 1 sentence? Or, how we can make the text blocks having constant text size, but able to perform line wrapping to next line, so that they appear like 1 sentence? Currently, this is the code snippet I am using. import SwiftUI struct ContentView: View { var array = ["lecture", "conversation", "meeting"] @State var currentIndex : Int = 0 @State var firstString : String = "" var body: some View { VStack { HStack { Text("Transform") .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) Text(firstString) .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0))) .background(.yellow) Text("to Quick Note") .lineLimit(1) .minimumScaleFactor(0.5) .font(.title) }.padding() } .animation(.default) .onAppear { firstString = array[0] let timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in if currentIndex == array.count - 1 { self.firstString = array[0] currentIndex = 0 } else { self.firstString = array[currentIndex+1] currentIndex += 1 } } } } } #Preview { ContentView() }
2
0
353
Dec ’24
Separate RealityView inside a RealityView attachment
Hi, I am having some troubles creating a "nested" RealityView content using MapKit attachment. I am building a visionOS app that has horizontal MapKit map as an attachment to RealityView. I want to display 3D pins on that map, therefore I am using native map annotation and inside of these annotations, I create a new RealityView just for the 3D pin. This worked completely fine, unitil I wanted to have those RealityViews interact with each other. By interaction of those RealityViews I mean that I wanted to group entities from the first "main" RealityViews content with the 3D pins using ModelSortGroupComponent. Why I want this? I want to make the map circular, that is not a problem. Problem is that when I move the map with 3D pins, these pins have their own RealityView space and are only bounded by volumetric window dimensions. What happes is that these pins float next to the map (shown on attached image). So I came up with this solution: create a custom "toroid" like 3D entity model that occludes the pins that go outside the map region. In order to occlude only the pins, I need to use ModelSortGroupComponent to group the "toroid" entity with 3D pins entities (as described in another forum thread). To summarize: need the content of the superior RealityView to interact with map attachment annotations RealityView content in order to group them. There might be of course another, better way to achieve my whole goal, so I would naturally appreciate any help or guidance. Image below showing 3D pins on circular map. Since pins RealityView does no know anything about other RealityViews, it just overlows and hangs in space until is cropped by volumetric window boundary. Simplified code: var body: some View { let modelSortGroup = ModelSortGroup(depthPass: .prePass) RealityView { content, attachments in var mainEntity = Entity() // My other entities here... if let mapAttachment = attachments.entity(for: "mapAttachment") { // Edit map properties, position, horizontal layout etc. mainEntity.addChild(mapAttachment) } // Create and add to content mask "toroid" entity mapMaskEntity. Use OcclusionMaterial() material. mapMaskEntity.components.set(ModelSortGroupComponent(group: modelSortGroup, order: 0)) // For all pins, somehow also set the group // 3DPinEntity.components.set(ModelSortGroupComponent(group: modelSortGroup, order: 1)) content.add(mainEntity) } attachments: { Attachment(id: "mapAttachment") { Map { ForEach(mapViewModel.clusters, id: \.id) { cluster in Annotation("", coordinate: cluster.coordinate) { MapPin3DView(cluster: cluster) } } } .clipShape(Circle()) } } } // MapPin3DView is an map annotation view that includes a model of 3D pin and some details like image etc., uses RealityView. struct MapPin3DView: View { var body: some View { RealityView { content in // 3D pin entities... } } }
1
0
484
Dec ’24
Error when clicking on TextField : CLIENT ERROR: TUINSRemoteViewController does not override -viewServiceDidTerminateWithError: and thus cannot react to catastrophic errors beyond logging them
Hello, I face an error everytime I want to interact with a TextField. The XCode debug area is showing : CLIENT ERROR: TUINSRemoteViewController does not override -viewServiceDidTerminateWithError: and thus cannot react to catastrophic errors beyond logging them There is no crash, and the text field is working fine. I am developing for MacOS using a macbook pro Intel from 2019 with Sonoma 14.5 and Xcode 15.4 and I think that I noticed since the release of Sonoma. I was not particularly concerned by it but I noticed that interacting with the textField was leading to severe hang in my app, and micro-hang in the test app and I am wondering is these two issues could be related. The message is easy to reproduce. Just create a new Project/Application/App using SwiftUI and add a TextField to the ContentView. When you start app, click or double click on the text field, enter a message and press enter. import SwiftUI struct ContentView: View { @State var value: String = "" var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") TextField(text: $value, label: { Text("Test") } ) } .padding() } } Did you notice the same thing ? How I could solve it ? Note : I already posted the problem on Swift forums but it was close because related to SwiftUI https://forums.swift.org/t/error-when-clicking-on-textfield-client-error-tuinsremoteviewcontroller-does-not-override-viewservicedidterminatewitherror-and-thus-cannot-react-to-catastrophic-errors-beyond-logging-them/72134/1 Thank you
24
11
7k
Dec ’24
GeometryReader problem
I'm adding Admob ads to my app, and Admob needs to know the width of the view, so I'm using GeometryReader for that. To prevent GeometryReader from grabbing screen space, I've wrapped the main view in GeometryReader { }. I then use geometry.size.width in my call to the adView. This all works fine. I have two main screens where I show ads, and they both work, until I rotate the device. Then the app crashes! If I comment out the GeometryReader code and pass a fixed value to the ad view, I can rotate the device with no fear of a crash. My question is: Do I have to accept that GeometryReader will crash the app when it's rotated, or is there another, stable way to get view dimensions?
3
0
495
Dec ’24
Textfield producing : Can't find or decode reasons, Failed to get or decode unavailable reasons
How to reproduce: create blank Xcode project run on physical iPhone(mine 14 pro) not simulator, updated iOS18.1.1 most up to date, on Xcode 16.1 make a text field enter any value in it in console: Can't find or decode reasons Failed to get or decode unavailable reasons This is happening in my other projects as well and I don't know a fix for it is this just an Xcode bug random log noise? It makes clicking the text field lag sometimes on initial tap.
13
18
3.1k
Dec ’24
Programmatically set EditMode in SwiftUI not working
Hello! I want to programmatically set the editMode in SwiftUI for a view as soon as it appears. However, I have read a lot now but it only works via the EditButton - but not programmatically. I'm using the simulator for this example and Xcode Version 15.4. struct EditTodos: View { @State private var editMode = EditMode.inactive @State var content = ["apple", "banana", "peanut"] var body: some View { NavigationStack { List { ForEach(content, id: \.self) { item in Text(item) } .onDelete { _ in } .onMove { _, _ in } } .onAppear { editMode = .active // note: not working, why?? } .navigationBarItems( trailing: HStack(spacing: 20) { EditButton() } ) } } } #Preview { EditTodos() }
1
0
447
Dec ’24
Initialize view struct with @StateObject parameter
May I inquire about the differences between the two ways of view under the hood in SwiftUI? class MyViewModel: ObservableObject { @Published var state: Any init(state: Any) { self.state = state } } struct MyView: View { @StateObject var viewModel: MyViewModel var body: some View { // ... } } struct CustomView: View { let navigationPath: NavigationPath @StateObject var viewModel: MyViewModel var body: some View { Button("Go to My View") { navigationPath.append(makeMyView()) } } } // Option 1: A viewModel is initialized outside view's initialization func makeMyView(state: Any) -> some View { let viewModel = MyViewModel(state: state) MyView(viewModel: viewModel) } // Option 2: A viewModel is initialized inside view's initialization func makeMyView(state: Any) -> some View { MyView(viewModel: MyViewModel(state: state)) } For option 1, the view model will be initialized whenever custom view is re-rendered by changes whereas the view model is only initialized once when the view is re-rendered for option 2. So what happens here?
0
0
214
Dec ’24
UIViewRepresentable is not working
I have been trying to integrate a UIKit view into SwiftUI, specifically a WKWebView. However, I keep encountering a does not conform to protocol error. Here's my code: import SwiftUI import WebKit struct SimpleWebView: View { var body: some View { WebViewContainerRepresentable() .edgesIgnoringSafeArea(.all) } } struct WebViewContainerRepresentable: UIViewRepresentable { typealias UIViewType = WKWebView func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() if let url = Bundle.main.url(forResource: "index", withExtension: "html") { webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) } return webView } func updateUIView(_ uiView: WKWebView, context: Context) { // Updates not required for this use case } } I tried this with other views as well, and it turns out this is not WKWebView-specific. The minimum deployment version is iOS 15. Any help would be much appreciated. Let me know if I need to add any more information.
1
0
589
Dec ’24
MapProxy conversion from screen to coords is wrong on macOS
Try the following code on macOS, and you'll see the marker is added in the wrong place, as the conversion from screen coordinates to map coordinates doesn't work correctly. The screenCoord value is correct, but reader.convert(screenCoord, from: .local) offsets the resulting coordinate by the height of the content above the map, despite the .local parameter. struct TestMapView: View { @State var placeAPin = false @State var pinLocation :CLLocationCoordinate2D? = nil @State private var cameraProsition: MapCameraPosition = .camera( MapCamera( centerCoordinate: .denver, distance: 3729, heading: 92, pitch: 70 ) ) var body: some View { VStack { Text("This is a bug demo.") Text("If there are other views above the map, the MapProxy doesn't convert the coordinates correctly.") MapReader { reader in Map( position: $cameraProsition, interactionModes: .all ) { if let pl = pinLocation { Marker("(\(pl.latitude), \(pl.longitude))", coordinate: pl) } } .onTapGesture(perform: { screenCoord in pinLocation = reader.convert(screenCoord, from: .local) placeAPin = false if let pinLocation { print("tap: screen \(screenCoord), location \(pinLocation)") } }) .mapControls{ MapCompass() MapScaleView() MapPitchToggle() } .mapStyle(.standard(elevation: .automatic)) } } } } extension CLLocationCoordinate2D { static var denver = CLLocationCoordinate2D(latitude: 39.742043, longitude: -104.991531) } (FB13135770)
5
1
1.3k
Dec ’24
Why am I unable to render .dae file in Playground?
This is my code in ContentView: import SwiftUI import SceneKit import PlaygroundSupport struct ContentView: View { var body: some View { VStack { Text("SceneKit with SwiftUI") .font(.headline) .padding() SceneView( scene: loadScene(), options: [.autoenablesDefaultLighting, .allowsCameraControl] ) .frame(width: 400, height: 400) .border(Color.gray, width: 1) } } } func loadScene() -> SCNScene? { if let fileURL = Bundle.main.url(forResource: "a", withExtension: "dae") { do { let scene = try SCNScene(url: fileURL, options: [ SCNSceneSource.LoadingOption.checkConsistency: true ]) print("Scene loaded successfully.") return scene } catch { print("Error loading scene: \(error.localizedDescription)") } } else { print("Error: Unable to locate a.dae in Resources.") } return nil } a.dae file exists in the Resources section of macOS Playground app. And a.dae can be viewed in Xcode. Console shows: Error loading scene: The operation couldn’t be completed. (Foundation._GenericObjCError error 0.) Any input is appreciated.
1
0
507
Dec ’24
Using TextField:text:selection crashes on macOS
I am trying out the new TextField selection ability on macOS but it crashes in various different ways with extremely large stack traces. Looks like it is getting into re-entrant function calls. A similar problem is described on the SwiftUI forums with no responses yet. Here is my simple example struct ContentView: View { @State private var text: String = "" @State private var selection: TextSelection? var body: some View { TextField("Message", text: $text, selection: $selection) .padding() } } Setting text to a value like "Hallo World" causes an instant crash as soon as you start typing in the TextField. Setting text empty (as in example above) lets you edit the text but as it crashes as soon as you commit it (press enter). Any workarounds or fixes?
4
1
502
Dec ’24
Navigation Bar Jumping Issue in SwiftUI with TabView and NavigationStack (Observed in Apple's Example Code)
I recently started exploring the latest version of SwiftUI and encountered an issue while working with TabView and NavigationStack. I downloaded the example code provided by Apple and began making changes to explore new SwiftUI features. However, I noticed that the navigation bar "jumps" or resets when switching between tabs, even in their example implementation. Here are some changes which I made below in the files: LibraryView: .navigationTitle("Library") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color("AccentColor"),for: .navigationBar) WatchNowView: .navigationTitle("Watch Now") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color("AccentColor"),for: .navigationBar) example code url :- destinationVideo I suspect the issue arises because each tab bar item has its own NavigationStack. When we set a navigation title for each view, the NavigationStack resets the navigation bar on view appearance, which causes this visual bug. Thank you!
0
0
282
Dec ’24
Navigation Bar Jumping Issue in SwiftUI with TabView and NavigationStack (Observed in Apple's Example Code)
I recently started exploring the latest version of SwiftUI and came across a issue while working with TabView and NavigationStack. I downloaded Apple’s provided example code and began making changes to explore new SwiftUI changes. i added navigationtitle and toolbarBackground to first two tab. However, I noticed that the navigation bar "jumps" or resets when switching between tabs, even in their own example implementation. Here’s a simplified version of the example code I was testing: file name - WatchNowView .navigationTitle("Watch Now") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color("AccentColor"),for: .navigationBar) file name - LibraryView .navigationTitle("Library") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color("AccentColor"),for: .navigationBar) Here is a sample code link (provided by Apple developer document) : destination-video I have attached a gif below demonstrating this issue: Questions: Is this behavior expected in the latest version of SwiftUI, or is it a bug in the framework's handling of TabView and NavigationStack? Is this behavior expected as all tabbar item have their own nativationStack? Are there any official recommendations for maintaining seamless navigation experiences when using navigationStack and TabView? This behavior detracts from the otherwise smooth experience SwiftUI aims to provide. If anyone has encountered this issue and found a workaround, I’d greatly appreciate your insights. I hope Apple can review this problem to enhance the usability of SwiftUI. Thank you!
3
3
307
Dec ’24
Why is ScrollView / LazyVStack retaining Views which causes memory leaks in the end?
Recently I noticed how my ViewModels aren't deallocating and they end up as a memory leaks. I found something similar in this thread but this is also happening without using @Observation. Check the source code below: class CellViewModel: Identifiable { let id = UUID() var color: Color = Color.red init() { print("init") } deinit { print("deinit") } } struct CellView: View { let viewModel: CellViewModel var body: some View { ZStack { Color(viewModel.color) Text(viewModel.id.uuidString) } } } @main struct LeakApp: App { @State var list = [CellViewModel]() var body: some Scene { WindowGroup { Button("Add") { list.append(CellViewModel()) } Button("Remove") { list = list.dropLast() } ScrollView { LazyVStack { ForEach(list) { model in CellView(viewModel: model) } } } } } } When I tap the Add button twice in the console I will see "init" message twice. So far so good. But then I click the Remove button twice and I don't see any "deinit" messages. I used the Debug Memory Graph in Xcode and it showed me that two CellViewModel objects are in the memory and they are owned by the CellView and some other objects that I don't know where are they coming from (I assume from SwiftUI internally). I tried using VStack instead of LazyVStack and that did worked a bit better but still not 100% "deinits" were in the Console. I tried using weak var struct CellView: View { weak var viewModel: CellViewModel? .... } but this also helped only partially. The only way to fully fix this is to have a separate class that holds the list of items and to use weak var viewModel: CellViewModel?. Something like this: class CellViewModel: Identifiable { let id = UUID() var color: Color = Color.red init() { print("init") } deinit { print("deinit") } } struct CellView: View { var viewModel: CellViewModel? var body: some View { ZStack { if let viewModel = viewModel { Color(viewModel.color) Text(viewModel.id.uuidString) } } } } @Observable class ListViewModel { var list = [CellViewModel]() func insert() { list.append(CellViewModel()) } func drop() { list = list.dropLast() } } @main struct LeakApp: App { @State var viewModel = ListViewModel() var body: some Scene { WindowGroup { Button("Add") { viewModel.insert() } Button("Remove") { viewModel.drop() } ScrollView { LazyVStack { ForEach(viewModel.list) { model in CellView(viewModel: model) } } } } } } But this won't work if I want to use @Bindable such as @Bindable var viewModel: CellViewModel? I don't understand why SwiftUI doesn't want to release the objects?
0
1
482
Dec ’24
SwiftUI bug, when removing a TabView all other tabs have `onAppear` and `onDisappear` triggered
Xcode 14.1 Running on iPhone 14 Pro max simulator 16.1 Code... import SwiftUI struct ContentView: View { @State var loggedIn: Bool = false var body: some View { switch loggedIn { case false: Button("Login") { loggedIn = true } .onAppear { print("🍏 Login on appear") } .onDisappear { print("🍎 Login on disappear") } case true: TabView { NavigationView { Text("Home") .navigationBarTitle("Home") .onAppear { print("🍏 Home on appear") } .onDisappear { print("🍎 Home on disappear") } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Logout") { loggedIn = false } } } } .tabItem { Image(systemName: "house") Text("Home") } NavigationView { Text("Savings") .navigationBarTitle("Savings") .onAppear { print("🍏 Savings on appear") } .onDisappear { print("🍎 Savings on disappear") } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Logout") { loggedIn = false } } } } .tabItem { Image(systemName: "dollarsign.circle") Text("Savings") } NavigationView { Text("Profile") .navigationBarTitle("Profile") .onAppear { print("🍏 Profile on appear") } .onDisappear { print("🍎 Profile on disappear") } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Logout") { loggedIn = false } } } } .tabItem { Image(systemName: "person") Text("Profile") } } .onAppear { print("🍏 Tabview on appear") } .onDisappear { print("🍎 Tabview on disappear") } } } } Video of bug... https://youtu.be/oLKjRGL2lX0 Example steps... Launch app Tap Login Tap Savings tab Tap Home tab Tap Logout Expected Logs... 🍏 Login on appear 🍏 Tabview on appear 🍏 Home on appear 🍎 Login on disappear 🍏 Savings on appear 🍎 Home on disappear 🍏 Home on appear 🍎 Savings on disappear 🍏 Login on appear 🍎 Home on disappear 🍎 Tabview on disappear Actual logs... 🍏 Login on appear 🍏 Tabview on appear 🍏 Home on appear 🍎 Login on disappear 🍏 Savings on appear 🍎 Home on disappear 🍏 Home on appear 🍎 Savings on disappear 🍏 Login on appear 🍏 Savings on appear 🍎 Home on disappear 🍎 Savings on disappear 🍎 Tabview on disappear Error... 10 and 12 in the actual logs should not be there at all. For each tab that you have visited (that is not the current tab) it will call onAppear and onDisappear for it when the tab view is removed.
1
4
1.1k
Dec ’24
Why first View on my NavigationStack appears again when I switch branch?
Hello, In my app, I have an onboarding made of multiple steps in a NavigationStack. I also have a state variable that controls an if else root branch to show either the onboarding NavigationStack or the app content if the onboarding is finished. I noticed that when I end the onboarding (i.e. I switch to the other part of the if else root branch), the onAppear of the first View in the NavigationStack of the onboarding is called again. I don’t understand why. Is this a bug? Thanks, Axel enum Step { case one case two case three case four } struct ContentView: View { @State private var isFinished: Bool = false @State private var steps: [Step] = [] var body: some View { if isFinished { Button("Restart") { steps = [] isFinished = false } } else { NavigationStack(path: $steps) { VStack { Text("Start") .onAppear { print("onAppear: start") } Button("Go to step 1") { steps.append(.one) } } .navigationDestination(for: Step.self) { step in switch step { case .one: Button("Go to step 2") { steps.append(.two) } .onAppear { print("onAppear: step 1") } case .two: Button("Go to step 3") { steps.append(.three) } .onAppear { print("onAppear: step 2") } case .three: Button("Go to step 4") { steps.append(.four) } .onAppear { print("onAppear: step 3") } case .four: Button("End") { isFinished = true } .onAppear { print("onAppear: end") } } } } .onAppear { print("onAppear: NavigationStack") } } } }
6
0
750
Dec ’24