I have a RealityView displaying a Reality Composer Pro scene in window. Things are generally working fine, but the content seems to be appearing in front of and blocking the VisionOS window, rather than being contained inside it. Do I need to switch to a volumetric view for this to work? My scene simply contains a flat display which renders 3D content (it has a material that sends different imagery to each eye).
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
97 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Development environment: Xcode 16.1, macOS 15.1 (24B83)
OS version: iOS iOS 17.5 and above
When NavigationStack is presented by a sheet, and navigationDestination API is being used for navigation within the stack, the sheet content is forced to be reevaluated when app is in background.
Sample Project
import SwiftUI
struct TestView: View {
var id: Int
@State private var isLoading = false
@State private var presentSheet = false
var body: some View {
let _ = Self._printChanges()
VStack {
if isLoading {
ProgressView()
} else {
VStack {
Text("View: \(id)")
Text("Not loading")
Button("Present Sheet in NavStack") {
presentSheet = true
}
NavigationLink("Show Link", value: id * 100)
}
}
}
.sheet(
isPresented: $presentSheet,
content: {
NavigationStack {
TestView(id: self.id + 1)
// Comment this block out and note the view no longer reloads when app is in background when there's > 1 sheet modals
.navigationDestination(for: Int.self, destination: { num in
TestView(id: num)
})
}
}
)
.task {
isLoading = true
defer {
isLoading = false
}
try? await Task.sleep(for: .seconds(1))
}
}
}
struct ContentView: View {
var body: some View {
let _ = Self._printChanges()
VStack {
content
.padding()
}
}
var content: some View {
VStack {
NavigationStack {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
TestView(id: 0)
}
.navigationDestination(for: Int.self, destination: { num in
TestView(id: num)
})
}
}
}
}
Steps to reproduce:
To reproduce the issue in the sample project:
Tap on present sheet in navstack button to invoke View #1 presented in sheet
Put the app into multitasking mode by tapping on the simulator home button twice
Observe that console does not emit debug messages on SwiftUI View change. Also observe that there was no loading in the view
Tap on present sheet in navstack button again to invoke View #2 presented in sheet
Repeat step #2, but this time observe that console does emit debug message that SwiftUI View were changed due to the following:
TestView: @self, @identity, _isLoading, _presentSheet changed.
TestView: _isLoading changed.
TestView: _isLoading changed.
To remove the issue:
7. Comment out the block on navigationDestination. Recompile the app and run it in simulator
8. Repeat step 2-5. Note this time the console does not emit debug message that SwiftUI View were changed.
We are having issues with implementing a List that has Views in it that contain a Textfield.
The criteria we are trying to achieve is
Select to edit the quantity of a product
Auto focus on the row with that textfield, with the textfield's contents selected
Display/Dismiss the keyboard
Mask other rows in the list while interacting with a qty field
We explored many routes and are looking for direction on what the designated approach is. This originally was a Tech Support Incident, and I was instructed to post here. There were 2 working project examples available if needed.
In an implementation that has the FocusState on the parent view, we see collisions in animation / weird jumpiness
// MARK: - Constant
enum Constant {
static let logTag = "AddReplenishmentProductView"
}
@Binding var state: ContentViewState
// MARK: - Private Properties
@State private var focusedLineItemId: String?
// MARK: - Life cycle
var body: some View {
VStack {
replenishmentProductList
}
.background(.tertiary)
.navigationTitle("Add Products")
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
}
// MARK: - Private Computed properties
@ViewBuilder
private var replenishmentProductList: some View {
ScrollViewReader { proxy in
List {
let list = Array(state.lineItems.enumerated())
ForEach(list, id: \.1.product.id) { (index, lineItem) in
RowView(
lineItem: $state.lineItems[index],
focusedLineItemId: $focusedLineItemId
)
.id(lineItem.id.uuidString)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.alignmentGuide(.listRowSeparatorLeading) { _ in
return 0
}
// Blocks all the other rows that we are not focusing on.
.maskingOverlay(focusId: $focusedLineItemId, elementId: "\(lineItem.id)")
}
.listSectionSeparator(.hidden)
}
.listStyle(.plain)
.scrollDismissesKeyboard(.never)
.scrollContentBackground(.hidden)
/*
We are looking for a solution that doesn't require us to have this onChange modifier
whenever we want to change a focus.
*/
.onChange(of: focusedLineItemId) {
guard let lineItemId = focusedLineItemId else { return }
/*
We need to scroll to a whole RowView so we can see both done and cancel buttons.
Without this, the focus will auto-scroll only to the text field, due to updating FocusState.
We are experiencing weird jumping issues. It feels like the animations for focus on
text field and RowView are clashing between each other.
To fix this, we added a delay to the scroll so the focus animation completes first and then we
scroll to the RowView.
However, when we attempt to focus on a row that is partially shown, sometimes the RowView won't
update it's focus and won't focus ultimately on the TextField until we scroll.
*/
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
withAnimation {
// We need to add the withAnimation call to animate the scroll to the whole row.
proxy.scrollTo(lineItemId, anchor: .top)
}
}
}
}
}
}
In an implementation where the FocusState is on the row views, we see issues with actually being able to focus. When quantity field we tap is located on a row near the top/bottom of the screen it does not look to be identified correctly, and the ability to scrollTo / the keyboard being presented are broken.
struct ContentView: View {
// MARK: - Constant
enum Constant {
static let logTag = "AddReplenishmentProductView"
}
@Binding var state: ContentViewState
// MARK: - Private Properties
@State private var focusedLineItemId: String?
@FocusState private var focus: String?
// MARK: - Life cycle
var body: some View {
VStack {
replenishmentProductList
}
.background(.tertiary)
.navigationTitle("Add Products")
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
}
// MARK: - Private Computed properties
@ViewBuilder
private var replenishmentProductList: some View {
ScrollViewReader { proxy in
List {
let list = Array(state.lineItems.enumerated())
ForEach(list, id: \.1.product.id) { (index, lineItem) in
RowView(
lineItem: $state.lineItems[index],
focusedLineItemId: $focusedLineItemId,
focus: $focus
)
.id(lineItem.id.uuidString)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.alignmentGuide(.listRowSeparatorLeading) { _ in
return 0
}
// Blocks all the other rows that we are not focusing on.
.maskingOverlay(focusId: $focusedLineItemId, elementId: "\(lineItem.id)")
}
.listSectionSeparator(.hidden)
}
.listStyle(.plain)
.scrollDismissesKeyboard(.never)
.scrollContentBackground(.hidden)
/*
We are looking for a solution that doesn't require us to have this onChange modifier
whenever we want to change a focus.
*/
.onChange(of: focusedLineItemId) {
/*
We need to scroll to a whole RowView so we can see both done and cancel buttons.
Without this, the focus will auto-scroll only to the text field, due to updating FocusState.
However, we are experiencing weird jumping issues. It feels like the animations for focus on
text field and RowView are clashing between each other.
*/
focus = focusedLineItemId
guard let lineItemId = focusedLineItemId else { return }
withAnimation {
// We need to add the withAnimation call to animate the scroll to the whole row.
proxy.scrollTo(lineItemId, anchor: .top)
}
}
}
}
}
I recently compiled my macOS App with Swift 6 in Xcode 16 (was using Swift 5 previously) and noticed that AppKit Integration doesn't appear to be working as before. All my instances of NSHostingView which allow me to add a SwiftUI View to an AppKit NSWindow view controller no longer respond to mouse input anymore. All my NSHostingView instances display but refuse to accept any user interaction. Has anyone else noticed this and is there a workaround to get NSHostingView to once again be able to accept user/mouse events with Swift 6?
Hello, I recently have crashes on my application, it results in many crashes with different reasons, here are the different main reasons:
AttributeGraph: AG::Graph::update_main_refs(AG::AttributeID)
SwiftUICore: closure #1 in ViewLayoutEngine.explicitAlignment(_:at:)
SwiftUICore: __swift_instantiateGenericMetadata
My main problem is that these crashes appeared without any major changes to my app, and they never happen when I emulate the app from xcode whether on a simulator or a real device. I have other crashes with other errors I can provide them if necessary.
So I have a lot of trouble identifying where the errors come from, I tried to activate zombie objects, and address sanitizer without it revealing anything. Thanks in advance for the answers.
Hello Apple Community,
With a backend development background, I was always reluctant to do any front end. Especially with my bad experience with html & css, my negative opinion towards UI only got stronger.
When starting a new project at my current company, I was forced to do SwiftUI for iOS. After a few small (I mean really small) hiccups, I really understood the concept and it all became natural.
This positive experience made me want to try other front end frameworks which work for web. I dipped my toes into Jetpack Compose, C# UWP/WPF, Rust with EGUI.
I was really impressed with the performance and possibilities of Rust (EGUI) compiled to WASM. I was especially impressed that you do not have to use any HTML or CSS rather the rendering is completely up to you just like with a desktop application. I was always disappointed of the necessity of html, but with the rise of WASM in the recent years, I really hope there will be amazing alternatives using WASM & WEBGL.
Rust with EGUI is good and all but lets be honest to our self: With the ease of SwiftUI, its obvious why all the best looking applications are on iOS.
Its time for SwiftUI in web.
The advantages for the developers are obvious:
Arguably better UI Framework
No Html DOM stuff
Friendlier for new developers
One framework & language for multiple platforms
etc ...
But whats in for Apple? Why "waste" resources?
In my opinion the most important thing is: Increased Developer adoption
What is your opinion on this topic?
Would you use SwiftUI for web?
What are you currently using for web?
Do you prefer any other frontend framework over SwiftUI? (not considering the platform)
Hello, I have a small lightweight macOS application that includes a medium widget but the widget does not update with new data as often as I'd like. I understand that in apple's WidgetKit documentation they mention that apple controls when the widget updates due to battery life concerns, but I'd like to know if theres any way at all to control when the widget updates or when I think it makes sense to do so if I am not able to control how often it refreshes new data.
https://github.com/Alexx1105/MacStat-v2.1
I am encountering an issue with the UndoManager functionality in a SwiftUI application that integrates SwiftData for persistence. This issue occurs specifically in macOS 14 (Sonoma) but works as expected on macOS 15 (Sequoia).
The focused test app I have prepared for demonstration allows users to create ParentItem objects, and for each ParentItem, users can add multiple ChildItem objects. The undo functionality (via Cmd+Z) is not working as expected in Sonoma. When I try to undo a ChildItem addition, the UndoManager does not revert just the last ChildItem added, but instead removes all ChildItems that were added in that session.
Expected Behavior
On macOS 14 (Sonoma), I expect the UndoManager to undo only the most recent transaction (in this case, a single ChildItem insert), similar to how it functions on macOS 15 (Sequoia). Each ChildItem insertion should be treated as a separate undoable action.
Current Behavior
In macOS Sonoma, pressing Cmd+Z undoes the entire list of ChildItems added to a ParentItem in the current session, rather than just the most recent ChildItem. This appears to be an issue with undo grouping, but I’ve confirmed that no explicit grouping is being used.
Question
Is this an issue with UndoManager in macOS Sonoma, particularly in how it interacts with SwiftData persistence? What changes should I make to ensure that each ChildItem insert is treated as an individual undo action in macOS Sonoma, just as it works in Sequoia?
Any guidance on isolating the issue or recommended workarounds would be appreciated. I would expect that undo actions for each child addition would be treated as separate transactions, not grouped.
Steps Taken to Solve the Problem
I attempted to manually save the model context (modelContext.save()) after each ChildItem insert to ensure proper persistence.
I also verified that UndoManager was not grouping operations explicitly by calling beginUndoGrouping() or endUndoGrouping() myself.
This issue seems to be tied specifically to macOS Sonoma, as it does not occur on macOS Sequoia, where undoing behaves as expected.
Conditions
macOS 14 Sonoma: The issue occurs consistently.
macOS 15 Sequoia: The issue does not occur.
This issue appears to be independent of hardware, as I’ve tested it on multiple machines.
APIs/Features Potentially Involved
UndoManager in a SwiftUI application
SwiftData for persistence (using modelContext.save())
macOS version-specific behavior
Steps to reproduce
Clone test project (https://github.com/Maschina/SwiftDataUndoManagerExample), compile and run
Create a new ParentItem in the app (via plus toolbar button in the sidebar).
Add multiple ChildItems to the ParentItem (via plus toolbar button in the content / middle column of the navigation split view).
Press Cmd+Z to undo the last addition.
I’m seeing a crash in production for a small percentage of users, and have narrowed it down based on logging to happening as or very shortly after an alert is presented using SwiftUI.
This seems to be isolated to iOS 17.5.1, but since it’s a low-volume crash I can’t be sure there aren’t other affected versions. What can I understand from the crash report?
Here’s a simplified version of the code which presents the alert, which seems so simple I can’t understand why it would crash. And following that is the crash trace.
// View (simplified)
@MainActor public struct MyView: View {
@ObservedObject var model: MyViewModel
public init(model: MyViewModel) {
self.model = model
}
public var body: some View {
myViewContent
.overlay(clearAlert)
}
var clearAlert: some View {
EmptyView().alert(
"Are You Sure?",
isPresented: $model.isClearAlertVisible,
actions: {
Button("Keep", role: .cancel) { model.clearAlertKeepButtonWasPressed() }
Button("Delete", role: .destructive) { model.clearAlertDeleteButtonWasPressed() }
},
message: {
Text("This cannot be undone.")
}
)
}
}
// Model (simplified)
@MainActor public final class MyViewModel: ObservableObject {
@Published var isClearAlertVisible = false
func clearButtonWasPressed() {
isClearAlertVisible = true
}
func clearAlertKeepButtonWasPressed() {
// No-op.
}
func clearAlertDeleteButtonWasPressed() {
// Calls other code.
}
}
Incident Identifier: 36D05FF3-C64E-4327-8589-D8951C8BAFC4
Distributor ID: com.apple.AppStore
Hardware Model: iPhone13,2
Process: My App [379]
Path: /private/var/containers/Bundle/Application/B589E780-96B2-4A5F-8FCD-8B34F2024595/My App.app/My App
Identifier: com.me.MyApp
Version: 1.0 (1)
AppStoreTools: 15F31e
AppVariant: 1:iPhone13,2:15
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.me.MyApp [583]
Date/Time: 2024-06-21 20:09:20.9767 -0500
Launch Time: 2024-06-20 18:41:01.7542 -0500
OS Version: iPhone OS 17.5.1 (21F90)
Release Type: User
Baseband Version: 4.50.06
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001a69998c0
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [379]
Triggered by Thread: 0
Kernel Triage:
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001a69998c0 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1 AttributeGraph 0x00000001d0cd61a4 Attribute.init<A>(body:value:flags:update:) + 352 (Attribute.swift:473)
2 SwiftUI 0x00000001ac034054 closure #1 in Attribute.init<A>(_:) + 128 (<compiler-generated>:0)
3 SwiftUI 0x00000001ac033cac partial apply for closure #1 in Attribute.init<A>(_:) + 32 (<compiler-generated>:0)
4 libswiftCore.dylib 0x00000001a6ad0450 withUnsafePointer<A, B>(to:_:) + 28 (LifetimeManager.swift:128)
5 SwiftUI 0x00000001ad624d14 closure #2 in UIKitDialogBridge.startTrackingUpdates(actions:) + 268 (UIKitDialogBridge.swift:370)
6 SwiftUI 0x00000001ad624ae0 UIKitDialogBridge.startTrackingUpdates(actions:) + 248 (UIKitDialogBridge.swift:369)
7 SwiftUI 0x00000001ad6250cc closure #4 in UIKitDialogBridge.showNewAlert(_:id:) + 72 (UIKitDialogBridge.swift:471)
8 SwiftUI 0x00000001abfdd050 thunk for @escaping @callee_guaranteed () -> () + 36 (:-1)
9 UIKitCore 0x00000001aa5722e4 -[UIPresentationController transitionDidFinish:] + 1096 (UIPresentationController.m:651)
10 UIKitCore 0x00000001aa571d88 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.114 + 320 (UIPresentationController.m:1390)
11 UIKitCore 0x00000001aa5cb9ac -[_UIViewControllerTransitionContext completeTransition:] + 116 (UIViewControllerTransitioning.m:304)
12 UIKitCore 0x00000001aa34a91c __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__ + 36 (UIView.m:16396)
13 UIKitCore 0x00000001aa34a800 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 624 (UIView.m:16429)
14 UIKitCore 0x00000001aa349518 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 436 (UIView.m:0)
15 UIKitCore 0x00000001aa356b14 -[UIViewAnimationState animationDidStop:finished:] + 192 (UIView.m:2400)
16 UIKitCore 0x00000001aa356b84 -[UIViewAnimationState animationDidStop:finished:] + 304 (UIView.m:2422)
17 QuartzCore 0x00000001a96f8c50 run_animation_callbacks(void*) + 132 (CALayer.mm:7714)
18 libdispatch.dylib 0x00000001aff61dd4 _dispatch_client_callout + 20 (object.m:576)
19 libdispatch.dylib 0x00000001aff705a4 _dispatch_main_queue_drain + 988 (queue.c:7898)
20 libdispatch.dylib 0x00000001aff701b8 _dispatch_main_queue_callback_4CF + 44 (queue.c:8058)
21 CoreFoundation 0x00000001a808f710 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 (CFRunLoop.c:1780)
22 CoreFoundation 0x00000001a808c914 __CFRunLoopRun + 1996 (CFRunLoop.c:3149)
23 CoreFoundation 0x00000001a808bcd8 CFRunLoopRunSpecific + 608 (CFRunLoop.c:3420)
24 GraphicsServices 0x00000001ecf3c1a8 GSEventRunModal + 164 (GSEvent.c:2196)
25 UIKitCore 0x00000001aa6c490c -[UIApplication _run] + 888 (UIApplication.m:3713)
26 UIKitCore 0x00000001aa7789d0 UIApplicationMain + 340 (UIApplication.m:5303)
27 SwiftUI 0x00000001ac27c148 closure #1 in KitRendererCommon(_:) + 168 (UIKitApp.swift:51)
28 SwiftUI 0x00000001ac228714 runApp<A>(_:) + 152 (UIKitApp.swift:14)
29 SwiftUI 0x00000001ac2344d0 static App.main() + 132 (App.swift:114)
30 My App 0x00000001001e7bfc static MyApp.$main() + 52 (MyApp.swift:0)
31 My App 0x00000001001e7bfc main + 64
32 dyld 0x00000001cb73de4c start + 2240 (dyldMain.cpp:1298)
in this great talk https://developer.apple.com/videos/play/wwdc2023/10111/ the code references usdz models to replace hands. e.g assets/gloves/LeftGlove_v001.usdz. Are these models available to download to explain rigging and how to make hand models (ideally in Blender )
I am developing an app for Vehicle owners with a built-in map navigation feature with voice navigation support. The app works fine without voice navigation but when I use voice navigation it occasionally crashes and it crashes while voice navigation is not in progress.
What makes it impossible to diagnose is that even though it crashed 10 times on the flight, I don't see any crash reports in 'Apple Connect'. I tried running it in a simulator and it didn't crash there! but on a real device, when I drive with the app navigating me I crashes abruptly after a few minutes and it's not while the voice navigation is speaking! I also ran the app without AVFoundation and it did not crash then. So I am 100% sure it is something with this AVFoundation framework.
If anyone can help find the problem in my following code it would be really helpful.
import SwiftUI
import AVFoundation
struct DirectionHeaderView: View {
@Environment(\.colorScheme) var bgMode: ColorScheme
var directionSign: String?
var nextStepDistance: String
var instruction: String
@Binding var showDirectionsList: Bool
@Binding var height: CGFloat
@StateObject var locationDataManager: LocationDataManager
@State private var synthesizer = AVSpeechSynthesizer()
@State private var audioSession = AVAudioSession.sharedInstance()
@State private var lastInstruction: String = ""
@State private var utteranceDistance: String = ""
@State private var isStepExited = false
@State private var range = 20.0
var body: some View {
VStack {
HStack {
VStack {
if let directionSign = directionSign {
Image(systemName: directionSign)
}
if !instruction.contains("Re-calculating the route...") {
Text("\(nextStepDistance)")
.onChange(of: nextStepDistance) {
let distance = getDistanceInNumber(distance: nextStepDistance)
if distance <= range && !isStepExited {
startVoiceNavigation(with: instruction)
isStepExited = true
}
}
}
}
Spacer()
Text(instruction)
.onAppear {
isStepExited = false
utteranceDistance = nextStepDistance
range = nextStepRange(distance: utteranceDistance)
startVoiceNavigation(with: "In \(utteranceDistance), \(instruction)")
}
.onChange(of: instruction) {
isStepExited = false
utteranceDistance = nextStepDistance
range = nextStepRange(distance: utteranceDistance)
startVoiceNavigation(with: "In \(utteranceDistance), \(instruction)")
}
.padding(10)
Spacer()
}
}
.padding(.horizontal,10)
.background(bgMode == .dark ? Color.black.gradient : Color.white.gradient)
}
func startVoiceNavigation(with utterance: String) {
if instruction.isEmpty || utterance.isEmpty {
return
}
if instruction.contains("Re-calculating the route...") {
synthesizer.stopSpeaking(at: AVSpeechBoundary.immediate)
return
}
let thisUttarance = AVSpeechUtterance(string: utterance)
lastInstruction = instruction
if audioSession.category == .playback && audioSession.categoryOptions == .mixWithOthers {
DispatchQueue.main.async {
synthesizer.speak(thisUttarance)
}
}
else {
setupAudioSession()
DispatchQueue.main.async {
synthesizer.speak(thisUttarance)
}
}
}
func setupAudioSession() {
do {
try audioSession.setCategory(AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.mixWithOthers)
try audioSession.setActive(true)
}
catch {
print("error:\(error.localizedDescription)")
}
}
func nextStepRange(distance: String) -> Double {
var thisStepDistance = getDistanceInNumber(distance: distance)
if thisStepDistance != 0 {
switch thisStepDistance {
case 0...200:
if locationDataManager.speed >= 90 {
return thisStepDistance/1.5
}
else {
return thisStepDistance/2
}
case 201...300:
if locationDataManager.speed >= 90 {
return 120
}
else {
return 100
}
case 301...500:
if locationDataManager.speed >= 90 {
return 150
}
else {
return 125
}
case 501...1000:
if locationDataManager.speed >= 90 {
return 250
}
else {
return 200
}
case 1001...10000:
if locationDataManager.speed >= 90 {
return 250
}
else {
return 200
}
default:
if locationDataManager.speed >= 90 {
return 250
}
else {
return 200
}
}
}
return 200
}
func getDistanceInNumber(distance: String) -> Double {
var thisStepDistance = 0.0
if distance.contains("km") {
let stepDistanceSplits = distance.split(separator: " ")
let stepDistanceText = String(stepDistanceSplits[0])
if let dist = Double(stepDistanceText) {
thisStepDistance = dist * 1000
}
}
else {
var stepDistanceSplits = distance.split(separator: " ")
var stepDistanceText = String(stepDistanceSplits[0])
if let dist = Double(stepDistanceText) {
thisStepDistance = dist
}
}
return thisStepDistance
}
}
#Preview {
DirectionHeaderView(directionSign: "", nextStepDistance: "", instruction: "", showDirectionsList: .constant(false), height: .constant(0), locationDataManager: LocationDataManager())
}
I am new to Swift and iOS development. I am trying to wrap a web app where the orientation is dependent on the URL. I have the code working with Stack Overflow as an example where "https://stackoverflow.com" displays in portrait and all other pages change to landscape after being loaded. I have a URL observer that triggers when the URL changes and calls requestGeometryUpdate. I'm running into the following problem:
When changing the orientation with requestGeometryUpdate, the orientation changes, but if the device is physically rotated after the change, the orientation changes again. I would like to make the orientation change locked and permanent until a new page is loaded.
Any help would be much appreciated. My code is below:
import SwiftUI
import WebKit
struct TestView: View {
private let urlString: String = "https://stackoverflow.com/"
var body: some View {
TestWebView(url: URL(string: urlString)!)
.background(Color.black)
.scrollIndicators(.hidden)
.ignoresSafeArea([.all])//stretchs webview over notch on iphone
.defersSystemGestures(on:.bottom)//deprioritizes multitasking indicator
.statusBar(hidden: true)//hides time and battery
}
}
class TestController: UIViewController {
var webview: WKWebView!
var webViewURLObserver: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
let winScene = UIApplication.shared.connectedScenes.first
let windowScene = winScene as! UIWindowScene
webview = WKWebView(frame: self.view.frame)
webview.autoresizingMask = [.flexibleWidth,.flexibleHeight]//makes webview fit screen in portrait and landscape
self.view.addSubview(self.webview)
webViewURLObserver = self.webview.observe(\.url, options: .new) { webview, change in
let url=change.newValue!!;//! converts from optional to string
print(url)
let arr = url.absoluteString.split(separator: "stackoverflow.com").map(String.init)
var portrait=false
if(arr.count>1){
let path = arr[1];
if path=="/"{
portrait=true
}
}
if portrait==true {
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in print(error)}
}
else{
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in print(error)}
}
self.setNeedsUpdateOfSupportedInterfaceOrientations()
}
}
}
// WebView Struct
struct TestWebView: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context: Context) -> TestController {
let webviewController = TestController()
return webviewController
}
func updateUIViewController(_ webviewController: TestController, context: Context) {
let request = URLRequest(url: url)
webviewController.webview.scrollView.contentInsetAdjustmentBehavior = .never
webviewController.webview.load(request)
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
I'm developing a SwiftUI, CoreData / CloudKit App with Xcode 16.2 & Sequoia 15.2. The main CoreData entity has 20 NSManaged vars and 5 derived vars, the latter being computed from the managed vars and dependent computed vars - this somewhat akin to a spreadsheet. The data entry/updating Form is complex for each managed var because the user needs to be able to enter data in either Imperial or Metric units, and then switch (by Button) between units for viewing equivalents. This has to happen on an individual managed var basis, because some source data are in Imperial and others Metric.
Consequently, I use a generalised SubView on the Form for processing the managed var (passed as a parameter with its identity) and then updating the CoreData Entity (about 100 lines of code in total): i.e. there are 20 uses of the generalised SubView within the Main Form. However, none of the SubViews triggers an update of the managed var in the Form, nor computations of the derived vars. On initial load of the app, the CoreData entity is retrieved and the computations happen correctly: thereafter not.
No technique for refreshing either View works: e.g. trigger based on NSManagedObjectContextDidSave; nor does reloading the CoreData entity after Context Save (CoreData doesn't recognise changes at the attribute level anyway). If the SubView is removed and replaced with code within the Form View itself, then it works. However, this will require about 40 @State vars, 20 onCommits, etc - so it's not something I'm keen to do.
Below is a much-simplified example of the problem.
Form{
Section(header: Text("Test Record")){
Text(testRec.dateString ?? "n/a")
TextField("Notes",text:$text)
.onSubmit{
testRec.notes = text
dataStore.contextSave()
}
//DoubleNumberEntry(testRec: testRec) - doesn't work
TextField("Double",value:$numDbl,format: .number)
// This works
.onSubmit{
testRec.dblNum = numDbl
dataStore.contextSave()
}
TextField("Integer",value: $numInt,format: .number)
.onSubmit{
testRec.intNum = Int16(numInt)
dataStore.contextSave()
}
Text(String(format:"%.2f",testRec.computation))
Section(header: Text("Computations")) {
Text(String(format:"%.2f",testRec.computation))
Text(String(format:"%.2f",testRec.anotherComputation))
}
}
}
A much simplified version of my NSManaged var entry/updating.
struct DoubleNumberEntry: View {
let dataStore = MainController.shared.dataStore
var testRec : TestRec
@State private var numDbl: Double
init(testRec: TestRec) {
self.testRec = testRec
self.numDbl = testRec.dblNum
}
var body: some View {
TextField("Double",value:$numDbl,format: .number)
.onSubmit{
testRec.dblNum = numDbl
dataStore.contextSave()
}
}
}
I'd appreciate any offered solution or advice.
Regards, Michaela
I’m looking for the easiest and most efficient way to convert a SwiftUI Image to Data so that I can store it in SwiftData.
let image: Image
let data: Data = GetImageData(image: image)
How would I implement the GetImageData function above?
I have found examples of how to do so with UIImage but not Image.
We have an iPad app and are using the new TabView and TabSection views in our sidebar. The TabSection is populated with data from a @FetchRequest that fetches data from CoreData. The data in CoreData is updated by a single worker that makes sure every value only exists once. This is done by using an OperationQueue with maxConcurrentOperationCount set to 1.
This is crashing for our users, and we can't figure out why. We can't reproduce it, and it only seems to happen on iPadOS. We have the same code running on macOS and haven't received any reports. (We collect them all via 3rd party).
The error is:
NSInternalInconsistencyException
Fatal: supplied item identifiers are not unique. Duplicate identifiers: {(
...
)}
Where ... is one to many comma separated strings.
In our latest update we made sure the values are unique by passing them through a Set, unfortunately this is till crashing. Here's the fix we tried.
var uniqueTags: [HashTag] {
let set = Set(hashTags)
let array = Array(set)
return array.sorted {
$0.name?.lowercased() ?? "" < $1.name?.lowercased() ?? ""
}
}
We're out of ideas and have no idea what to do next.
Hi,
Im developing a data centric App using SwiftData, I noticed that the device I use for testing doesn't sync its data with the simulator although both have same Apple Account ? What's Im missing here ? arched is my project settings.
Kind Regards
I receive the following compiler error:
Cannot infer key path from context; consider explicitly specifying a root type
when I attempt an @Environment(\.foodRepository) lookup in a descendant View.
Here's the setup in my App class:
import SwiftUI
import SwiftData
@main
struct BulkCutApp: App {
private var foodRepository: FoodRepository = /* some code*/
var body: some Scene {
WindowGroup {
ContentView()
.foodRepository(foodRepository)
}
}
}
extension View {
func foodRepository(_ customValue: FoodRepository) -> some View {
environment(\.foodRepository, customValue)
}
}
extension EnvironmentValues {
var foodRepository: FoodRepository {
get { self[FoodRepositoryKey.self] }
set { self[FoodRepositoryKey.self] = newValue }
}
}
struct FoodRepositoryKey: EnvironmentKey {
static var defaultValue: FoodRepository = FoodRepository(food:[])
}
Nothing special in FoodRepository:
@Observable
class FoodRepository {
var food: [Food]
// more code
}
I want to create master details relationship between patient and vitals signs so which of option codes below are better performance wise ? Option one is master - details done manually ..
option 1
@Model
class TestResult {
@Attribute(.primaryKey) var id: UUID
var patientID: UUID
Option 2
@Model
final class Vital {
var patient: Patient?
Im building an recipe app for the social media of my mother. i already have the functionality for the users, when a user gets created an empty array gets initiated at the database named favoriteRecipes, which stores the id of his favorite recipes to show in a view.
This is my AuthViewModel which is relevant for the user stuff:
import Firebase
import FirebaseAuth
import FirebaseFirestore
protocol AuthenticationFormProtocol {
var formIsValid: Bool { get }
}
@MainActor
class AuthViewModel : ObservableObject {
@Published var userSession: FirebaseAuth.User?
@Published var currentUser: User?
@Published var currentUserId: String?
init() {
self.userSession = Auth.auth().currentUser
Task {
await fetchUser()
}
}
func signIn(withEmail email: String, password: String) async throws {
do {
let result = try await Auth.auth().signIn(withEmail: email, password: password)
self.userSession = result.user
await fetchUser() // fetch user sonst profileview blank
} catch {
print("DEBUG: Failed to log in with error \(error.localizedDescription)")
}
}
func createUser(withEmail email: String, password: String, fullName: String) async throws {
do {
let result = try await Auth.auth().createUser(withEmail: email, password: password)
self.userSession = result.user
let user = User(id: result.user.uid, fullName: fullName, email: email)
let encodedUser = try Firestore.Encoder().encode(user)
try await Firestore.firestore().collection("users").document(result.user.uid).setData(encodedUser)
await fetchUser()
} catch {
print("Debug: Failed to create user with error \(error.localizedDescription)")
}
}
func signOut() {
do {
try Auth.auth().signOut() // sign out user on backend
self.userSession = nil // wipe out user session and take back to login screen
self.currentUser = nil // wipe out current user data model
} catch {
print("DEBUG: Failed to sign out with error \(error.localizedDescription)")
}
}
func deleteAcocount() {
let user = Auth.auth().currentUser
user?.delete { error in
if let error = error {
print("DEBUG: Error deleting user: \(error.localizedDescription)")
} else {
self.userSession = nil
self.currentUser = nil
}
}
}
func fetchUser() async {
guard let uid = Auth.auth().currentUser?.uid else { return }
currentUserId = uid
let userRef = Firestore.firestore().collection("users").document(uid)
do {
let snapshot = try await userRef.getDocument()
if snapshot.exists {
self.currentUser = try? snapshot.data(as: User.self)
print("DEBUG: current user is \(String(describing: self.currentUser))")
} else {
// Benutzer existiert nicht mehr in Firebase, daher setzen wir die userSession auf nil
self.userSession = nil
self.currentUser = nil
}
} catch {
print("DEBUG: Fehler beim Laden des Benutzers: \(error.localizedDescription)")
}
}
}
This is the code to fetch the favorite recipes, i use the id of the user to access the collection and get the favoriteRecipes out of the array:
import SwiftUI
@MainActor
class FavoriteRecipeViewModel: ObservableObject {
@Published var favoriteRecipes: [Recipe] = []
@EnvironmentObject var viewModel: AuthViewModel
private var db = Firestore.firestore()
init() {
Task {
await fetchFavoriteRecipes()
}
}
func fetchFavoriteRecipes() async{
let userRef = db.collection("users").document(viewModel.userSession?.uid ?? "")
do {
let snapshot = try await userRef.collection("favoriteRecipes").getDocuments()
let favoriteIDs = snapshot.documents.map { $0.documentID }
let favoriteRecipes = try await fetchRecipes(recipeIDs: favoriteIDs)
} catch {
print("DEBUG: Failed to load favorite recipes for user: \(error.localizedDescription)")
}
}
func fetchRecipes(recipeIDs: [String]) async throws -> [Recipe] {
var recipes: [Recipe] = []
for id in recipeIDs {
let snapshot = try await db.collection("recipes").document(id).getDocument()
if let recipe = try? snapshot.data(as: Recipe.self) {
recipes.append(recipe)
}
}
return recipes
}
}
Now the Problem occurs at the build of the project, i get the error
SwiftUICore/EnvironmentObject.swift:92: Fatal error: No ObservableObject of type AuthViewModel found. A View.environmentObject(_:) for AuthViewModel may be missing as an ancestor of this view.
I already passed the ViewModel instances as EnvironmentObject in the App Struct.
import SwiftUI
import FirebaseCore
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
@main
struct NimetAndSonApp: App {
@StateObject var viewModel = AuthViewModel()
@StateObject var recipeViewModel = RecipeViewModel()
@StateObject var favoriteRecipeViewModel = FavoriteRecipeViewModel()
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(viewModel)
.environmentObject(recipeViewModel)
.environmentObject(favoriteRecipeViewModel)
}
}
}
Hi,
Firstly: The whole question is about MacCatalyst (in IOS it works as intended)
In my Maccatalyst app I want to share Userdefaults between app and widget. I have added an app group to the widget and the app and have set up Userdefauls accordingly.
Here is the problem:
Xcode claims that the app group should start with "group.***" because Catalyst is based on iOS. If I do so, my Catalyst app rises the "App wants to access data from other apps" requester on EVERY launch. So, I can't use it in production. Even if I would accept the requester, the widget isn't able to access the defaults at all because it does not rise that requester, but silently ignores the access.
In contrast, if I setup the app group name with our TeamID (instead of group.*) then the requester vanishes, but Xcode does not accept it, issuing a warning and displaying the app group in red. I don't think this is advisable 'state' for production code. Even then widget can't see the data either.
What is the recommended way of sharing Userdefaults between Catalyst app and Catalyst Widget (not the iOS widget which displays the "open on iPhone warning" when clicked) on macOS ?
Thanks