Apple published a set of examples for using system gestures to interact with RealityKit entities. I've been using DragGesture a lot in my apps and noticed an issue when using it in an immersive space.
When dragging an entity, if I turn my body to face another direction, the dragged entity does not stay relative to my hand. This can lead to situations where the entity is pulled very close to me, or pushed far way, or even ends up behind me.
In the examples linked above, there are two versions of how they use drag.
handleFixedDrag: This is similar to what I'm doing now. It uses the value from value.gestureValue.translation3D as the basis for the drag
handlePivotDrag: This version aims to solve the problem I described above by using value.inputDevicePose3D as the basis of the gesture.
I've tried the example from handlePivotDrag, but it has one limitation. Using this version, I can move the entity around me as if it were on the inside of an arc or sphere. However, I can no longer move the entity further or closer. It stays within a similar (though not exact) distance relative to me while I drag.
Is there a way to combine these concepts? Ideally, I would like to use a gesture that behaves the same way that visionOS windows do. When we drag windows, I can move them around relative to myself, pull them closer, push them further, all while avoiding the issues described above.
Example from handleFixedDrag
mutating private func handleFixedDrag(value: EntityTargetValue<DragGesture.Value>) {
let state = EntityGestureState.shared
guard let entity = state.targetedEntity else { fatalError("Gesture contained no entity") }
if !state.isDragging {
state.isDragging = true
state.dragStartPosition = entity.scenePosition
}
let translation3D = value.convert(value.gestureValue.translation3D, from: .local, to: .scene)
let offset = SIMD3<Float>(x: Float(translation3D.x),
y: Float(translation3D.y),
z: Float(translation3D.z))
entity.scenePosition = state.dragStartPosition + offset
if let initialOrientation = state.initialOrientation {
state.targetedEntity?.setOrientation(initialOrientation, relativeTo: nil)
}
}
Example from handlePivotDrag
mutating private func handlePivotDrag(value: EntityTargetValue<DragGesture.Value>) {
let state = EntityGestureState.shared
guard let entity = state.targetedEntity else { fatalError("Gesture contained no entity") }
// The transform that the pivot will be moved to.
var targetPivotTransform = Transform()
// Set the target pivot transform depending on the input source.
if let inputDevicePose = value.inputDevicePose3D {
// If there is an input device pose, use it for positioning and rotating the pivot.
targetPivotTransform.scale = .one
targetPivotTransform.translation = value.convert(inputDevicePose.position, from: .local, to: .scene)
targetPivotTransform.rotation = value.convert(AffineTransform3D(rotation: inputDevicePose.rotation), from: .local, to: .scene).rotation
} else {
// If there is not an input device pose, use the location of the drag for positioning the pivot.
targetPivotTransform.translation = value.convert(value.location3D, from: .local, to: .scene)
}
if !state.isDragging {
// If this drag just started, create the pivot entity.
let pivotEntity = Entity()
guard let parent = entity.parent else { fatalError("Non-root entity is missing a parent.") }
// Add the pivot entity into the scene.
parent.addChild(pivotEntity)
// Move the pivot entity to the target transform.
pivotEntity.move(to: targetPivotTransform, relativeTo: nil)
// Add the targeted entity as a child of the pivot without changing the targeted entity's world transform.
pivotEntity.addChild(entity, preservingWorldTransform: true)
// Store the pivot entity.
state.pivotEntity = pivotEntity
// Indicate that a drag has started.
state.isDragging = true
} else {
// If this drag is ongoing, move the pivot entity to the target transform.
// The animation duration smooths the noise in the target transform across frames.
state.pivotEntity?.move(to: targetPivotTransform, relativeTo: nil, duration: 0.2)
}
if preserveOrientationOnPivotDrag, let initialOrientation = state.initialOrientation {
state.targetedEntity?.setOrientation(initialOrientation, relativeTo: nil)
}
}
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
A class initialized as the initial value of an @State property is not released until the whole View disappears. Every subsequent instance deinitializes properly.
Am I missing something, or is this a known issue?
struct ContentView: View {
// 1 - init first SimpleClass instance
@State var simpleClass: SimpleClass? = SimpleClass(name: "First")
var body: some View {
VStack {
Text("Hello, world!")
}
.task {
try? await Task.sleep(for: .seconds(2))
// 2 - init second SimpleClass instance and set as new @State
// "First" should deinit
simpleClass = SimpleClass(name: "Second")
// 3 - "Second" deinit just fine
simpleClass = nil
}
}
}
class SimpleClass {
let name: String
init(name: String) {
print("init: \(name)")
self.name = name
}
deinit {
print("deinit: \(name)")
}
}
output:
init: First
init: Second
deinit: Second
Thanks
I want to present a textfield inside a sheet.
However when the keyboard is shown, the sheet view produces extra padding even though I explicitly set the frame of the textfield and the presentationDent to be the exact same height.
Reproducible example:
struct ContentView: View {
@State var showSheet: Bool = false
@State var text = ""
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
Button {
showSheet.toggle()
} label: {
Text("Show Sheet")
}
}
.sheet(isPresented: $showSheet) {
TextField("Hello", text: $text)
.frame(height: 44)
.background(.red)
.presentationDetents([.height(44)])
.presentationDragIndicator(.hidden)
}
}
}
Does anyone know how to resolve this issue?
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?
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 ?
With iOS 18.3.1 in Playground there is a different view in TabView: in Preview the systemImage are visible and the TabView is visible under, instead launching the app the systemImage it is no longer visible. How can I solve it? Thank you
I'm looking to develop a very rich networking macOS app (like social media apps) operated by very large number of users, each user is able to create a number of windows, operate/view each of them, able to customize the app to his liking etc. The UI is expected to be very rich and dynamic.
The question is, should I choose AppKit or SwiftUI?
I have a basic understanding of SwiftUI, its declarative way of defining UI layouts and populating it with data. Not sure if SwiftUI can handle a very rich and dynamic UI customised by large number of users.
Any thoughts? What works best in this scenario? What is Apple's recommendation?
Hey everyone! Totally a newbe question here but cant find the answer anywhere when searching so figured I would just post. Trying to create my first SwiftUI app in Xcode and wanted to create a simple launch screen with an image file, and a text label. however when I select the launch screen in the Project settings it lets me pick it, but then when i navigate away it never saves the value.
Then when I go somewhere else and come back its blank again... Any thoughts?
XCode 16.2
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 ?
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.
I have a SwiftUI project which has the following hierarchy:
IOSSceneDelegate (App target) - depends on EntryPoint and Presentation static libs.
Presentation (Static library) - Depends on EntryPoint static lib. Contains UI related logic and updates the UI after querying the data layer.
EntryPoint (Static library) - Contains the entry point, AppDelegate (for its lifecycle aspects) etc.
I've only listed the relevant targets here.
SceneDelegate was initially present in EntryPoint library, because the AppDelegate references it when a scene is created.
public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Set the SceneDelegate dynamically
let sceneConfig: UISceneConfiguration = UISceneConfiguration(name: "mainWindow", sessionRole: connectingSceneSession.role)
sceneConfig.delegateClass = SceneDelegate.self
return sceneConfig
}
The intent is to move the SceneDelegate to the Presentation library.
When moved, the EntryPoint library fails to compile because it's referencing the SceneDelegate (as shown above).
To remove this reference, I tried to set up the SceneDelegate in the old way - In the info.plist file, mention a SceneConfiguration and set the SceneDelegate in Presentation.
// In the Info.plist file
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>Presentation.SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
// In the AppDelegate
public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Refer to a static UISceneconfiguration listed in the info.plist file
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
As shown above, the Presentation.SceneDelegate is referred in the Info.plist file and the reference is removed from the AppDelegate (in EntryPoint library).
The app target compiles, but when I run it, the SceneDelegate is not invoked. None of the methods from the SceneDelegate (scene(_:willConnectTo:options:), sceneDidDisconnect(_:), sceneDidEnterBackground(_:) etc.) are invoked. I only get the AppDelegate logs.
It seems like the Configuration is ignored because it was incorrect. Any thoughts? Is it possible to move the SceneDelegate in this situation?
Our app presents an NSOpenPanel with an accessory view implemented in SwiftUI and presented via NSHostingView. TextFields and pickers are working OK, but Buttons and Toggles (checkboxes) aren’t, although Toggles styled with .switch are functioning as expected. Specifically:
Toggles styled with .checkbox fail with no feedback. Overriding NSHostingView mouseDown() shows that the mouse event is completely ignored by the Toggle
Buttons “see” the mouseDown event (the button highlights when pressed, and the event doesn’t fall through to the hosting view), but the button action isn’t triggered until the dialog is dismissed
Any idea on how to get these controls functional?
NavigationTitle does not change when the app language changes. It works well in iOS 17.5 but does not in iOS 18.x
Hey, I am building some widgets and I'm quite surprised that Swipe gestures for widgets is not supported. It means the user must sacrifice home screen real estate to view multiple widgets to receive the same information. Ideally, swiping left / right inside of the widget should give a developer access to present different views.
I realize that it means that a user would need to swipe outside of the widget, (or swipe to the beginning/end of the series of views inside of the widget) for the page to swipe, but I'd argue that this is the intuitive behavior of what widget scrollview would or should look like anyway.
I have the following code for generating a one page PDF:
@MainActor func render() -> URL {
let renderer = ImageRenderer(content: pdfView))
let url = URL.documentsDirectory.appending(path: "output.pdf")
renderer.render { size, context in
var document = CGRect(x: 0, y: 0, width: 2550, height: 3300)
guard let pdf = CGContext(url as CFURL, mediaBox: &document, nil) else {
return
}
pdf.beginPDFPage(nil)
context(pdf)
pdf.endPDFPage()
pdf.closePDF()
}
return url
}
I'm trying to write code to create a multi-page PDF if there is multiple ImageRenderers. I tried something shown below but I'm not sure how to properly implement.
@MainActor func render() -> URL {
let renderer = ImageRenderer(content: pdfView)
let url = URL.documentsDirectory.appending(path: "output.pdf")
for image in renderer {
image.render { size, context in
var page = generatePage(image: image)
}
}
return url
}
func generatePage(image: ImageRenderer<<#Content: View#>>) -> CGContext {
var view = CGRect(x: 0, y: 0, width: 2550, height: 3300)
guard let pdf = CGContext(url as CFURL, mediaBox: &view, nil) else {
return
}
pdf.beginPDFPage(nil)
context(pdf)
pdf.endPDFPage()
pdf.closePDF()
return pdf
}
Any guidance would be greatly appreciated. Thank you.
When using a VStack containing two TextFields inside a ScrollView on an iPad running iOS 18.0, the FocusState of the topmost TextField does not trigger, while the second TextField's FocusState works correctly. Adding an invisible TextField on top resolves the issue, but it appears to be a bug specifically in iOS 18.0 on iPads. This issue does not occur on iOS versions below or above 18.0 (including iOS 18.1).
Code that is not working
struct ContentView: View {
@State var text: String = ""
@FocusState
private var focusState: Bool
var body: some View {
ScrollView(.vertical, content: {
VStack(spacing: 0) {
TextField(text: $text) {
Text("Hello, World!")
}
.border(focusState ? Color.red : Color.gray)
.focused($focusState)
.onChange(of: focusState) { oldValue, newValue in
print(newValue)
}
.onChange(of: text) { oldValue, newValue in
focusState = true
}
}
})
.padding()
}
}
Code that is working
struct ContentView: View {
@State var text: String = ""
@FocusState
private var focusState: Bool
var body: some View {
ScrollView(.vertical, content: {
VStack(spacing: 0) {
// Invisible Text Field
TextField("", text: .constant(""))
.frame(height: 0)
TextField(text: $text) {
Text("Hello, World!")
}
.border(focusState ? Color.red : Color.gray)
.focused($focusState)
.onChange(of: focusState) { oldValue, newValue in
print(newValue)
}
.onChange(of: text) { oldValue, newValue in
focusState = true
}
}
})
.padding()
}
}
Hello,
I'm creating an app that stores multiple Date objects: the users selects a date and a time and receives a notification at this time precisely.
The problem that happens is after saving a Date, if the device's timezone changes, the Date also changes - and that is not what's I'm expecting (just want the original time as is without depending on timezone).
I have inspected the TimeZone properties when I'm building the Date from DateComponents but nothing has worked.
Thank you for your answer.
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?
Given Apple's new .limited contact authorization introduced in ios18, I want to be able to present the ContactAccessPicker directly from my app, via ionic capacitor. I present the .contactAccessPicker view via a UIHostingController, and I manage the view controller's dismissal accordingly when the ContactAccessPicker completes and is no longer presented.
Bug: After a few searches or interactions with the Contact Access Picker (ex. searching, selecting contacts, clicking the "show selected" button), the contact access picker crashes and the overlay remains. Any interaction with my app is then blocked because I can't detect that the contact access picker has disappeared when it crashes so I can't dismiss the viewController.
Is there a way for me to prevent the contact access picker from crashing, and how can I detect if it does crash, so I can at least dismiss the view controller if that happens?
struct ContactAccessPickerView: View {
@Binding var isPresented: Bool
let completion: @MainActor ([String]) -> Void
var body: some View {
Group {
if #available(iOS 18.0, *) {
Color.clear
.contactAccessPicker(isPresented: $isPresented) { result in
Task { @MainActor in
completion(result)
}
}
} else {
}
}
}
}
@objc func selectMoreContacts(_ call: CAPPluginCall) {
guard isContactsPermissionGranted() else {
call.resolve(["success": false])
return
}
// Save the call to ensure it's available until we finish
self.bridge?.saveCall(call)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
var isPresented = true
let picker = ContactAccessPickerView(isPresented: .init(get: { isPresented }, set: { isPresented = $0 })) { contacts in
call.resolve(["success": true])
self.dismissAndCleanup(call)
}
let hostingController = UIHostingController(rootView: picker)
hostingController.modalPresentationStyle = .overFullScreen
self.bridge?.viewController?.present(hostingController, animated: true)
}
}
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?