I have a DocumentGroup working with a FileDocument, and that's fine.
However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created).
There seems to be no way to do this on macOS?
I basically want to have someone:
create a new document
enter some basic data
hit "create" which saves the file
then lets the user start editing it
(1), (2), and (4) are done and fairly trivial.
(3) seems impossible, though...?
This really only needs to support macOS but any pointers would be appreciated.
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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Subject: SwiftUI Gesture Conflict in iOS 18: Simultaneous Recognition of Drag and Tap Gestures
Description:
In SwiftUI on iOS 18 and above, we've identified an issue with gesture handling that affects user experience. When implementing .simultaneousGesture(DragGesture()), the system incorrectly recognizes and processes both drag and tap gestures concurrently, resulting in unintended behavior.
Technical Details:
Environment: SwiftUI, iOS 18+
Issue: Simultaneous recognition of horizontal drag gestures and vertical scroll/tap gestures
Current Behavior: Both vertical and horizontal scrolling occur simultaneously when using .simultaneousGesture(DragGesture())
Expected Behavior: Gestures should be properly disambiguated to prevent concurrent scrolling in multiple directions
Impact:
This behavior significantly impacts user experience, particularly in custom carousel implementations and other UI components that rely on precise gesture handling. The simultaneous recognition of both gestures creates a confusing and unpredictable interaction pattern.
Steps to Reproduce:
Create a SwiftUI view with horizontal scrolling (e.g., custom carousel)
Implement .simultaneousGesture(DragGesture())
Add tap gesture recognition to child views
Run on iOS 18
Attempt to scroll horizontally
Observed Result:
Both horizontal dragging and vertical scrolling/tapping are recognized and processed simultaneously, creating an inconsistent user experience.
Expected Result:
The system should properly disambiguate between horizontal drag gestures and vertical scroll/tap gestures, allowing only one type of gesture to be recognized at a time based on the user's intent.
Please let me know if you need any additional information or reproduction steps.
Device: iPhone 16 Pro Max
System Version: 18.3.1
Screen width and height obtained using [UIScreen mainScreen].bounds.size are as follows
Why are the two results different?
I have received permission from Apple to access SensorKit data for my app. I have granted all necessary permissions, but no data is being retrieved.
The didCompleteFetch method is being called, but I’m unsure where to find event data like Device Usage and Ambient Light. Additionally, the didFetchResult method is never called.
Could anyone please assist me in resolving this issue? Any guidance or troubleshooting steps would be greatly appreciated.
import SensorKit
class ViewController: UIViewController, SRSensorReaderDelegate {
let store = SRSensorReader(sensor: .deviceUsageReport)
override func viewDidLoad() {
super.viewDidLoad()
requestSensorAuthorization()
}
func requestSensorAuthorization() {
var sensors: Set<SRSensor> = [
.accelerometer,
.deviceUsageReport,
.messagesUsageReport,
.visits,
.keyboardMetrics,
.phoneUsageReport,
.ambientLightSensor
]
if #available(iOS 16.4, *) {
sensors.insert(.mediaEvents)
}
SRSensorReader.requestAuthorization(sensors: sensors) { error in
if let error = error {
print("Authorization failed: \(error.localizedDescription)")
} else {
self.store.startRecording()
self.requestSensorData()
print("Authorization granted for requested sensors.")
}
}
}
func requestSensorData() {
let fromTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: Date().addingTimeInterval(-60 * 60).timeIntervalSinceReferenceDate)
let toTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: Date().timeIntervalSinceReferenceDate)
let request = SRFetchRequest()
request.from = fromTime
request.to = toTime
request.device = SRDevice.current
store.fetch(request)
store.delegate = self
}
func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest) {
print("Fetch request completed: \(fetchRequest.from) to \(fetchRequest.to)")
Task {
do {
let samples = try await reader.fetch(fetchRequest)
print("Samples count: \(samples)")
} catch {
print("Error Fetching Data: \(error.localizedDescription)")
}
}
}
func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool {
print(result)
return true
}
}
Hi Apple team and community,
We’re encountering a strange issue with Live Activity that seems related to memory management or background lifecycle.
❓ Issue:
Our app updates a Live Activity regularly (every 3 minutes) using .update(...). However, after the app remains in the background for around 8 hours, the Live Activity reverts to the initial state that was passed into .request(...).
Even though the app continues sending updates in the background, the UI on the Lock Screen and Dynamic Island resets to the original state.
I want to truncate text from head with max 2 lines.
I try the following code
import SwiftUI
struct ContentView: View {
@State var content: String = "Hello world! wef wefwwfe wfewe weweffwefwwfwe wfwe"
var body: some View {
VStack {
Text(content)
.lineLimit(nil)
.truncationMode(.head)
.frame(height: 50)
Button {
content += content
} label: {
Text("Double")
}
.buttonStyle(.borderedProminent)
}
.frame(width: 200, height: 1000)
.padding()
}
}
#Preview {
ContentView()
}
It show result like this, this is not what I want.
I have the MainView as the active view if the user is logged in(authenticated). the memory allocations when we run profile is pretty good. We have graphql fetching, we have token handling eg: This is All heap:
1 All Heap & Anonymous VM 13,90 MiB 65408 308557 99,10 MiB 373965 Ratio: %0.14, %0.86
After what i have checked this is pretty good for initialise and using multiple repositories eg. But when we change tabs:
1 All Heap & Anonymous VM 24,60 MiB 124651 543832 156,17 MiB 668483 Ratio: %0.07, %0.40
And that is not pretty good. So i guess we need to "kill" it or something. How? I have tried some techniques in a forum this was a recommended way:
public struct LazyView<Content: View>: View {
private let build: () -> Content
@State private var isVisible = false
public init(_ build: @escaping () -> Content) {
self.build = build
}
public var body: some View {
build()
Group {
if isVisible {
build()
} else {
Color.clear
}
}
.onAppear { isVisible = true }
.onDisappear { isVisible = false }
}
}
But this did not help at all. So under here is the one i use now. So pleace guide me for making this work.
import DIKit
import CoreKit
import PresentationKit
import DomainKit
public struct MainView: View {
@Injected((any MainViewModelProtocol).self) private var viewModel
private var selectedTabBinding: Binding<MainTab> {
Binding(
get: { viewModel.selectedTab },
set: { viewModel.selectTab($0) }
)
}
public init() {
// No additional setup needed
}
public var body: some View {
NavigationStack(path: Binding(
get: { viewModel.navigationPath },
set: { _ in }
)) {
TabView(selection: selectedTabBinding) {
LazyView {
FeedTabView()
}
.tabItem {
Label("Feed", systemImage: "house")
}
.tag(MainTab.feed)
LazyView {
ChatTabView()
}
.tabItem {
Label("Chat", systemImage: "message")
}
.tag(MainTab.chat)
LazyView {
JobsTabView()
}
.tabItem {
Label("Jobs", systemImage: "briefcase")
}
.tag(MainTab.jobs)
LazyView {
ProfileTabView()
}
.tabItem {
Label("Profile", systemImage: "person")
}
.tag(MainTab.profile)
}
.accentColor(.primary)
.navigationDestination(for: MainNavigationDestination.self) { destination in
switch destination {
case .profile(let userId):
Text("Profile for \(userId)")
case .settings:
Text("Settings")
case .jobDetails(let id):
Text("Job details for \(id)")
case .chatThread(let id):
Text("Chat thread \(id)")
}
}
}
}
}
import SwiftUI
public struct LazyView<Content: View>: View {
private let build: () -> Content
public init(_ build: @escaping () -> Content) {
self.build = build
}
public var body: some View {
build()
}
}
My setup:
a UILabel with text in it
and then
let aBugRenderer = UIGraphicsImageRenderer(size: aBugLabel.bounds.size)
let aBugImage = aBugRenderer.image { context in
aBugLabel.drawHierarchy(in: aBugLabel.bounds, afterScreenUpdates: true)
}
The layout and everything is correct, the image is correct, but I used my colors in the displayP3 color space to configure the source UILabel.textColor
And unfortunately, the resulted image ends up being sRGB IEC61966-2.1 color space and the color appears way bleaker than when it's drawn natively.
Question: how can I set up the renderer so that it draws the same color.
I have a UITextField in my application, and I want to detect all the keys uniquely to perform all relevant task. However, there is some problem in cleanly identifying some of the keys.
I m not able to identify the backspace key press in the textField(_:shouldChangeCharactersIn:replacementString:) method.
Also I don't know how to detect the Caps Lock key.
I am intending to so this because I want to perform some custom handling for some keys. Can someone help me with what is the way of detecting it under the recommendation from apple. Thanks in advance.
Note: checking for replacementString parameter in shouldChangeCharactersIn method for empty does not help for backspace detection as it overlaps with other cases.
The behavior of the Button in ScrollView differs depending on how the View is displayed modally.
When the View is displayed as a .fullScreenCover, if the button is touched and scrolled without releasing the finger, the touch event is canceled and the action of the Button is not called.
On the other hand, if the View is displayed as a .sheet, the touch event is not canceled even if the view is scrolled without lifting the finger, and the action is called when the finger is released.
In order to prevent accidental interaction, I feel that the behavior of .fullScreenCover is better, as it cancels the event immediately when scrolling. Can I change the behavior of .sheet?
Demo movie is here:
https://x.com/kenmaz/status/1896498312737611891
Sample code
import SwiftUI
@main
struct SampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var showSheet = false
@State private var showFullScreen = false
var body: some View {
VStack(spacing: 16) {
Button("Sheet") {
showSheet.toggle()
}
Button("Full screen") {
showFullScreen.toggle()
}
}
.sheet(isPresented: $showSheet) {
SecondView()
}
.fullScreenCover(isPresented: $showFullScreen) {
SecondView()
}
.font(.title)
}
}
struct SecondView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
ScrollView {
Button("Dismiss") {
dismiss()
}
.buttonStyle(MyButtonStyle())
.padding(.top, 128)
.font(.title)
}
}
}
private struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration
.label
.foregroundStyle(.red)
.background(configuration.isPressed ? .gray : .clear)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
@Observable seems not to work well with generic typed throw.
The following code using @Observable with non-generic typed throw builds good:
@Observable
class ThrowsLoadingViewModel<R, E: Error> {
private(set) var isLoading = true
private(set) var error: E? = nil
private(set) var data: R? = nil
private var task: () throws(Error) -> R
init(task: @escaping () throws(E) -> R) {
self.task = task
}
func load() {
do throws(Error) {
self.data = try task()
} catch {
// self.error = error
}
self.isLoading = false
}
}
But if I change Line 7 and 14 to generic, it'll breaks the build with a "Command SwiftCompile failed with a nonzero exit code" message :
@Observable
class ThrowsLoadingViewModel<R, E: Error> {
private(set) var isLoading = true
private(set) var error: E? = nil
private(set) var data: R? = nil
private var task: () throws(E) -> R
init(task: @escaping () throws(E) -> R) {
self.task = task
}
func load() {
do throws(E) {
self.data = try task()
} catch {
// self.error = error
}
self.isLoading = false
}
}
A the same time, if I remove @Observable, the generic typed throw works again:
class ThrowsLoadingViewModel<R, E: Error> {
private(set) var isLoading = true
private(set) var error: E? = nil
private(set) var data: R? = nil
private var task: () throws(E) -> R
init(task: @escaping () throws(E) -> R) {
self.task = task
}
func load() {
do throws(E) {
self.data = try task()
} catch {
// self.error = error
}
self.isLoading = false
}
}
Currently the possible solution seems to fall back to use ObservableObject...
I want to record screen ,and than when I call the method stopCaptureWithHandler:(nullable void (^)(NSError *_Nullable error))handler to stop recording and saving file. before call it,I check the value record of RPScreenRecorder sharedRecorder ,the value is false , It's weird! The screen is currently being recorded !
I wonder if the value of [RPScreenRecorder sharedRecorder].record will affect the method stopCaptureWithHandler:
-(void)startCaptureScreen {
[[RPScreenRecorder sharedRecorder] startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error) {
//code
} completionHandler:^(NSError * _Nullable error) {
//code
}];
}
- (void)stopRecordingHandler {
if([[RPScreenRecorder sharedRecorder] isRecording]){
// deal error .sometime isRecording is false
}else {
[[RPScreenRecorder sharedRecorder] stopCaptureWithHandler:^(NSError * _Nullable error) {
}];
}
}
here are my code.
Hi, I'm working on RealityView and I have two entities in RCP. In order to set views for both entities, I have to create two separate attachments for each entity. What I want to achieve is that when I hover (by eye) on one entity's attachment, it would trigger the hover effect of the other entity's attachment. I try to use the hoverEffectGroup, but it would only activate the hover effect in a subview, instead a complete separate view. I refer to the following WWDC instruction for the hover effect.
https://developer.apple.com/videos/play/wwdc2024/10152/
I'm using SwiftUI's TextEditor. I'd like to include an undo button in my UI that operates on the TextEditor. I don't see a way to hook this up. You can get the UndoManager from the environment, but this is not the undo manager the TextEditor is using. I know that UITextView uses an undocumented UndoManager (_UITextUndoManager) and I've accessed that before when using a UIViewRepresentable wrapper around UITextView. I'd like to achieve the same with TextEditor.
Topic:
UI Frameworks
SubTopic:
SwiftUI
I am currently implementing multiple scenes in my React Native / Swift application (one scene for the phone and one scene for CarPlay). I am facing an issue where one scene renders completely white (on the iPhone) but I can see in the console that the code is running (for example if I add a console.log to the App.tsx I can see that console log happen in XCode).
There are no errors when building the app in XCode, and testing with the simulator CarPlay appears to render the correct output, but there is no component being rendered on the simulated phone screen (just white).
AppDelegate.swift
import CarPlay
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import UIKit
@main
class AppDelegate: RCTAppDelegate {
var rootView: UIView?;
static var shared: AppDelegate { return UIApplication.shared.delegate as! AppDelegate }
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
self.moduleName = "appName"
self.dependencyProvider = RCTAppDependencyProvider()
self.initialProps = [:]
self.rootView = self.createRootView(
with: RCTBridge(
delegate: self,
launchOptions: launchOptions
),
moduleName: self.moduleName!,
initProps: self.initialProps!
);
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
if (connectingSceneSession.role == UISceneSession.Role.carTemplateApplication) {
let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role)
scene.delegateClass = CarSceneDelegate.self
return scene
}
let scene = UISceneConfiguration(name: "Phone", sessionRole: connectingSceneSession.role)
scene.delegateClass = PhoneSceneDelegate.self
return scene
}
override func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {}
override func sourceURL(for bridge: RCTBridge) -> URL? {
self.bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}
PhoneSceneDelegate.swift
import Foundation
import UIKit
import SwiftUI
class PhoneSceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?;
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if session.role != .windowApplication {
return
}
guard let appDelegate = (UIApplication.shared.delegate as? AppDelegate) else {
return
}
guard let windowScene = (scene as? UIWindowScene) else {
return
}
let rootViewController = UIViewController()
rootViewController.view = appDelegate.rootView;
let window = UIWindow(windowScene: windowScene)
window.rootViewController = rootViewController
self.window = window
window.makeKeyAndVisible()
}
}
App.tsx
import React, {useEffect, useState} from 'react';
import type {PropsWithChildren} from 'react';
import {CarPlay, ListTemplate} from 'react-native-carplay';
import {
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
LearnMoreLinks,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
type SectionProps = PropsWithChildren<{
title: string;
}>;
function Section({children, title}: SectionProps): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
</Text>
<Text
style={[
styles.sectionDescription,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{children}
</Text>
</View>
);
}
function App(): any { // React.JSX.Element
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
const [carPlayConnected, setCarPlayConnected] = useState(CarPlay.connected);
useEffect(() => {
function onConnect() {
setCarPlayConnected(true);
CarPlay.setRootTemplate(new ListTemplate(/** This renders fine on the CarPlay side */));
}
function onDisconnect() {
setCarPlayConnected(false);
}
CarPlay.registerOnConnect(onConnect);
CarPlay.registerOnDisconnect(onDisconnect);
return () => {
CarPlay.unregisterOnConnect(onConnect);
CarPlay.unregisterOnDisconnect(onDisconnect);
};
});
if (carPlayConnected) {
console.log('car play connected');
} else {
console.log('car play not connected');
}
const safePadding = '5%';
// This doesn't render on the phone?
return (
<View style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
style={backgroundStyle}>
<View style={{paddingRight: safePadding}}>
<Header/>
</View>
<View
style={{
backgroundColor: isDarkMode ? Colors.black : Colors.white,
paddingHorizontal: safePadding,
paddingBottom: safePadding,
}}>
<Section title="Step One">
Edit <Text style={styles.highlight}>App.tsx</Text> to change this
screen and then come back to see your edits.
</Section>
<Section title="See Your Changes">
<ReloadInstructions />
</Section>
<Section title="Debug">
<DebugInstructions />
</Section>
<Section title="Learn More">
Read the docs to discover what to do next:
</Section>
<LearnMoreLinks />
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
export default App;
I have been attempting to get this working now for some 20+ hours with no luck with searching for answers elsewhere. I am very new to building apps with React Native and Swift so could do with some support.
Hi, I've got an app that displays markdown in UITextView / NSTextView.
I would like it to behave like Notes app does, that is if user types the line start modifier, e.g:
"# "
or
"> "
I would like the keyboard to show a capitalized letters.
I've tried looking into overriding insertText - and it breaks the predictive text (can not insert white space).
I've tried implementing UITextInputTokenizer but no luck either.
Like I said, I see the Notes app does it perfectly, so maybe I'm missing something obvious or there is a way to do it without interrupting the auto-correction and predictive text.
Ideally same thing can be applied to the NSTextView as the app support both platforms.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Button ("Button 1") {
print ("Button 1");
}
.keyboardShortcut("k", modifiers: .command)
Button ("Button 2") {
print ("Button 2");
}
.keyboardShortcut("k", modifiers: .command)
}
}
}
I the above snippet, I have assigned the same keyboard shortcut (cmd +k) to 2 different buttons. According to the docs, if multiple controls are associated with the same shortcut, the first one found is used.
How do I figure out if Button 1 would be found first during the traversal or Button 2 ?
Is it based on the order of declaration? Is it always the case that Button 1 would be found first since it was declared before Button 2 ?
I am currently developing an AR experience using ARKit with SceneKit and am looking to implement functionality that enables:
Zooming into the AR camera feed, ideally leveraging the ultra-wide or telephoto lenses available on supported devices.
Macro-style focus capabilities, allowing users to view and interact with virtual content closely aligned with small or nearby real-world objects (within a few centimeters).
My objective is to ensure that ARKit continues to render the scene accurately while enabling a zoomed-in view or macro-level focus for better detail visibility and alignment.
Could you please advise on:
Whether ARKit currently supports camera zoom or allows access to macro or ultra-wide cameras within an ARSession.
Limitations or considerations when using multi-camera setups in conjunction with ARKit.
Any guidance or references to documentation or sample code would be greatly appreciated.
Best regards,
Ayush
The app I'm converting includes two unique document types. UI-wise they have key similarities (eg contents are password protected) But serialization/model - wise. they are different documents. I have not been able to find any documentation on options for implementing this (eg use a (abstract?) base class derived from FileDocument, with two concrete sub classes? maybe just a single subclass of FileDocument that contains model details for both file types?)
Stepping back from implementation options, am I crazy for attempting to use DocumentGroup to create a single app that would need to be able to open/modify/save multiple unique document types?
any/all guidance much appreciated.
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have a SwiftUI app which needs the Ivanti AppConnect SDK. The docs only show how to integrate it into a Swift/UIKit app. But I need it to work with SwiftUI. I probably could make a UIKit base app and then load my existing SwiftUI views and code through a SwiftUI component host or something. But I'd like to avoid that if possible.
Here is where I'm stuck:
The AppConnect framework loads through a custom UIApplication subclass in the main.swift file:
import Foundation
import AppConnect
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
ACUIApplicationClassName,
NSStringFromClass(AppDelegate.self)
)
The startup works as expected, and the expected function is called in the AppDelegate class:
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {...}
However, the SwiftUI view is not loaded and the scree stays blank.
I implemented a SceneDelegate.swift class which doesn't seem to be called.
Also, the following function in the AppDelegate doesn't get called either:
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {...}
So how do I bootstrap SwiftUI with a custom UIApplication class? can that be done with the @main macro somehow?
I'm still pretty new to Swift and iOS development. Any help is appreciated