Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

Issue with TabView in Split Screen
Below is a basic test app to resemble an actual app I am working on to hopefully better describe an issue I am having with tab view. It seems only in split screen when I am triggering something onAppear that would cause another view to update, or another view updates on its own, the focus gets pulled to that newly updated view instead of staying on the view you are currently on. This seems to only happen with views that are listed in the more tab. In any other orientation other than 50/50 split this does not happen. Any help would be appreciated. struct ContentView: View { @State var selectedTab = 0 var body: some View { NavigationStack { NavigationLink(value: 0) { Text("ENTER") }.navigationDestination(for: Int.self) { num in TabsView(selectedTab: $selectedTab) } } } } struct TabsView: View { @Binding var selectedTab: Int @State var yikes: Int = 0 var body: some View { if #available(iOS 18.0, *) { TabView(selection: $selectedTab) { MyFlightsView(yikes: $yikes) .tabItem { Label("My Flights", systemImage: "airplane.circle") }.tag(0) FlightplanView() .tabItem { Label("Flight Plan", systemImage: "doc.plaintext") }.tag(1) PreFlightView() .tabItem { Label("Pre Flight", systemImage: "airplane.departure") }.tag(2) CruiseView(yikes: $yikes) .tabItem { Label("Cruise", systemImage: "airplane") }.tag(3) PostFlightView() .tabItem { Label("Post Flight", systemImage: "airplane.arrival") }.tag(4) MoreView() .tabItem { Label("More", systemImage: "ellipsis") }.tag(5) NotificationsView() .tabItem { Label("Notifications", systemImage: "bell") }.tag(6) }.tabViewStyle(.sidebarAdaptable) } } }
1
0
386
Feb ’25
On macOS SwiftUI.TimelineView() inside NSViewController is causing AutoLayout recalculations
I have a complex app that requires the main SwiftUI view of the app to be embedded inside an NSHostingView which is a subview of an NSViewController's view. Then this NSViewController is wrapped using NSViewControllerRepresentable to be presented using SwiftUI's Window. And if I have a TimelineView inside my SwiftUI view hierarchy, it causes constant recalculation of the layout. Here's a simplified demo code: @main struct DogApp: App { private let dogViewController = DogViewController() var body: some Scene { Window("Dog", id: "main") { DogViewControllerUI() } } } private struct DogViewControllerUI: NSViewControllerRepresentable { let dogViewController = DogViewController () func makeNSViewController(context: Context) -> NSViewController { dogViewController } func updateNSViewController(_ nsViewController: NSViewController, context: Context) {} func sizeThatFits(_ proposal: ProposedViewSize, nsViewController: NSViewController, context: Context) -> CGSize? { debugPrint("sizeThatFits", proposal) return nil } } public class DogViewController: NSViewController { public override func viewDidLoad() { super.viewDidLoad() let mainView = MainView() let hostingView = NSHostingView(rootView: mainView) view.addSubview(hostingView) hostingView.translatesAutoresizingMaskIntoConstraints = false hostingView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true hostingView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true hostingView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true hostingView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true } } struct MainView: View { var body: some View { VStack { TimelineView(.animation) { _ in Color.random .frame(width: 100, height: 100) } } } } extension Color { static var random: Color { Color( red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1) ) } } When running it's printing out this repeatedly (multiple times a second). "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) If I run an equivalent code for an iPad, it only prints twice. If I comment out TimelineView on macOS, then it only prints out the above logs when resizing the app window. The main reason this is an issue is that it's clearly causing dramatic degradation in performance. I was told to submit a bug report after I submitted TSI so a SwiftUI engineer could investigate it. Case-ID: 7461887. FB13810482. This was back in May but I received no response. LLMs are no help, and I've experimented with all sorts of workarounds. My last hope is this forum, maybe someone has an idea of what might be going on and why the recalculation is happening constantly on macOS.
1
0
401
Feb ’25
@Binding bools within a VStack getting conflated
I am running into an issue where two distinct bool bindings are both being toggled when I toggle only one of them. My component looks like VStack { Checkbox(label: "Checkbox 1", isOn: $stateVar1) Checkbox(label: "Checkbox 2", isOn: $stateVar2) } where my CheckBox component looks like struct Checkbox: View { let label: String @Binding var isOn: Bool var body: some View { Button { isOn.toggle() } label: { HStack { Image(systemName: isOn ? "checkmark.square" : "square") Text(label) } .foregroundStyle(.black) } } } If I click on one checkbox, both of them get toggled. However, if I simply remove the checkboxes from the VStack, then I am able to toggle them both independently. I believe this is a bug with bool Bindings, but if anyone can point out why I am mistaken that would be much appreciated :)
Topic: UI Frameworks SubTopic: SwiftUI
1
0
281
Feb ’25
SwiftUI Gestures: Sequenced Long Press and Drag
In creating a sequenced gesture combining a LongPressGesture and a DragGesture, I found that the combined gesture exhibits two problems: The @GestureState does not properly update as the gesture progresses through its phases. Specifically, the updating(_:body:) closure (documented here) is only ever executed during the drag interaction. Long presses and drag-releases do not call the updating(_:body:) closure. Upon completing the long press gesture and activating the drag gesture, the drag gesture remains empty until the finger or cursor has moved. The expected behavior is for the drag gesture to begin even when its translation is of size .zero. This second problem – the nonexistence of a drag gesture once the long press has completed – prevents access to the location of the long-press-then-drag. Access to this location is critical for displaying to the user that the drag interaction has commenced. The below code is based on Apple's example presented here. I've highlighted the failure points in the code with // *. My questions are as follows: What is required to properly update the gesture state? Is it possible to have a viable drag gesture immediately upon fulfilling the long press gesture, even with a translation of .zero? Alternatively to the above question, is there a way to gain access to the location of the long press gesture? import SwiftUI import Charts enum DragState { case inactive case pressing case dragging(translation: CGSize) var isDragging: Bool { switch self { case .inactive, .pressing: return false case .dragging: return true } } } struct ChartGestureOverlay<Value: Comparable & Hashable>: View { @Binding var highlightedValue: Value? let chartProxy: ChartProxy let valueFromChartProxy: (CGFloat, ChartProxy) -> Value? let onDragChange: (DragState) -> Void @GestureState private var dragState = DragState.inactive var body: some View { Rectangle() .fill(Color.clear) .contentShape(Rectangle()) .onTapGesture { location in if let newValue = valueFromChartProxy(location.x, chartProxy) { highlightedValue = newValue } } .gesture(longPressAndDrag) } private var longPressAndDrag: some Gesture { let longPress = LongPressGesture(minimumDuration: 0.2) let drag = DragGesture(minimumDistance: .zero) .onChanged { value in if let newValue = valueFromChartProxy(value.location.x, chartProxy) { highlightedValue = newValue } } return longPress.sequenced(before: drag) .updating($dragState) { value, gestureState, _ in switch value { case .first(true): // * This is never called gestureState = .pressing case .second(true, let drag): // * Drag is often nil // * When drag is nil, we lack access to the location gestureState = .dragging(translation: drag?.translation ?? .zero) default: // * This is never called gestureState = .inactive } onDragChange(gestureState) } } } struct DataPoint: Identifiable { let id = UUID() let category: String let value: Double } struct ContentView: View { let dataPoints = [ DataPoint(category: "A", value: 5), DataPoint(category: "B", value: 3), DataPoint(category: "C", value: 8), DataPoint(category: "D", value: 2), DataPoint(category: "E", value: 7) ] @State private var highlightedCategory: String? = nil @State private var dragState = DragState.inactive var body: some View { VStack { Text("Bar Chart with Gesture Interaction") .font(.headline) .padding() Chart { ForEach(dataPoints) { dataPoint in BarMark( x: .value("Category", dataPoint.category), y: .value("Value", dataPoint.value) ) .foregroundStyle(highlightedCategory == dataPoint.category ? Color.red : Color.gray) .annotation(position: .top) { if highlightedCategory == dataPoint.category { Text("\(dataPoint.value, specifier: "%.1f")") .font(.caption) .foregroundColor(.primary) } } } } .frame(height: 300) .chartOverlay { chartProxy in ChartGestureOverlay<String>( highlightedValue: $highlightedCategory, chartProxy: chartProxy, valueFromChartProxy: { xPosition, chartProxy in if let category: String = chartProxy.value(atX: xPosition) { return category } return nil }, onDragChange: { newDragState in dragState = newDragState } ) } .onChange(of: highlightedCategory, { oldCategory, newCategory in }) } .padding() } } #Preview { ContentView() } Thank you!
7
1
1.6k
Mar ’25
iOS ImageRenderer Unable to localize text correctly Bug
A simple view has misaligned localized content after being converted to an image using ImageRenderer. This is still problematic on real phone and TestFlight I'm not sure what the problem is, I'm assuming it's an ImageRenderer bug. I tried to use UIGraphicsImageRenderer, but the UIGraphicsImageRenderer captures the image in an inaccurate position, and it will be offset resulting in a white border. And I don't know why in some cases it encounters circular references that result in blank images. "(1) days" is also not converted to "1 day" properly.
4
1
1.1k
Mar ’25
Why is this causing my app to crash?
I'm developing an app for my watch and have a list of different classes (referred to as 'courses' to avoid confusion) that I take in school, eg: struct Course { let name: String let icon: String let room: String let colour: String let listName: String let listIcon: String init(name: String, icon: String, room: String? = nil, colour: String, listName: String? = nil, listIcon: String? = nil) { self.name = name self.icon = icon self.room = room ?? "None" self.colour = colour self.listName = listName ?? name self.listIcon = listIcon ?? icon+".circle.fill" } } // here's a few of my Course variables (there are lots more I've excluded) let MathsCourse = Course(name: "Maths", icon: "number", room: "FT5", colour: "Rose") let English6 = Course(name: "English", icon: "book.closed", room: "BT6", colour: "Lemon") let LunchPeriod = Course(name: "Lunch", icon: "fork.knife", room: "food", colour: "White") and I have designed a 'list view' of all the courses I have on whatever day it is. I used to define a different View for every course I defined but I merged the list data with the overall Course and replaced the Views with something that I should be able to call repeatedly and pass in a course to use, but unfortunately it's not working. (yes, I'm making a timetable app) This is the template for a 'list view' for a class: struct courseListView: View { var localcourse: Course var localtime: String var body: some View { HStack{ Image(systemName: localcourse.listIcon) .foregroundColor(Color(localcourse.colour)) .padding(.leading, 5) Text(localcourse.name) .bold() Spacer() Text(localtime) Text(roomOrBlank(course: localcourse)).bold().padding(.trailing, 5) } .padding(.bottom, 1) .background(currentCourse.name==localcourse.name ? Color(localcourse.colour).colorInvert(): nil) } } Then I should be able to programmatically work out what courses I have that day (I haven't scripted that bit yet), and compose a view containing all the courses: struct ListView: View { var body: some View { ScrollView { VStack(alignment: .leading) { courseListView(localcourse: MathsCourse, localtime: "10:00") // ^^^ note above line; I'll come back to this // the idea is I can repeat that for a bunch of courses: courseListView(localcourse: English6, localtime: "11:00") courseListView(localcourse: LunchPeriod, localtime: "12:00") } } } } Then be able to call all that in my @main: @main struct Timetaber_Watch_AppApp: App { var body: some Scene { WindowGroup { TabView{ HomeView() ListView() SettingsView() } .tabViewStyle(.carousel) .onAppear() { log() } } } } Unfortunately, each time I try to get a list view for a course, // if you need a reminder: courseListView(localcourse: MathsCourse, localtime: "10:00") ...even only calling it once causes my entire app to crash. Here's an excerpt from the crash report: Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x0000000180210194 Termination Reason: SIGNAL 5 Trace/BPT trap: 5 Terminating Process: exc handler [14932] Triggered by Thread: 0 Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libdispatch.dylib 0x180210194 _dispatch_once_wait.cold.1 + 28 1 libdispatch.dylib 0x1801db4f4 _dispatch_once_wait + 184 2 ??? 0x3400200d0 ??? 3 ??? 0x340020198 ??? 4 ... So... Anyone know what's happening?
3
0
313
Mar ’25
MacOS: Spacing between NavigationLink-s in a sidebar with NavigationView.
How can I put one list item at the top and another one at the bottom, retaining the NavigationView functionality? Here is a simple app: struct ContentView: View { var body: some View { NavigationView { Sidebar() } } } struct Sidebar: View { @State private var isActive = true var body: some View { List { NavigationLink(isActive: $isActive) { HomeView() } label: { Text("Home") } NavigationLink { SettingsView() } label: { Text("Settings") } } } } struct HomeView: View { var body: some View { VStack {} .navigationTitle("Home") } } struct SettingsView: View { var body: some View { VStack {} .navigationTitle("Settings") } } Which looks like this: My initial though was to put a Spacer() between each NavigationLink, but it results in an unexpected view: What i can do: Place an empty VStack between each NavigationLink with a hard-coded height like this: VStack {}.frame(height: 275) Which looks like this: But it wouldn't work if a user would want to increase the height of a window. I could disable window resizing which is kind of fine, but not the most optimal. Another obvious option was to replace the List with a VStack, but with this approach the styling of the NavigationLink gets broken and it does not get highlighted when I click on it. It looks like this: P.S. I know that NavigationView is deprecated, but i want to support macOS 12.0.
1
0
365
Mar ’25
SwiftUI NavigationView background
Hello everyone. Can someone please help me. I am completely lost and have exhausted everything I know to do. I have a Navigation View with a list inside of it. For some reason, there is a gray background behind my list. I'm assuming this is due to some type of padding with the Navigation View but I can't seem to be able to adjust the background or change it to clear. I have attached an image of what I'm mentioning to hopefully better explain. You will see the green bar at the top. that is the background of another view behind this view. I want to either fully cover the screen with the gray background or remove it completely.
Topic: UI Frameworks SubTopic: SwiftUI
1
0
186
Mar ’25
How to reverse a custom Domain in Swift Charts?
I'm currently building an app in SwiftUI that needs to show some charts. Swift Charts has been quite helpful but I can't seem to set the domain of the chart just how I want it. The following chart display events that happend in a week and I want to display every hour even if nothing happened there, and I want the hours to go up, instead of the default where the new day start at the top of the chart. struct ChartView: View { let dataSets: [someData] // simplified date init let datemin = date(year:2025, month: 2, day: 24) let datemax = date(year:2025, month: 2, day: 25) var body: some View { Chart(dataset) { data in PointMark(x: .value("Day", data.day, unit: .weekday), y: .value("Time", data.time, unit: .minute)) } } // The focus is on this line .chartYScale(domain: .automatic(reversed: true)) } } The .chartYScale(domain:) modifier allows me to set the start of the day at the bottom, but still ignores some hours. If I instead use this Chart(...) { ... } .chartYScale(domain: datemin...datemax) The chart display every hour of the day, but now the start of the day is at the bottom. I can't seem to find a way to get both things at the same time. if I add both modifiers only the first one get applied while the other ignored. Any solutions or workarounds?
2
0
396
Mar ’25
Invalid Numeric Value (NaN) Error in SwiftUI's TextField on Long-Press
I'm experiencing a peculiar issue with SwiftUI's TextField. Whenever I long-press on the TextField, the console outputs an error about passing an invalid numeric value (NaN, or not-a-number) to the CoreGraphics API. This issue persists even in a new Xcode project with minimal code. Code Snippet: import SwiftUI struct ContentView: View { @State private var text: String = "" var body: some View { TextField("Placeholder", text: $text) } } Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem. Steps to Reproduce: Create a new SwiftUI project in Xcode. Add a TextField to the ContentView. Run the app on a device or simulator. Long-press inside the TextField. What I've Tried: Updating to the latest version of Xcode and iOS. Using UIViewRepresentable to wrap a UIKit UITextField. Creating a new Xcode project to isolate the issue. None of these steps have resolved the issue. Questions: Has anyone else encountered this problem? Are there any known workarounds for this issue? Is this a known bug, and if so, has it been addressed in any updates?
21
34
14k
Mar ’25
Switching my App from UserDefaults to CoreData and CloudKit
I need someone to tell me if it’s possible to switch my whole app from user defaults to core data. My app is pretty data and calculation intensive and I don’t think user defaults is enough to store and retrieve all the data. Also, I need my app to be iCloud enabled so that the user can access their data from any of their devices. (I’m very new to this coding thing and I’ve been using AI for my entire app)
Topic: UI Frameworks SubTopic: SwiftUI
1
0
199
Mar ’25
Button Behavior between fullScreenCover and sheet
The behavior of the Button in ScrollView differs depending on how the View is displayed modally. When the View is displayed as a .fullScreenCover, if the button is touched and scrolled without releasing the finger, the touch event is canceled and the action of the Button is not called. On the other hand, if the View is displayed as a .sheet, the touch event is not canceled even if the view is scrolled without lifting the finger, and the action is called when the finger is released. In order to prevent accidental interaction, I feel that the behavior of .fullScreenCover is better, as it cancels the event immediately when scrolling. Can I change the behavior of .sheet? Demo movie is here: https://x.com/kenmaz/status/1896498312737611891 Sample code import SwiftUI @main struct SampleApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var showSheet = false @State private var showFullScreen = false var body: some View { VStack(spacing: 16) { Button("Sheet") { showSheet.toggle() } Button("Full screen") { showFullScreen.toggle() } } .sheet(isPresented: $showSheet) { SecondView() } .fullScreenCover(isPresented: $showFullScreen) { SecondView() } .font(.title) } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { ScrollView { Button("Dismiss") { dismiss() } .buttonStyle(MyButtonStyle()) .padding(.top, 128) .font(.title) } } } private struct MyButtonStyle: ButtonStyle { func makeBody(configuration: Self.Configuration) -> some View { configuration .label .foregroundStyle(.red) .background(configuration.isPressed ? .gray : .clear) } }
Topic: UI Frameworks SubTopic: SwiftUI
0
0
190
Mar ’25
How To Change Animation Speed while it is running in RealityView
I have a USDZ 3d model contains a running man animation and I manage to run the model well using this code: import SwiftUI import RealityKit struct ContentView: View { @State var animationResource: AnimationResource? @State var animationDefinition: AnimationDefinition? @State var manPlayer = Entity() @State var speed:Float = 0.5 var body: some View { VStack { RealityView { content in if let item = try? await Entity(named: "run.usdz") { manPlayer = item content.add(manPlayer) } } HStack { Button(action: playThis) { Text("Play") } Button(action: increaseSpeed) { Text("increase Speed (+) ") } Button(action: decreaseSpeed) { Text("decrease Speed (-) ") } } } } func playThis() { animationResource = manPlayer.availableAnimations[0] animationDefinition = animationResource?.definition animationDefinition?.repeatMode = .repeat animationDefinition?.speed = speed // i could not add the definition to the animation resource back again // so i generated a new one let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } func increaseSpeed() { speed += 0.1 animationDefinition?.speed = speed // Now i wonder is this the best way to increase speed // isn't it as if im adding more load to the memory // by adding another players let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } func decreaseSpeed() { speed -= 0.1 animationDefinition?.speed = speed // Now i wonder is this the best way to increase speed // isn't it as if im adding more load to the memory // by adding another players let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } } how to control speed of this animation while it is running without have to regenerate a resource and replay the animation over and over with every speed change knowing that every time the animation replayed it started from the frame zero meaning its not completing its cycle before its replayed but cut in the middle and start over again from start which I do not prefer to be happen. The USDZ file is here if you wish to try https://www.worldhotelity.com/stack/run.usdz
1
0
406
Mar ’25
SwiftUI Gestures prevent subview gesture when build with XCode 16 in iOS 18
I have a view with some buttons, and add 2 gestures using simultaneously. My app works well when built with XCode less than 16, or run on iOS less than 18.0. Example code is below: VStack(spacing: 0) { Button { print("button tapped") } label: { Rectangle() .foregroundColor(.red) } .frame(height: 100) } .gesture( DragGesture(minimumDistance: 0) .onEnded { value in print("single tap") } .simultaneously(with: TapGesture(count: 2).onEnded { print("double tap") } ) ) .frame(width: 200, height: 200) .border(Color.purple) I expect the action on Button should be recognized and print out button tapped, but only single tap and double tap are recognized
0
1
366
Mar ’25
PhoneSceneDelegate white screen
I am currently implementing multiple scenes in my React Native / Swift application (one scene for the phone and one scene for CarPlay). I am facing an issue where one scene renders completely white (on the iPhone) but I can see in the console that the code is running (for example if I add a console.log to the App.tsx I can see that console log happen in XCode). There are no errors when building the app in XCode, and testing with the simulator CarPlay appears to render the correct output, but there is no component being rendered on the simulated phone screen (just white). AppDelegate.swift import CarPlay import React import React_RCTAppDelegate import ReactAppDependencyProvider import UIKit @main class AppDelegate: RCTAppDelegate { var rootView: UIView?; static var shared: AppDelegate { return UIApplication.shared.delegate as! AppDelegate } override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { self.moduleName = "appName" self.dependencyProvider = RCTAppDependencyProvider() self.initialProps = [:] self.rootView = self.createRootView( with: RCTBridge( delegate: self, launchOptions: launchOptions ), moduleName: self.moduleName!, initProps: self.initialProps! ); return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { if (connectingSceneSession.role == UISceneSession.Role.carTemplateApplication) { let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role) scene.delegateClass = CarSceneDelegate.self return scene } let scene = UISceneConfiguration(name: "Phone", sessionRole: connectingSceneSession.role) scene.delegateClass = PhoneSceneDelegate.self return scene } override func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {} override func sourceURL(for bridge: RCTBridge) -> URL? { self.bundleURL() } override func bundleURL() -> URL? { #if DEBUG RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") #else Bundle.main.url(forResource: "main", withExtension: "jsbundle") #endif } } PhoneSceneDelegate.swift import Foundation import UIKit import SwiftUI class PhoneSceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow?; func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { if session.role != .windowApplication { return } guard let appDelegate = (UIApplication.shared.delegate as? AppDelegate) else { return } guard let windowScene = (scene as? UIWindowScene) else { return } let rootViewController = UIViewController() rootViewController.view = appDelegate.rootView; let window = UIWindow(windowScene: windowScene) window.rootViewController = rootViewController self.window = window window.makeKeyAndVisible() } } App.tsx import React, {useEffect, useState} from 'react'; import type {PropsWithChildren} from 'react'; import {CarPlay, ListTemplate} from 'react-native-carplay'; import { ScrollView, StatusBar, StyleSheet, Text, useColorScheme, View, } from 'react-native'; import { Colors, DebugInstructions, Header, LearnMoreLinks, ReloadInstructions, } from 'react-native/Libraries/NewAppScreen'; type SectionProps = PropsWithChildren<{ title: string; }>; function Section({children, title}: SectionProps): React.JSX.Element { const isDarkMode = useColorScheme() === 'dark'; return ( <View style={styles.sectionContainer}> <Text style={[ styles.sectionTitle, { color: isDarkMode ? Colors.white : Colors.black, }, ]}> {title} </Text> <Text style={[ styles.sectionDescription, { color: isDarkMode ? Colors.light : Colors.dark, }, ]}> {children} </Text> </View> ); } function App(): any { // React.JSX.Element const isDarkMode = useColorScheme() === 'dark'; const backgroundStyle = { backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, }; const [carPlayConnected, setCarPlayConnected] = useState(CarPlay.connected); useEffect(() => { function onConnect() { setCarPlayConnected(true); CarPlay.setRootTemplate(new ListTemplate(/** This renders fine on the CarPlay side */)); } function onDisconnect() { setCarPlayConnected(false); } CarPlay.registerOnConnect(onConnect); CarPlay.registerOnDisconnect(onDisconnect); return () => { CarPlay.unregisterOnConnect(onConnect); CarPlay.unregisterOnDisconnect(onDisconnect); }; }); if (carPlayConnected) { console.log('car play connected'); } else { console.log('car play not connected'); } const safePadding = '5%'; // This doesn't render on the phone? return ( <View style={backgroundStyle}> <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} backgroundColor={backgroundStyle.backgroundColor} /> <ScrollView style={backgroundStyle}> <View style={{paddingRight: safePadding}}> <Header/> </View> <View style={{ backgroundColor: isDarkMode ? Colors.black : Colors.white, paddingHorizontal: safePadding, paddingBottom: safePadding, }}> <Section title="Step One"> Edit <Text style={styles.highlight}>App.tsx</Text> to change this screen and then come back to see your edits. </Section> <Section title="See Your Changes"> <ReloadInstructions /> </Section> <Section title="Debug"> <DebugInstructions /> </Section> <Section title="Learn More"> Read the docs to discover what to do next: </Section> <LearnMoreLinks /> </View> </ScrollView> </View> ); } const styles = StyleSheet.create({ sectionContainer: { marginTop: 32, paddingHorizontal: 24, }, sectionTitle: { fontSize: 24, fontWeight: '600', }, sectionDescription: { marginTop: 8, fontSize: 18, fontWeight: '400', }, highlight: { fontWeight: '700', }, }); export default App; I have been attempting to get this working now for some 20+ hours with no luck with searching for answers elsewhere. I am very new to building apps with React Native and Swift so could do with some support.
0
0
360
Mar ’25
App Clip iMessage Sharing Not Working
We have been having problems with our app clip not working when sharing through iMessage. The app and app clip are published and work correctly when scanning a QR code that points to the URL: https://www.coderus.com/locations?loc=1 however if this same URL is shared through the iMessage app, a link to the website displays and not the app clip card. We have confirmed that: AASA file is available and has the type application/json Both devices are above iOS 14 Both devices are in each other's contacts The website has the meta tag for the smart app clip banner The website has a meta tag for the og:image Launch experiences have been configured on AppStoreConnect - as said before, the QR codes work correctly The link leads to a 404 page, I wasn't sure if there needs to be an actual page that the link points to as app clips seem to work fine without when scanning the QR code through the camera app.
3
1
1.2k
Mar ’25
NavigationSplitView sidebar animation lag with minimum width
Hi, when I run NavigationSplitView as shown below, the sidebar opens and closes smoothly. struct TestingView: View { var body: some View { NavigationSplitView { Text("Sidebar") } detail: { Text("Detail") } } } However, when I add a minimum width, the sidebar animation starts to lag. I tried various wapping solutions, but I couldn’t get rid of the stutter. struct TestingView: View { var body: some View { NavigationSplitView { Text("Sidebar") } detail: { Text("Detail") } .frame(minWidth: 800) } } As a solution, I had to disable the animation completely: .animation(nil, value: columnVisibility) Is there a way to keep the animation without the stuttering?
2
0
366
Mar ’25
Infinite loop refreshing view with EnvironmentValue
Adding environment value openURL or dismiss to a View in a NavigationStack, without even using it, causes an infinite refresh loop. What doesn't work: a) struct ViewA: View { @State private var path = NavigationPath() var body: some View { NavigationStack(path: $path) { ViewB() } } } struct ViewB: View { @Environment(\.openURL) var openURL var body: some View { NavigationLink("Next", value: 1) .navigationDestination(for: Int.self, destination: itemView) } func itemView(_ item: Int) -> some View { Text("Item \(item)") } } Prints ViewB: _openURL changed. infinitely. b) Passing the path to ViewB and appending the value with a Button What works: a) .navigationDestination(for: Int.self) { Text("Item \($0)") } Prints ViewB: @self, @identity, _openURL changed. ViewB: @self, _openURL changed. ViewB: _openURL changed. (3 times) b) Handling the destination on ViewA, which is not ideal for my use case. Prints ViewB: @self, @identity, _openURL changed. ViewB: _openURL changed. (5 times) While the workaround would work, it is still unclear how the environment value can cause the freeze (and eventual crash). Also that passing a function as parameter fails, while providing the destination in place does not. The code is stripped down to the minimal reproducible version. Any thoughts?
3
9
993
Mar ’25
`.refreshable(action:)` `s indicator will not dismiss after when app into backgound (iOS 17.1)
Hello, I am encountering an issue with .refreshable(action:) in ScrollView. The refresh action works as expected when performing a pull-to-refresh. However, if I put the app in the background while the refresh operation is in progress, the refresh indicator remains visible on the screen when I return to the foreground and does not disappear. Once I interact with the ScrollView after returning to the foreground, the refresh indicator disappears, and the functionality itself is not affected. I initially attempted to resolve this issue by triggering a view redraw when scenePhase changes. However, since my app presents the SwiftUI view using UIHostingController, the scenePhase from the environment does not seem to function correctly. This issue occurs on iOS 17.1 but does not appear on iOS 16.1.1. Is there a known way to resolve this unexpected behavior? Below is a simplified sample code (some parts are omitted): struct MyView: View { @StateObject private var model: MyModel var body: some View { ScrollView { // My ContentViews... } .refreshable { do { try await self.model.refresh() } catch { // Handle error } } } } @MainActor final class MyModel: ObservableObject { // === Some Code === func refresh() async throws { let data = try await self.fetchData() self.data = Array(OrderedSet(data)) } } I apologize for any mistakes in my English, as I am using a translation tool. Thank you in advance for your help! Best regards,
1
0
207
Mar ’25