I use onPreferenceChange() and onScrollPhaseChange() to detect scroll is triggered by double tap. Is there any way to directly know the scroll is triggered by double tap?
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
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 have Swift code that accepts dragging a lowercase string from the TextEdit app.
On the first drop, the text is accepted as is but, on the second drop, the first words are capitalised.
Any ideas?
Topic:
UI Frameworks
SubTopic:
AppKit
I updated to iPadOS 18.2, i have a iPad Pro M2 11 inch, and this is what happens, can someone explain on how to fix this. (this is for users and Apple Developers only)
Previously this code would trigger fine on pressesBegan in iOS 17 and earlier versions, but no longer works in iOS 18. How can I start capturing pressesBegan in iOS 18? It seems like UIResponder is just not capturing the keyboard anymore?
struct ContentView: View {
var body: some View {
KeyBoardView()
}
}
//To Use in SwiftUI
struct KeyBoardView: UIViewRepresentable{
func makeUIView(context: Context) -> KeyEventView {
KeyEventView()
}
func updateUIView(_ uiView: KeyEventView, context: Context) {
}
class KeyEventView: UIView {
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?)
{
print("test")
}
}
}
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.
Hi, in my macOS app I am modifying the mouse cursor image for some user interactions. I also have an NSSlider in the app which can be changed programmatically by setting its doubleValue. I've noticed that whenever the slider is set programmatically the custom mouse cursor is lost and changes back to an arrow. This doesn't happen if other controls are changed programmatically, e.g. the progress bar. Any ideas on how I can prevent this happening?
Topic:
UI Frameworks
SubTopic:
AppKit
I want to play remote videos using an AVPlayer in my SwiftUI App. However, I can't fix the error:
"Main thread blocked by synchronous property query on not-yet-loaded property (PreferredTransform) for HTTP(S) asset. This could have been a problem if this asset were being read from a slow network."
My code looks like this atm:
struct CustomVideoPlayer: UIViewControllerRepresentable {
let myUrl: URL
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
func makeUIViewController(context: Context) -> AVPlayerViewController {
let playerItem = AVPlayerItem(url: myUrl)
let player = AVQueuePlayer(playerItem: playerItem)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
context.coordinator.setPlayerLooper(player: player, templateItem: playerItem)
playerViewController.delegate = context.coordinator
playerViewController.beginAppearanceTransition(true, animated: false)
return playerViewController
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
static func dismantleUIViewController(_ uiViewController: AVPlayerViewController, coordinator: ()) {
uiViewController.beginAppearanceTransition(false, animated: false)
}
class Coordinator: NSObject, AVPlayerViewControllerDelegate {
var parent: CustomVideoPlayer
var player: AVPlayer? = nil
var playerLooper: AVPlayerLooper? = nil
init(_ parent: CustomVideoPlayer) {
self.parent = parent
super.init()
}
func setPlayerLooper(player: AVQueuePlayer, templateItem: AVPlayerItem) {
self.player = player
playerLooper = AVPlayerLooper(player: player, templateItem: templateItem)
}
}
}
I already tried creating the AVPlayerItem/AVAsset on a background thread and I also tried loading the properties asynchronously before setting the player in makeUIViewController:
let player = AVQueuePlayer(playerItem: nil)
...
Task {
let asset = AVAsset(url: myUrl)
let _ = try await asset.load(.preferredTransform)
let item = AVPlayerItem(asset: asset)
player.replaceCurrentItem(with: item)
}
Nothing seems to fix the issue (btw: the main thread is actually blocked, there is a noticable animation hitch).
Any help is much appreciated.
Topic:
UI Frameworks
SubTopic:
General
Hello, I've created an app that follows the user as they navigate through public transport.
I want the camera to follow the user and at the same time I want the camera distance (elevation) to change dynamically depending on speed and other factors.
I've tried a first approach using camera keyframes, but I've noticed a lot of crashes when the app comes back to the foreground.
.mapCameraKeyframeAnimator(trigger: cameraFrame) { camera in
KeyframeTrack(\MapCamera.centerCoordinate) {
LinearKeyframe(cameraFrame.center, duration: cameraFrame.duration, timingCurve: cameraFrame.curve)
}
KeyframeTrack(\MapCamera.distance) {
LinearKeyframe(cameraFrame.distance, duration: cameraFrame.duration, timingCurve: cameraFrame.curve)
}
}
Some logs mention wrong center coordinates (nan, nan) but when I print them, it's show me valid coordinates.
I've also tried manually setting the camera for each position update, but the result is not smooth.
position = .camera(
.init(.init(
lookingAtCenter: newPosition,
fromDistance: cameraElevation,
pitch: .zero,
heading: .zero)
)
)
What's the best way to achieve this?
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 for some reason the left side showing the Entity (Box) more near to the camera than the right side which make it not identical, I wonder is this a bug and need to be fixed or what ? thanx
Here is the code
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])
}
}
}
And Here is the View
Not sure exactly what’s going on here. I’ve been building out this little app for the past couple of weeks using Xcode 16 betas, and in a couple of places I have code like this:
EditItemView(item: inItem)
.toolbar
{
ToolbarItem
{
Button(action: { self.printLabel(item: inItem) })
{
Label("Print Label", systemImage: "printer.filled.and.paper")
}
}
}
Now all of a sudden I'm getting an error on .toolbar: “Trailing closure passed to parameter of type 'Visibility' that does not accept a closure.”
Looking at the comment for toolbar, it says this method "specifies the visibility," which is a weird thing for it to do with a name like that. But it also has a deprecation tag that I don't quite understand: @available(macOS, introduced: 13.0, deprecated: 100000.0, renamed: "toolbarVisibility(_:for:)"). The name change makes sense, given the description. But what is the huge deprecation version number? Just a hack?
And why is this code no longer compiling? As I'm commenting out instances of this, all my toolbars are failing in this way.
ETA: yeah, I finally found the right declaration of .toolbar: func toolbar<Content>(@ViewBuilder content: () -> Content) -> some View where Content : View. It's no longer choosing that one. I hate Swift sometimes.
ETA2: I finally whittled it down to it not liking Label for some reason. Replacing that with Image works. But of course, the compiler won't tell me why.
ETA3: It's worse than I thought: I tried to make a small test case for a bug, and Label works just fine. Why does my code not?
Is there really no way to hide a TabItem using the built-in TabView?
I have 6 pages, but the 6th one I want hidden from the bottom tab bar, because I have a button that programmatically navigates to it on the navigation bar.
I did not want to have to code a custom tab bar due to losing some useful features like pop to root in Navigation Stack.
I made a ImagePicker which worked pretty well. But when app get bigger it stops. Does not react to change isPresented value. As far I know I changed nothing around this part of an App. Also same thing happened in different place, another kind of picker.
print ("HELL'o") never prints. Silence.
struct ImagePicker: View {
@Binding var imageSource: ImageSource
@State var showFileImporter: Bool = false
@EnvironmentObject var manager: Manager
var body: some View {
VStack {
....
Button(action: {
print("before", showFileImporter)
showFileImporter = true
print("after", showFileImporter)
},
label: { Text("open Image") })
.buttonStyle(.borderless)
.controlSize(.mini)
}.fileImporter(isPresented: $showFileImporter,
allowedContentTypes: [.png, .jpeg, .tiff],
onCompletion: { result in
print ("HELL'o") // Never prints
switch result {
case let .success(url):
guard let _ = try? Data(contentsOf: url) else { return }
....
case let .failure(error):
print(error)
}
})
}
}
Does anybody have an idea what happened?
I suspect some settings in completely different palce or bug or computer does not like me.
Dear Experts,
I created a SwiftUI View (in a UIKit based project) whose objective is to display a short animation in the front of the user screen. I developed it 8 month ago in XCode 15 for iOS 17, no problems.
But since iOS 18, I can observe huge lags on my animation only in Release app. The problem is not present in Debug app.
I don't understand why this problem occurs, the animation is quite simple, it's just an offset deplacement.
I tried many thing like:
Show the animation with a UINavigationController
Show the animation with a UIWindow
Move the view with .position
Remove the GeometryReader
All other animation
withAnimation and .animation
Task and DispatchQueue
Etc...
I found that the laggy animation occurs when I set the Optimization Level for the Swift Compiler - Code Generation to Optimize for Speed [-O]. That's very strange because we had this option on Release for iOS 17 and we had no lags...
I can share to you a Sample Repository with the configuration we have. https://github.com/Thibma/sample-animation-swiftui
Today the only option I used is to develop this feature in UIKit but it's too bad to skip the SwiftUI opportunity. :/
If you have any ideas to resolve this, I take !
Thank you !
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
}
Hi,
Have been trying to work with MapkitJS for a website, but I'm stumped on once basic capability: I want to be able to click on a point of interest, and perform some actions such as:
Get its coordinates
Attach an annotation to it (e.g. a callout)
In my code, PointOfInterest's are selectable:
map.selectableMapFeatures = [
mapkit.MapFeatureType.PointOfInterest,
];
But when I click on one, I do see the marker pop up but nothing else (which is not much help since there is no additional information in the marker itself). I see no event getting triggered that I can do something with.
I am using an event listener as follows:
map.addEventListener('single-tap', (event) => {
const coordinate = map.convertPointOnPageToCoordinate(event.pointOnPage);
console.log('Map tapped at:', coordinate);
console.log('Map tapped event:', event);
...
I guess I have to grab the Place ID somehow but I don't know how to.
Thanks for any help.
Hello guys,
I have such a big coding problem since a half year now about data saving.
I have a fitness app where we can add our exercices depend of the muscle, so you can choose it and then select your weight and number of repetitions and valid your exercise.
But when I do my exercises and my watch screen is also turn off, my muscle and muscleExercise variables are going back to their default value.
Here some code for you :
@EnvironmentObject var dataManager: DataManager
@Environment(\.modelContext) private var context
@AppStorage("savedGroupName") private var savedGroupName: String = ""
@AppStorage("savedExerciceName") private var savedExerciceName: String = ""
@State var groupName: String = "À choisir"
@State var ExerciceChoose: String = "À choisir"
I use my variables here :
HStack {
Text("Muscle:")
Spacer()
NavigationLink(destination: MusclesView()) {
Text(savedGroupName.isEmpty ? "À choisir" : savedGroupName)
}
.buttonStyle(PlainButtonStyle())
}
.onAppear {
savedGroupName = groupName
}
HStack {
Text("Exercise:")
Spacer()
NavigationLink(destination: MuscleExercicesView(groupName: groupName, ExerciceChoose: ExerciceChoose)) {
Text(savedExerciceName.isEmpty ? "À choisir" : savedExerciceName)
}
.onAppear {
savedExerciceName = ExerciceChoose
}
.buttonStyle(PlainButtonStyle())
}
The value of my muscle variable is taking in an other view :
struct MusclesView: View {
let muscleGroup = ExerciceData.muscleGroups
var body: some View {
NavigationStack {
List(muscleGroup, id: \.name) { group in
NavigationLink(destination: MuscleExercicesView(groupName: group.name, ExerciceChoose: "À choisir")) {
Text(group.name)
}
}
}
}
}
#Preview {
MusclesView()
}
and the value of the exerciseMuscle variable is also taking in an other view :
```import SwiftUI
struct MuscleExercicesView: View {
let exerciceGroup = ExerciceData.muscleGroups
@State var groupName: String
@State var ExerciceChoose: String
var body: some View {
if let group = ExerciceData.muscleGroups.first(where: { $0.name == groupName }) {
List(group.exercices, id: \.id) { exercice in
NavigationLink(exercice.name, destination: CurrentInformationsView(groupName: groupName, ExerciceChoose: exercice.name))
}
/*.onTapGesture {
print("Selected exercise: \(ExerciceChoose) for muscle group: \(groupName)")
}*/
.navigationTitle(Text("Exercices pour \(groupName)"))
} else {
Text("Aucun exercice trouvé pour \(groupName)")
.navigationTitle(Text("Erreur"))
}
}
}
#Preview {
MuscleExercicesView(groupName: "Pectoraux", ExerciceChoose: "À choisir")
}
I tried many things (like userDefault, put my values in an array to save it etc..) to keep my variables with the same value during the session but nothing works.
I wish I could have some help from you guys.
Have a good day !
Cyrille
let activityViewController = UIActivityViewController(activityItems: items,
applicationActivities: [])
activityViewController.popoverPresentationController?.barButtonItem = navigationController.topViewController?.navigationItem.rightBarButtonItem
navigationController.present(activityViewController, animated: true, completion: nil)
Crash logs
=====================================================
*** Assertion failure in -[_UIActivityContentCollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], UICollectionView.m:7588
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to dequeue a cell for a different registration or reuse identifier than the existing cell when reconfiguring an item, which is not allowed. You must dequeue a cell using the same registration or reuse identifier that was used to dequeue the cell originally to obtain the existing cell. Dequeued reuse identifier: UIActivityContentActionCellIdentifier; Original reuse identifier: UIActivityActionGroupCell; Existing cell: <UIActivityActionGroupCell: 0x10f19f220; baseClass = _UICollectionViewListCell; frame = (16 354; 358 30); clipsToBounds = YES; layer = <CALayer: 0x600000781740>>'
I am able to play a video on a plane in ARKit. But, I need to remove its background, presumably using a chromaKey technique. how do I do that? I have spent more time than is reasonable searching the docs and the internet, but to no avail. ChatGPT useless of course.
Surely it is doable; even the react native library for ARKit has it.
Hi all! I encountered some strange behaviour that I cannot explain. When I have a NavigationStack that is embedded in a TabView, and that NavigationStack uses a NavigationPath that is stored within an ObservableObject, and the view within the NavigationStack gets its NavigationDestinations via an extension on the View object (either via a direct function or via a ViewExtension), the navigation doesn't work as expected, namely that back button seems to not pop views from the path. Consider the following example:
struct ContentView: View {
var body: some View {
TabView {
NavViewContainer1()
.tabItem {
Text("One")
}
NavViewContainer2()
.tabItem {
Text("Two")
}
}
}
}
@MainActor
class Model: ObservableObject {
@Published var path = NavigationPath()
}
struct NavViewContainer1: View {
@StateObject private var model = Model()
var body: some View {
NavigationStack(path: $model.path) {
VStack {
Text("1").font(.title).padding()
NavigationLink(value: "One") {
Text("Dest 1")
}
NavigationLink(value: "Two") {
Text("Dest 2")
}
}
.navigationDestination(for: String.self) { Text($0) }
}
}
}
struct NavViewContainer2: View {
@StateObject private var model = Model()
var body: some View {
NavigationStack(path: $model.path) {
VStack {
Text("2").font(.title).padding()
NavigationLink(value: "One") {
Text("Dest 1")
}
NavigationLink(value: "Two") {
Text("Dest 2")
}
}
.setUpDestinations()
}
}
}
extension View {
func setUpDestinations() -> some View {
navigationDestination(for: String.self) { Text($0) }
}
}
When clicking the destination buttons on the first tab (so in NavViewContainer1, I can go to a child view, back to the root, then click the other link to go to a child view and back to the root, all good. The route taken looks like this: Root > Dest 1 > Root > Dest 2 > Root.
However, when I do the same in the second tab (NavViewContainer2), as soon as I click on the second destination, it seems like the first destination was not removed from the path, since clicking the back button in the second destination brings me to the first destination. The route taken looks like this: Root > Dest 1 > Root > Dest 2 > Dest 1 > Root.
If I either move the view out of the TabView, move the path inside of the view with a @State variable or as in view 1 add the navigationDestinations directly, the path works as expected. Only the combination of TabView + NavigationPath in ObservableObject + view extension yields this behaviour. Am I missing something here, or is this a bug in the SwiftUI framework?
Topic:
UI Frameworks
SubTopic:
SwiftUI