In my visionOS app, I have an initial WindowGroup (no parameters), which opens correctly on application launch. I have multiple other WindowGroup(for:) closures in the app, too.
If I open one of the other WindowGroup(for:) windows, then close the initial window, I can't get the initial window back. If I close the second window, then tap on app icon, the second window reappears, but the initial window isn't shown.
The only way to get the initial window back, once it's closed, is to force-quit the app and restart.
A one-file reproducible example is below. In this example, the "button tapped" window is the second window. What do I need to do to get the initial window back?
Note this problem is in a visionOS app. But I've been able to reproduce even if I remove the RealityKitContent package from the target.
If I close, say, Safari's only window, then Safari exits, and shows me its window when I relaunch. The behavior I'd like to see is that when I "click" the app icon, the app presents its main window again.
I have also tried giving the WindowGroup an id. That does allow me to openWindow from another window (could use a toolbar item for that), but it doesn't get the main window to appear on launch, and I end up with multiple copies of the Main window.
import SwiftUI
@main
struct Limbo_MREApp: App {
var body: some Scene {
// I've also tried this form, same result
// WindowGroup(id: "main") {
WindowGroup {
ContentView()
}
WindowGroup(for: String.self) { $string in
if let string {
Text(string)
.font(.extraLargeTitle2)
}
}
}
}
struct ContentView: View {
@Environment(\.openWindow) var openWindow
var body: some View {
VStack {
Text("Hello, world!")
Button("Tap Me", systemImage: "doc.on.doc") {
openWindow(value: "button tapped")
}
}
}
}
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.
Post
Replies
Boosts
Views
Activity
In a UITabBarController, its controllers are set to be UINavigationControllers.
When programmatically setting the selectedViewController to a desired controller which is not currently displayed, the selected icon is correct however the actual view controller is still the previously selected.
Pseudo code:
tabController.controllers = [viewcontroller1, viewcontroller2, viewcontroller3].map{ UINavigationController(rootViewController: $0) }
....
// let's say at some point tab bar is set to e.g. showing index 1
tabController.selectedController = tabController.controllers[0]
// after this the icon of the 1st tab is correctly displayed, but the controller is still the one at index 1
I have noticed that if the controllers are simple UIViewController (not UINavigationController) upon setting the selectedViewController the TabController sets both icon and content correctly.
But this is not the wanted setup and different UINavigationControllers are needed.
Is this a new bug in iOS18?
Any idea how to fix this (mis)behaviour?
I want to share UserDefaults between main App and macOS Widget, in iOS I can do it using AppGroups, but how to do it between macOS Widget and main App, because macOS widget's AppGroup require to use "Team Identifier" as prefix and main App's AppGroup require prefix to be "group" so how can I share UserDefaults between the two?
I have an app with a TabView containing a view representable containing a SwiftUI View with a toolbar. The representable is providing the toolbar while the .toolbar modifier provides the content.
Everything works normally on iOS 17, but on iOS 18 the toolbar contents are not showing.
Is this a iOS 18 bug?
See the code below for a simplified example.
import SwiftUI
@main
struct TestApp: App {
@State var selection: String = "one"
var body: some Scene {
WindowGroup {
TabView(selection: $selection) {
Representable()
.tabItem {
Text("One")
}
.tag("one")
}
}
}
}
struct Representable: UIViewControllerRepresentable {
let navigationController = UINavigationController()
func makeUIViewController(context: Context) -> UINavigationController {
navigationController.pushViewController(UIHostingController(rootView: ToolbarView()), animated: false)
return navigationController
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
}
struct ToolbarView: View {
var body: some View {
NavigationLink("Navigate") {
ToolbarView()
}
.toolbar {
ToolbarItem(placement: .principal) {
Text("Top")
}
}
}
}
Hello, since the last version of iOS and WatchOS I have a problem with this code.
This is the minimal version of the code, it have two pickers inside a view of a WatchOS App.
The problem its with the focus, I can't change the focus from the first picker to the second one.
As I said before, it was working perfectly in WatchOS 10.0 but in 11 the problems started.
struct ParentView: View {
@FocusState private var focusedField: String?
var body: some View {
VStack {
ChildView1(focusedField: $focusedField)
ChildView2(focusedField: $focusedField)
}
}
}
struct ChildView1: View {
@FocusState.Binding var focusedField: String?
@State private var selectedValue: Int = 0
var body: some View {
Picker("First Picker", selection: $selectedValue) {
ForEach(0..<5) { index in
Text("Option \(index)").tag("child\(index)")
}
}.pickerStyle(WheelPickerStyle()).focused($focusedField, equals: "first")
}
}
struct ChildView2: View {
@FocusState.Binding var focusedField: String?
@State private var selectedValue: Int = 0
var body: some View {
Picker("Second Picker", selection: $selectedValue) {
ForEach(0..<5) { index in
Text("Option \(index)").tag("childTwo\(index)")
}
}.pickerStyle(WheelPickerStyle()).focused($focusedField, equals: "second")
}
}
When you do vertical scrolling on the second picker, the focus should be on it, but it dosnt anything.
I try even do manually, setting the focusState to the second one, but it sets itself to nil.
I hope that you can help me, thanks!
I am using a Mac Catalyst with SwiftUI for our document-based app with DocumentGroup. The issue is that when we create a new document or open an existing one, the opened view is completely blank. It is only blank/empty when the "Optimzie for Mac" is checked. If it is "Scaled t oMatch iPad", then it works well.
Xcode 16.1
macOS 15.1
struct DocumentGroupTestApp: App {
var body: some Scene {
DocumentGroup(newDocument: WritingAppDocument()) { file in
TestView() // it is empty when it gets opened. It does not work if the option "Optimize for Mac" is checked. If it is scale iPad, then it works.
}
}
}
struct TestView: View {
var body: some View {
Text("Hello, World!")
}
}
This is a post down memory lane for you AppKit developers and Apple engineers...
TL;DR:
When did the default implementation of NSViewController.loadView start making an NSView when there's no matching nib file? (I'm sure that used to return nil at some point way back when...)
If you override NSViewController.loadView and call [super loadView] to have that default NSView created, is it safe to then call self.view within loadView?
I'm refactoring some old Objective-C code that makes extensive use of NSViewController without any use of nibs. It overrides loadView, instantiates all properties that are views, then assigns a view to the view controller's view property. This seems inline with the documentation and related commentary in the header. I also (vaguely) recall this being a necessary pattern when not using nibs:
@interface MyViewController: NSViewController
// No nibs
// No nibName
@end
@implementation MyViewController
- (void)loadView {
NSView *hostView = [[NSView alloc] initWithFrame:NSZeroRect];
self.button = [NSButton alloc...];
self.slider = [NSSlider alloc...];
[hostView addSubview:self.button];
[hostView addSubview:self.slider];
self.view = hostView;
}
@end
While refactoring, I was surprised to find that if you don't override loadView and do all of the setup in viewDidLoad instead, then self.view on a view controller is non-nil, even though there was no nib file that could have provided the view. Clearly NSViewController has realized that:
There's no nib file that matches nibName.
loadView is not overridden.
Created an empty NSView and assigned it to self.view anyways.
Has this always been the behaviour or did it change at some point? I could have sworn that if there as no matching nib file and you didn't override loadView, then self.view would be nil.
I realize some of this behaviour changed in 10.10, as noted in the header, but there's no mention of a default NSView being created.
Because there are some warnings in the header and documentation around being careful when overriding methods related to view loading, I'm curious if the following pattern is considered "safe" in macOS 15:
- (void)loadView {
// Have NSViewController create a default view.
[super loadView];
self.button = [NSButton...];
self.slider = [NSSlider...];
// Is it safe to call self.view within this method?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
Finally, if I can rely on NSViewController always creating an NSView for me, even when a nib is not present, then is there any recommendation on whether one should continue using loadView or instead move code the above into viewDidLoad?
- (void)viewDidLoad {
self.button = [NSButton...];
self.slider = [NSSlider...];
// Since self.view always seems to be non-nil, then what
// does loadView offer over just using viewDidLoad?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
This application will have macOS 15 as a minimum requirement.
In iOS18 the user can change their Home Screen customization to choose either light, dark, or tinted. If they choose tinted the widgets are rendered using the "accented" rendering mode and without a background.
Is there some way to override so that the tinted mode is ignore completely and the widgets render as full color?
I know about WidgetAccentedRenderingMode (https://developer.apple.com/documentation/widgetkit/widgetaccentedrenderingmode) but that's only for images, not the whole control and doesn't help with the background also being removed in the tinted mode.
I have this code to make ARVR Stereo View To Be Used in VR Box Or Google Cardboard, it uses iOS 18 New RealityView but it is not Act as an AR but rather Static VR on a Camera background so as I move the iPhone the cube move with it and that's not suppose to happen if its Anchored in a plane or to world coordinate.
import SwiftUI
import RealityKit
struct ContentView : View {
let anchor1 = AnchorEntity(.camera)
let anchor2 = AnchorEntity(.camera)
var body: some View {
HStack (spacing: 0){
MainView(anchor: anchor1)
MainView(anchor: anchor2)
}
.background(.black)
}
}
struct MainView : View {
@State var anchor = AnchorEntity()
var body: some View {
RealityView { content in
content.camera = .spatialTracking
let item = ModelEntity(mesh: .generateBox(size: 0.25), materials: [SimpleMaterial()])
anchor.addChild(item)
content.add(anchor)
anchor.position.z = -1.0
anchor.orientation = .init(angle: .pi/4, axis:[0,1,1])
}
}
}
the thing is if I remove .camera like this
let anchor1 = AnchorEntity()
let anchor2 = AnchorEntity()
It would work as AR Anchored to world coordinates but on the other hand is does not work but on the left view only not both views
Meanwhile this was so easy before RealityView and SwiftUI by cloning the view like in ARSCNView Example :
import UIKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {
//create Any Two ARSCNView's in Story board
// and link each to the next (dont mind dimensions)
@IBOutlet var sceneView: ARSCNView!
@IBOutlet var sceneView2: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
sceneView.delegate = self
sceneView.session.delegate = self
// Create SceneKit box
let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.01)
let item = SCNNode(geometry: box)
item.geometry?.materials.first?.diffuse.contents = UIColor.green
item.position = SCNVector3(0.0, 0.0, -1.0)
item.orientation = SCNVector4(0, 1, 1, .pi/4.0)
// retrieve the ship node
sceneView.scene.rootNode.addChildNode(item)
}
override func viewDidLayoutSubviews() // To Do Add the 4 Buttons
{
// Stop Screen Dimming or Closing While The App Is Running
UIApplication.shared.isIdleTimerDisabled = true
let screen: CGRect = UIScreen.main.bounds
let topPadding: CGFloat = self.view.safeAreaInsets.top
let bottomPadding: CGFloat = self.view.safeAreaInsets.bottom
let leftPadding: CGFloat = self.view.safeAreaInsets.left
let rightPadding: CGFloat = self.view.safeAreaInsets.right
let safeArea: CGRect = CGRect(x: leftPadding, y: topPadding, width: screen.size.width - leftPadding - rightPadding, height: screen.size.height - topPadding - bottomPadding)
DispatchQueue.main.async
{
if self.sceneView != nil
{
self.sceneView.frame = CGRect(x: safeArea.size.width * 0 + safeArea.origin.x, y: safeArea.size.height * 0 + safeArea.origin.y, width: safeArea.size.width * 0.5, height: safeArea.size.height * 1)
}
if self.sceneView2 != nil
{
self.sceneView2.frame = CGRect(x: safeArea.size.width * 0.5 + safeArea.origin.x, y: safeArea.size.height * 0 + safeArea.origin.y, width: safeArea.size.width * 0.5, height: safeArea.size.height * 1)
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
sceneView2.scene = sceneView.scene
sceneView2.session = sceneView.session
}
}
And here is the video for it
I have a Map within a SwiftUI app that has the selection parameter set to an optional MapSelection.
I need to be able to select MapFeatures which works as expected as well as MKMapItems which are added to the map. The MKMapItems are not selectable.
Is it possible to make it such that the Map allows the user to select MKMapItems as well as MapFeatures?
Is it possible to get a MapFeature from an MKMapItem?
I try to generate PDF from view. View is nice, there is a lot of transparency and many gradients (circular and linear). But if I use ImageRenderer in in a way that documentation suggest all transparency and gradients disappear. Is this bug or some feature? Is it way to generate vector graphic from view with transparency and gradients? PDF allows those features, so why not?
code:
let action1 = UIAction(title: "Restore".localized, image: UIImage(resource: .listRestore)) { [weak self] action in
self?.trashRestoreTapped(id: button.tag)
}
let action2 = UIAction(title: "Delete".localized, image: UIImage(resource: .listDelete), attributes: [.destructive]) { [weak self] action in
self?.trashDeleteTapped(id: button.tag)
}
button.menu = UIMenu(options: .displayInline, preferredElementSize: .large, children: [action1, action2])
button.showsMenuAsPrimaryAction = true
MacOS 15.1:
iPad:
Hello,
I'm seeing a strange error on another user's device where the SwiftUI file importer doesn't do anything at all. When selecting multiple files and hitting "open", the importer just freezes. Here's a video showing the problem: https://streamable.com/u5grgy
I'm unable to replicate on my own device, so I'm not sure what could be going on. I have startAccessingSecurityScopedResource and stopAccessingSecurityResource everywhere I access a file from fileImporter as well.
I have a Split View with the sidebar, content, and detail. Everything is working, but when I select on a NavigationLink in my detail view, the back button is seen next to the title above the content view. I want that back button to be displayed in the top bar on the left side of the detail view. I was expecting it to do this automatically, but I must be missing something.
This is where I want it to appear.
This is where it appears.
I made a simplified version of my code, because it would be too much to post but this has the same behavior.
struct TestView: View {
enum SidebarSelections {
case cycles
}
@State private var sidebarSelection: SidebarSelections = .cycles
var body: some View {
NavigationSplitView(sidebar: {
List(selection: $sidebarSelection, content: {
Label("Cycles", systemImage: "calendar")
.tag(SidebarSelections.cycles)
})
}, content: {
switch sidebarSelection {
case .cycles:
NavigationStack {
List {
// Displayed in Content
NavigationLink("Cycle link", destination: {
// Displayed in the Detail
NavigationStack {
List {
NavigationLink("Detail Link", destination: {
Text("More details")
})
}
}
})
}
}
}
}, detail: {
ContentUnavailableView("Nothing to see here", systemImage: "cloud")
})
}
}
Is what I want to do possible? Here is a Stack Overflow post that had it working at one point.
State of Mind is an amazing feature, and I want to provide a similar experience to the Journal app, making it easy to record emotions.
Can you consider public State of Mind record UI api.
I have an issue using RealityView to show two screens of AR, while I did succeed to make it as a non AR but now my code not working.
Also it is working using Storyboard and Swift with SceneKit, so why it is not working in RealityView?
import SwiftUI
import RealityKit
struct ContentView : View {
var body: some View {
HStack (spacing: 0){
MainView()
MainView()
}
.background(.black)
}
}
struct MainView : View {
@State var anchor = AnchorEntity()
var body: some View {
RealityView { content in
let item = ModelEntity(mesh: .generateBox(size: 0.2), materials: [SimpleMaterial()])
content.camera = .spatialTracking
anchor.addChild(item)
anchor.position = [0.0, 0.0, -1.0]
anchor.orientation = .init(angle: .pi/4, axis:[0,1,1])
// Add the horizontal plane anchor to the scene
content.add(anchor)
}
}
}
I am creating a UIKit application but that contains SwiftUI Views embedded using the hostingcontroller.
I have a particular approach for it..but it requires instantiating a swiftUI view, creating a hostingcontroller object from it and storing a reference to it. So that later If I wanted to update the view, I can simply get the reference back and update the swiftUI view using it.
I wanted to understand what does apple recommends on this. Can we store a swiftUI instance? Does it cause any issue or it is okay to do so?
I'm using Core Data to save data. Then I wanna add spotlight support.
self.spotlightDelegate = StorageSpotlightDelegate(forStoreWith: description, coordinator: container.persistentStoreCoordinator)
let isSpotlightDisable = UserDefaults.standard.bool(forKey: "isSpotlightDisable")
if !isSpotlightDisable {
self.toggleSpotlightIndexing(enable: true)
}
public func toggleSpotlightIndexing(enable: Bool) {
guard let spotlightDelegate = spotlightDelegate else { return }
if enable {
spotlightDelegate.startSpotlightIndexing()
} else {
spotlightDelegate.stopSpotlightIndexing()
spotlightDelegate.deleteSpotlightIndex { error in
if let error = error {
print(error)
}
}
}
UserDefaults.standard.set(!enable, forKey: "isSpotlightDisable")
}
It works fine on an iOS15 device, but not work on iOS 17&18.
On iOS 18 devices, I can search the data when the first time to added to Core Data. But if I stop spotlight indexing and restart again, the data is never be searched.
How can I to solve this? And I noticed that the problem is also exists in another dictionary app.
I was hoping for an update of SwiftData which adopted the use of shared and public CloudKit containers, in the same way it does for the private CloudKit container.
So firstly, a big request to any Apple devs reading, for this to be a thing!
Secondly, what would be a sensible way of adding a shared container in CloudKit to an existing app that is already using SwiftData?
Would it be possible to use the new DataStore method to manage CloudKit syncing with a public or shared container?