I am developing a macOS app using SwiftUI, and I am encountering an issue when launching the app at login. The app starts as expected, but the window does not appear automatically. Instead, it remains in the Dock, and the user must manually click the app icon to make the window appear.
Additionally, I noticed that the timestamp obtained during the app's initialization (init) differs from the timestamp obtained in .onAppear. This suggests that .onAppear does not trigger until the user interacts with the app. However, I want .onAppear to execute automatically upon login.
Steps to Reproduce
Build the app and add it to System Settings > General > Login Items as an item that opens at login.
Quit the app and restart the Mac.
Log in to macOS.
Observe that the app starts and appears in the Dock but does not create a window.
Click the app icon in the Dock, and only then does the window appear.
Expected Behavior
The window should be created and appear automatically upon login without requiring user interaction.
.onAppear should execute immediately when the app starts at login.
Observed Behavior
The app launches and is present in the Dock, but the window does not appear.
.onAppear does not execute until the user manually clicks the app icon.
A discrepancy exists between the timestamps obtained in init and .onAppear.
Sample Code
Here is a minimal example that reproduces the issue:
LoginTestApp.swift
import SwiftUI
@main
struct LoginTestApp: App {
@State var date2: Date
init(){
date2 = Date()
}
var body: some Scene {
WindowGroup {
MainView(date2: $date2)
}
}
}
MainView.swift
import SwiftUI
struct MainView: View {
@State var date1: Date?
@Binding var date2: Date
var body: some View {
Text("This is MainView")
Text("MainView created: \(date1?.description ?? "")")
.onAppear {
date1 = Date()
}
Text("App initialized: \(date2.description)")
}
}
Test Environment
Book Pro 13-inch, M1, 2020
macOS Sequoia 15.2
Xcode 16.2
Questions
Is this expected behavior in macOS Sequoia 15.2?
How can I ensure that .onAppear executes automatically upon login?
Is there an alternative approach to ensure the window is displayed without user interaction?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
In macOS application, we are using SwiftUI as an entry point to our application and attaching appdelegate using NSApplicationDelegateAdaptor.
We are using NSViewControllerRepresentable to add a View Controller to the hiracrchy so that we can store intance of viewcontroller and add content to it programatically .
@main
struct TWMainApp: App {
@NSApplicationDelegateAdaptor private var appDelegate: TWAppDelegate
internal var body : some Scene {
TWInitialScene ()
}
}
TWInitialScene :
public struct TWInitialScene : Scene {
public var body : some Scene {
WindowGroup {
TWInitialView ()
}
}
}
TWInitialView :
struct TWInitialView : View {
@Environment(\.scenePhase) private var scenePhase
var body : some View {
TWAppKitToSwiftUIBridge ()
}
}
TWAppKitToSwiftUIBridge :
struct TWNSKitToSwiftUIBridge : NSViewControllerRepresentable {
func makeNSViewController(context: Context) -> TWNSViewController {
let view_hierarchy : TWNSViewController
view_hierarchy = TWStaticContext.sViewController
return view_hierarchy
}
func updateNSViewController(_ nsViewController: TWNSViewController, context: Context) {
}
}
@objc
public class TWStaticContext : NSObject
{
public static let sViewController = TWNSViewController ()
public override init () {}
@objc
public static func GetViewController () -> TWNSViewController
{
return TWStaticContext.sViewController
}
}
public class TWNSViewController : NSViewController {
override public func viewDidLoad ()
{
super.viewDidLoad ()
}
}
To add content to the hirarchy we are accessing viewcontroller's intance and adding content to it like this :
public func PaintInitialScreen () {
let label = NSTextField(labelWithString: "TW window")
label.frame = NSRect(x: 100, y: 200, width: 200, height: 200)
// Adding content to viewcontroller
TWStaticContext.sViewController.view.addSubview(label)
}
We are using this approach because we have a contraint in our application that we have to update UI programatically and on compile time we dont know what we want to show . We will be adding content on runtime based on how many button we want, what label we want , where to place it etc.
When we were using purely appKit application, doing things programatically was simple but since SwiftUI is a declarative application we have to use above approach.
Rational for shifting to SwiftUI entry point is that we want our application to be future safe and since apple is more inclined to SwiffUI, we want to design our entry flow to use SwiftUI entry point . And SwiftUI being declarative, we are using appKit to add content to hiracrchy programtically.
We have used similar apprach in iOS also , where are using UIApplicationDelegateAdaptor inplace of NSApplicationAdaptor . And UIViewControllerReprestable in place of NSViewControllerRepresentable.
Is this right approach to use ?
Hi all, I am looking for a futureproof way of getting the Screen Resolution of my display device using SwiftUI in MacOS. I understand that it can't really be done to the fullest extent, meaning that the closest API we have is the GeometeryProxy and that would only result in the resolution of the parent view, which in the MacOS case would not give us the display's screen resolution. The only viable option I am left with is NSScreen.frame.
However, my issue here is that it seems like Apple is moving towards SwiftUI aggressively, and in order to futureproof my application I need to not rely on AppKit methods as much. Hence, my question: Is there a way to get the Screen Resolution of a Display using SwiftUI that Apple itself recommends? If not, then can I rely safely on NSScreen's frame API?
Hi,
I have created a line graph using LineMark in Charts, which by default includes grid lines and axes lines. My requirement is to remove the grid lines but retain the axes lines and the values.
I have tried the following code:
.chartXAxis {
AxisMarks(preset: .extended, values: .stride(by: 2), stroke: StrokeStyle(lineWidth: 0))
}
This is removing grid lines as well as axes lines.
How to retain axes lines while removing grid lines ?
Hi,
I am developing a new SwiftUI app. Running under OSX, I see very high cpu usage (I am generating lots of gpu based updates which shouldn't affect the cpu).
I have used the profiler to ensure my swift property updates are minimal, yet the cpu usage is high coming from SwiftUI.
It seems the high cpu usage is coming from NSAppearance, specifically, CUICopyMeasurements - for a single button??? But the swift updates don't show any buttons being updating
I have a SwiftUI LineMark chart that inverts the y axis when the data the chart is plotting is all zeros. I'm expecting the y axis 0 to be at the bottom but when the data is all zeros it's at the top. Below is an example demonstrating the problem:
import SwiftUI
import Charts
struct ChartView: View {
let data: [Double] = [0,0,0,0,0]
var body: some View {
Chart {
ForEach(data.indices, id: \.self) { index in
LineMark(
x: .value("Index", index),
y: .value("Value", data[index])
)
}
}
.chartYAxis {
AxisMarks(values: [0, 10, 20, 30, 40, 50]) { value in
AxisValueLabel()
AxisTick()
AxisGridLine()
}
}
.padding()
}
}
I can't use .chartYScale(domain: ) because it overrides the chartYAxis where the real code creates custom a leading and trailing y axis.
Does anyone have any suggestions how I may fix this?
I am considering of shifting my codebase from appkit to SwiftUI entry point.
In Appkit, we get control on each NSWindow. So that we can hide/resize window, close window and controll when to present a specific window . Because i have access to NSWindow instance which i can store and perform these actions.
But when i shift to SwiftUI entry point, i declare struct conforming to SwiftUI Scene. And new windows will be created with the instance of this scene.
I am using NSViewControllerRepresentable to add a NSViewController to the hierarchy of these scene. And adding content to this NSViewController's instance to show on screen.
I need help in controlling the size of these windows. How can i close specific window ? Resize specific window ? or Hide specific window?
If i use purely SwiftUI view's , then i can do this by using the Enviorment propery and use DismissWindow to close a window or openWindow with identifier to open a specific window by passing the specificer .
But i am using Appkit's NSViewController where i will add buttons in heirarchy from which i want to trigger these events . And in that case how can i controll a specific window in case of multiwindow application?
I've encountered an issue where storing a throws(PermissionError) closure as a property inside a SwiftUI View causes a runtime crash on iOS 17, while it works correctly on iOS 18.
Here’s an example of the affected code:
enum PermissionError: Error {
case denied
}
struct PermissionCheckedView<AllowedContent: View, DeniedContent: View>: View {
var protectedView: () throws(PermissionError) -> AllowedContent
var deniedView: (PermissionError) -> DeniedContent
init(
@ViewBuilder protectedView: @escaping () throws(PermissionError) -> AllowedContent,
@ViewBuilder deniedView: @escaping (PermissionError) -> DeniedContent
) {
self.protectedView = protectedView
self.deniedView = deniedView
}
public var body: some View {
switch Result(catching: protectedView) {
case .success(let content): content
case .failure(let error): deniedView(error)
}
}
}
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
PermissionCheckedView {
} deniedView: { _ in
}
}
}
}
Specifically this is the stack trace (sorry for the picture I didn't know how to get the txt):
If I use var protectedView: () throws -> AllowedContent without typed throws it works.
Hello, since I'm using SwiftUI and some interface should be optimized for different devices(like iPad and iPhone), so I'm curious that what device would be used to run the App? Is it iPad or iPhone?
And could I use SDKs like SiriKit?
We are trying to write an iOS app that supports regular and constrained widths using a TabView with .tabViewStyle(.sidebarAdaptable). On the surface this seems like a great way to write an app that supports all the different widths that your app may run in. Especially since Stage Manager and Apple Vision have made it easy for users to resize your apps window while it is running.
We are facing many challenges though. I will give a brief one liner of each below, but to truly experience them you need to run the sample app, or watch the sample videos included.
Issues
Basic TabView Issues
Double Navigation Bar: When tabs are collapsed into a "More" tab, there's an unwanted double navigation bar
Selection Sync: Tab selection gets out of sync when switching between narrow/wide layouts through the "More" tab
TabView Crash
Fatal crash occurs when resizing window to narrow width while Tab 5 is selected
Error: SwiftUI/SidebarAdaptableTabViewStyle_iOS.swift:482: Fatal error: Tried to update with invalid selection value
Section Handling Issues
Section Display Bug: Bottom tabs incorrectly show section names instead of tab names in narrow width
Tab Selection Mismatch: Tab identifiers don't match selected tabs in narrow width mode
Customization Issues
Inconsistent "Edit" button behavior in More tab
Unable to properly disable tab customization
Sample app and video
https://github.com/copia-wealth-studios/swiftui-tabview-sample
I am currently finalizing my Swift Student Challenge submission, and Metal shaders are an essential part of my app. However, during submission, I noticed a note explaining: "Note: Xcode app playgrounds are run in Simulator", which is not possible for my app, as it also requires the camera of a physical device to function. So, I am currently transferring my app from Xcode into Swift Playgrounds, which I presume will run on physical devices.
However, I noticed that Swift Playgrounds do not yet support Metal shaders directly, so I am now pre-compiling my shaders to load them at runtime instead. Note that all the code below was run either in the terminal or in Xcode.
I have already compiled my Metal shaders with:
xcrun -sdk iphoneos metal -o Shaders.ir -c Shaders.metal
xcrun -sdk iphoneos metallib Shaders.ir -o Shaders.metallib
Which seems to have run without any problems.
When I run:
let shaderPath = Bundle.main.path(forResource: "Shaders", ofType: "metallib")
let shaderURL = URL(fileURLWithPath: shaderPath!)
let shaderData = try! Data(contentsOf: shaderURL)
do {
let device = MTLCreateSystemDefaultDevice()!
let library = try shaderData.withUnsafeBytes { bytes -> MTLLibrary? in
let dispatchData = DispatchData(bytes: bytes)
return try device.makeLibrary(data: dispatchData as __DispatchData)
}
print(library!.functionNames)
} catch {
print(error.localizedDescription)
}
My Metal shader functions are printed correctly in the console. However, based on my research, it seems like a MTLLibrary cannot be converted into a SwiftUI ShaderLibrary.
That is why I am now looking at these two initializers:
ShaderLibrary(url: URL)
ShaderLibrary(data: Data)
Which state: Creates a new Metal shader library from the contents of url/data, which must be the contents of precompiled Metal library. Functions compiled from the returned library will only be cached as long as the returned library exists., which I believe should work for my use case.
However, the problem arises when I run this code:
let shaderPath = Bundle.main.path(forResource: "Shaders", ofType: "metallib")
let shaderURL = URL(fileURLWithPath: shaderPath!)
let library = ShaderLibrary(url: shaderURL)
My app consistently seems to crash on the ShaderLibrary initialization, rendering the app unusable. Why does ShaderLibrary(url: shaderURL) cause a crash, even though my .metallib file is valid? Are there additional requirements for loading a ShaderLibrary that I may have missed?
I'm seeing a Live Activity that's ended almost immediately after I'm creating it. I'm not ending the activity in my code, so something is happening at the system level. iOS version is 18.3.1.
Looking at the logs for liveactivitiesd, I see that it was successfully created:
default 12:57:34.837266-0800 liveactivitiesd Created activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B
default 12:57:34.837639-0800 liveactivitiesd Starting activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil
default 12:57:34.858701-0800 liveactivitiesd Activity did start 22713DF6-E853-4B34-85FA-CD08D8FCA91B
But then moments later, it's immediately ended:
default 12:57:34.933963-0800 liveactivitiesd Ending activity 22713DF6-E853-4B34-85FA-CD08D8FCA91B for XPC participant content source <private>
default 12:57:34.933983-0800 liveactivitiesd Stopping activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B
default 12:57:34.934019-0800 liveactivitiesd Activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil should be discarded now
default 12:57:34.934442-0800 liveactivitiesd Activity discarded: 22713DF6-E853-4B34-85FA-CD08D8FCA91B
Again, I'm not ending this activity in my code. I'll occasionally see this happen in my app, and the only solution I've found is to restart my device. Afterwards, everything seems fine.
Is this a bug?
I’m trying to implement my Examples view in my DocumentGroup app on visionOS. I am stuck on what on the surface seems very basic: programmatically opening a document.
Is there an analog to NSDocumentController.shared.openUntitledDocumentAndDisplay on visionOS?
Here’s what I’ve tried so far.
Ideally, this would a be collection of document templates in a DocumentGroupLaunchScene. However, I’ve been unable to get DocumentGroupLaunchScene to work on visionOS.
I’ve tried UIApplication.shared.open(url) with a url to a document in my app bundle. UIApplication.shared.canOpenURL(url) returns true, but open(url) has no effect.
In the macOS build, I use NSDocumentController.shared.openUntitledDocumentAndDisplay, but do not see any iOS or visionOS analog.
@Environment(\.newDocument) private var newDocument would be ideal, but that is not available on visionOS.
UIApplication.shared.activateSceneSession(for: .init()) brings up the document browser in a new window, at which point clicking the “+” button does what I want. Can I invoke that directly somehow?
It would be sufficient if I could programmatically open a new untitled document. On macOS, I do that and sneak the template contents to the Document constructor in a global variable.
I presume I am just overlooking something simple, but I’ve come up blank so far.
VisionOS developers want to modify the color of the button when they detect the eyes focusing on it. May I ask if there are any relevant methods that can be implemented? At present, there is a default highlight color when the eyes focus on the button, but this color is too dim. Not obvious enough, how can I modify it?
thank you!
SwiftUI Navigation Stack Zoom Transition – Title Animation Issue (iOS 18)
In the WWDC24 video "Enhance your UI animations and transitions", Apple demonstrates how the navigation stack title smoothly animates into the back button in the new view when using a zoom transition:
NavigationLink {
BraceletEditor(bracelet)
.navigationTransitionStyle(
.zoom(
sourceID: bracelet.id,
in: braceletList
)
)
} label: {
BraceletPreview(bracelet)
}
.matchedTransitionSource(
id: bracelet.id,
in: braceletList
)
However, I cannot get this animation.
Expected (from WWDC video):
Actual (iOS 18 simulator):
How can I get the original animation?
Hey, I am developing my app in Swift using Xcode for iOS 16 or later.
I want to implement the navigation behavior found in apps like WhatsApp or Instagram, where navigating from the feed to a user's profile keeps the tab bar visible. Then, when opening a chat from the profile, a new view appears, leaving the profile view behind along with the tab bar.
I have this code as a base to achieve this, but when navigating from View 1 to View 2, it applies the effect that should only happen in View 3. I haven't been able to prevent View 2 from using this effect and limit it only to View 3.
Can anyone help me???
import SwiftUI
struct ContentView: View {
@State private var path: [String] = [] // Controls the navigation stack in View1
var body: some View {
NavigationStack(path: $path) {
TabView {
View1(path: $path)
.tabItem {
Label("View 1", systemImage: "1.circle")
}
View4()
.tabItem {
Label("View 4", systemImage: "4.circle")
}
}
.navigationDestination(for: String.self) { value in
if value == "View3" {
View3(path: $path) // View3 outside the TabView
}
}
}
}
}
struct View1: View {
@Binding var path: [String]
var body: some View {
VStack {
Text("View 1 with TabBar")
Button("Go to View 2") {
path.append("View2") // Adds View2 to the stack
}
}
.navigationDestination(for: String.self) { value in
if value == "View2" {
View2(path: $path)
}
}
}
}
struct View2: View {
@Binding var path: [String]
var body: some View {
VStack {
Text("View 2 with TabBar")
Button("Go to View 3 (Without TabBar)") {
path.append("View3") // Adds View3 to the stack
}
}
}
}
struct View3: View {
@Binding var path: [String]
var body: some View {
VStack {
Text("View 3 without TabBar")
.font(.largeTitle)
.padding()
Button("Go Back") {
path.removeLast() // Returns to View2
}
}
}
}
struct View4: View {
var body: some View {
Text("View 4 with TabBar")
}
}
I opened a feedback ticket (FB16508762) but maybe someone in the community already found a workaround while the feedback reaches the maintainers.
When I put a Button inside a ScrollView, the tap animation stops working reliably and works only when the user taps and holds the button for a short time. The reasons, I believe is related to the fact that isPressed of configuration does not change and the default button styles use it to animate the tap.
import SwiftUI
struct DebuggingButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.onChange(of: configuration.isPressed, { oldValue, newValue in
print("Is pressed: \(oldValue) -> \(newValue)")
})
}
}
struct ContentView: View {
var body: some View {
VStack {
Text("Buttons inside scroll view respond to taps as expected, however isPessed value of the configuration do not change unless the user press and hold it. Try to press the promiment button quickly or use the debug button and observe the console log.")
ScrollView {
VStack {
Button("Button Inside ScrollView") {
print("Button tapped")
}
.buttonStyle(.borderedProminent)
Button("Button Inside ScrollView (printing isPressed)") {
print("Button tapped")
}
.buttonStyle(DebuggingButtonStyle())
}
}
.border(FillShapeStyle(), width: 2)
Spacer()
Text("For reference, here is a button outside of a ScrollView. Tap the promiment button to observe how the button is expected to animate in respnse to a press.")
VStack {
Button("Button Outside ScrollView") {
print("Button tapped")
}
.buttonStyle(.borderedProminent)
Button("Button Outside ScrollView (printing isPressed)") {
print("Button tapped")
}
.buttonStyle(DebuggingButtonStyle())
}
}
.padding()
}
}
I gave the FocusCookbook sample project a try and FocusState is not working correctly on iOS 18. I understand the sample was originally designed for iOS 17 when it was released along side the WWDC 2023 talk The SwiftUI Cookbook for Focus. however I am suprised it no longer works on iOS 18.
E.g. when I launch the app on iPhone 16 Pro simulator (Xcode 16.2, iOS 18.2 Simulator) and tap the grocery list nav bar button, the grocery sheet appears however the last entry text field is not focused like .defaultFocus is designed to do.
Futhermore, if I tap the add (+) button and a new entry is added, despite the addEmptyItem() func setting the currentItemID which is the @FocusState var the focus does not change to the new text field.
Is FocusState broken on iOS 18?
Relevant code from GroceryListView.swift
import SwiftUI
struct GroceryListView: View {
@Environment(\.dismiss) private var dismiss
@Binding var list: GroceryList
@FocusState private var currentItemID: GroceryList.Item.ID?
var body: some View {
List($list.items) { $item in
HStack {
Toggle("Obtained", isOn: $item.isObtained)
TextField("Item Name", text: $item.name)
.onSubmit { addEmptyItem() }
.focused($currentItemID, equals: item.id)
}
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
doneButton
}
ToolbarItem(placement: .primaryAction) {
newItemButton
}
}
.defaultFocus($currentItemID, list.items.last?.id)
}
// MARK: New item
private func addEmptyItem() {
let newItem = list.addItem()
currentItemID = newItem.id
}
private var newItemButton: some View {
Button {
addEmptyItem()
} label: {
Label("New Item", systemImage: "plus")
}
}
private var doneButton: some View {
Button {
dismiss()
} label: {
Text("Done")
}
}
}
Could anyone help confirm if this is a bug and suggest possible solutions?
Thanksssss
In iOS 18, when using Zoom NavigationTransition, the toolbar from the destination view may randomly appear on the source view after navigating back with the swipe-back gesture.
Re-entering the destination view and navigating back again can temporarily resolve the issue, but it may still occur intermittently.
This bug only happens with Zoom NavigationTransition and does not occur when using a button tap to navigate back.
import SwiftUI
struct test: View {
@Namespace private var namespace
var body: some View {
NavigationStack {
NavigationLink {
Image("img1")
.resizable()
.navigationTransition(.zoom(sourceID: 1, in: namespace))
.toolbar {
ToolbarItem(placement: .bottomBar) {
Text("destination noDisappear")
}
}
} label: {
Image("img1")
.resizable()
.frame(width: 100, height: 100)
.matchedTransitionSource(id: 1, in: namespace)
.toolbar {
ToolbarItem(placement: .bottomBar) {
Text("source toolbar")
}
}
}
}
}
}
I'm working on an old iOS app that started with objective-C + UIKit and has being migrated to Swift + SwiftUI. Currently its code is mostly Swift + SwiftUI but it has still some objective-C and some UIKit ViewControllers.
One of the SwiftUI views uses fileImporter to open Files App and select a file from the device. This has been working well until iOS 18 is launched. With iOS 18 the file picker is not launching correctly and is frozen in every simulator (the unique real device I've could test with iOS 18 seemed to work correctly).
I managed to clone my project and leave it with the minimal amount of files to reproduce this error. This is the code:
AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate> {}
@property (strong, nonatomic) UIWindow *window;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "MyApp-Swift.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
FirstViewBuilder *viewBuilder = [[FirstViewBuilder alloc] init];
[viewBuilder show];
return YES;
}
@end
FirstViewBuilder.swift
import SwiftUI
@objc class FirstViewBuilder: NSObject {
private var view: UIHostingController<FirstView>
@objc override init() {
self.view = MyHostingController(rootView: FirstView())
}
@objc func show() {
let app = UIApplication.shared.delegate as? AppDelegate
let window = app?.window
window?.backgroundColor = .white
// Use navigationController or view directly depending on use
window?.rootViewController = view
}
}
FirstView.swift
import SwiftUI
struct FirstView: View {
@State var hasToOpenFilesApp = false
var body: some View {
VStack(alignment: .leading, spacing: 0) {
Button("Open Files app") {
hasToOpenFilesApp = true
}.fileImporter(isPresented: $hasToOpenFilesApp, allowedContentTypes: [.text]) { result in
switch result {
case .success(let url):
print(url.debugDescription)
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
}
And finally, MyHostingController
import SwiftUI
class MyHostingController<Content>: UIHostingController<Content> where Content: View {
override init(rootView: Content) {
super.init(rootView: rootView)
}
@objc required dynamic init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
}
}
Launching this in an iPhone 13 Pro (18.2) simulator I click on Open Files App, it takes 2 seconds to open it, and it opens full screen (not like a modal). Buttons on the top are behind the status bar and buttons at the bottom are behind the Home indicator. But it's worse because the user can't interact with this view, it's frozen.
I created a fresh SwiftUI project just with this unique view and the fileimport worked as expected so I thought the problem was due to embed the SwiftUI view inside the UIHostingController. So I made these modifications to the minimal project:
Remove the files AppDelegate, FirstViewBuilder and MyHostingController.
Create this SwiftUI App file
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
FirstView()
}
}
}
And again the same problem with iOS 18.
But if I launch this exact project in an iPhone 13 Pro (17.4) simulator and open the files apps (now it opens almost instantly) it works OK and shows the file picker as a modal, as expected, and I can interact with it and select files.
Last thing I've tried is removing LaunchScreen.xib from my project and Launch screen interface file base name key from my info.plist but the problem keeps happening.
I guess it must be due to my project configuration (too old) but I have no more ideas of where to look at.
The possibility of having a fresh SwiftUI project and "move" the old project to the new one could take me several weeks and I discard it by the moment.
Could I use another method to select files from SwiftUI views with iOS 18?