Edit: Well this is embarassing. It looks like I didn't research this thoroughly enough, animations block UIVIew tap events. I found a solution by using DispatchQueue
I ran into an unexpected issue when presenting a UIView-based toast inside a separate UIWindow in a SwiftUI app. Specifically, when animations are applied to the toast view (UIToastView), the tap gesture no longer works.
To help identify the root cause, I created a minimal reproducible example (MRE) with under 500 lines of code, demonstrating the behavior:
Demo GIF: Screen Recording
Code Repo: ToastDemo
What I Tried:
Using a separate UIWindow to present the toast overlay.
Adding a tap gesture directly to the UIView.
Referencing related solutions:
A Blog Post explaining UIWindow usage in SwiftUI - https://www.fivestars.blog/articles/swiftui-windows (Sorry, Apple Dev Forum will not allow a link to this)
A Stack Overflow thread on handling touch events in multiple windows.
Problem Summary:
When animations are involved (fade in, slide up), taps on the toast are not recognized.
Without animations, taps work as expected.
UIWindow setup seems correct, so I’m wondering if animation effects are interfering with event propagation.
I could potentially work around this by restructuring the touch handling, but I'd love insight from the community on why this happens, or if there’s a cleaner fix.
Edit: Well this is embarassing. It looks like I didn't research this thoroughly enough, animations block UIVIew tap events. I found a solution by using DispatchQueue
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Posts under UIKit tag
187 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello!
I wanted to see if someone with more UIKit experience than me can help me out on guiding me in the right direction for conditionally adding and deleting a row in a UITableView.
What I Want to Accomplish
I have a tip slider with percentages (0% - 20%) with a custom option on the end. I'm wanting to, when the custom option is tapped, bring up a row immediately below there and have a UITextField. When another option, let's say 10%, is tapped, I want the text field row to go away.
Can someone explain to me how this would work? And if so, provide an example?
Thank you!
Hi. If the app is in landscape only and when the SKStoreProductViewController is presented, the safeArea changes to what looks like a portrait mode safe area. When the SKStoreProductViewController is dismissed, the safeArea does NOT revert back to the original values.
Is there a way to force the safeArea to "reset"? I've submitted some bug tickets through Apple Feedback but I haven't received any response about it.
The below code will pop up the SKStoreProductViewController and if you have a UIView that is constrained to the safe area, then you can visibly notice that the safe area is changed and doesn't go back.
I have tested this on iPhone 14 Pro, iPhone 15, and iPhone 16 Pro and in the Simulators. The incorrect behavior happens on those and probably more.
Thanks.
#import "ViewController.h"
#import <StoreKit/StoreKit.h>
@interface ViewController ()
@property (nonatomic, strong) SKStoreProductViewController *productViewController;
@end
@implementation ViewController
- (IBAction)buttonTapped:(id)sender {
self.productViewController = [[SKStoreProductViewController alloc] init];
NSDictionary *parameters = @{
@"id" : @"6443575749"
};
[self.productViewController loadProductWithParameters:parameters completionBlock:^(BOOL result, NSError * _Nullable error) {
[self presentViewController:self.productViewController animated:YES completion:^{
// presented
// The panel that is constraint to the safe area visibly shows that the safe area is no longer correct.
}];
}];
}
@end
I have a UIPageViewController embedded in a UIScrollView and each page has a drawing view with a UIPanGestureRecognizer to free-draw. With this setup, the 1st time I attempt to draw, the pan gesture is ignored. It works the 2nd time I perform the gesture.
In my case I need to wrap the UIPageViewController in a UIScrollView to have a pull to refresh mechanism (set thescrollView.refreshControl).
I’ve tried every combination of UIGestureRecognizerDelegate methods (shouldRecognizeSimultaneously…, require(toFail:), etc.) with no luck.
This is my view hierarchy:
ScrollView
|- UIPageViewController
|- Page 1
| |- DrawingView with UIPanGestureRecognizer
|- Page 2
|- DrawingView with UIPanGestureRecognizer
Is this a known limitation when a UIPageViewController is nested inside another scroll view?
Reproduction steps (tested on iOS 18.4 / Xcode 16.3, iPhone 16 Pro)
Launch the app; the first page shows a white canvas in the bottom part.
Try to draw immediately → nothing happens.
Lift your finger and draw again → works.
Here is a link for the sample project with the reproducible code: https://github.com/marcod-storyteller/page-controller-sample
P.S: If the UIPageViewController has a .pageCurl transition style instead, the problem disappears.
Hello,
I'm currently working on my first SceneKit game and have encountered an issue related to moving an SCNNode using a UIPanGestureRecognizer.
When I deploy the game to my iPhone via Xcode in debug mode, all interactions are smooth. However, when I stop the debugging session and run the game directly from the device (outside of Xcode), the SCNNode movement behaves inconsistently — it works sometimes smoothly and sometimes not and the interaction becomes choppy. The SCNNode movement is controlled using a UIPanGestureRecognizer.
Do you have any ideas what might be causing the issue?
I have used the following code for years to add a right bar button item to the navigation bar, but for some unknown reason, this no longer works. It stopped working when I updated my app to have Scene support. I don't understand what is preventing this code from working.
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"viewDidLoad");
// Add a Share Button
UIBarButtonItem *shareButton;
shareButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(editProject:)];
self.navigationItem.rightBarButtonItem = shareButton;
self.navigationItem.rightBarButtonItem.tintColor = [UIColor blueColor];
}
-(void) editProject:(id)sender {
}
@end
To test this, I created a brand new test app that does nothing except for attempting to add this button. The autogenerated code gives you the following project and I simply modified the ViewController class as shown above:
What do I need to do differently to make the right bar button item to display? I know that I can add buttons using the storyboard that can be controlled via IBOutlets, but just want to know if its still possible to do this programmatically.
When I create a tab group for the sidebar on iPad, the title and disclosure triangle act like a single control. Every time I tap the section title, the disclosure triangle for that section activates and hides or exposes that section's children and actions.
I want the section title to behave like Photos, where tapping a section title just displays its view controller, and the disclosure triangle is a separate control that must be tapped to hide and show children and actions.
I did not see any delegate methods that would let me control this behavior. Is this supported?
Our iOS app, when running as an iOS App on Mac, crashes consistently under the following scenario:
1. Launch the app on an external display.
2. Minimize the app window.
3. Disconnect the external display.
The app crashes every time under these conditions. The crash log shows the following call stack:
*** Assertion failure in -[UINSWorkspace _maximumContentSizeForWindowOnScreen:], UINSWorkspace.m:401
-[UINSWorkspace _maximumContentSizeForWindowOnScreen:]: screen parameter should not be nil
(
0 CoreFoundation 0x000000018e841df0 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000018e306b60 objc_exception_throw + 88
2 Foundation 0x000000018fb6aa78 -[NSCalendarDate initWithCoder:] + 0
3 UIKitMacHelper 0x00000001a9a59110 -[UINSWorkspace _maximumContentSizeForWindowOnScreen:] + 184
4 UIKitMacHelper 0x00000001a9a3e748 -[UINSSceneViewController _usableScreenSizeWithSceneSize:shouldOverride:] + 412
5 UIKitMacHelper 0x00000001a9a3d55c -[UINSSceneViewController _effectiveScaleFactorForLayoutWithOverride:] + 88
6 UIKitMacHelper 0x00000001a9a3f3a8 -[UINSSceneViewController _updateZoomFactors] + 28
7 UIKitMacHelper 0x00000001a9a3f248 -[UINSSceneViewController _updateZoomFactorsAndDoLayout] + 24
8 UIKitMacHelper 0x00000001a9a3df80 -[UINSSceneViewController _doUpdates:] + 104
9 UIKitMacHelper 0x00000001a99ad460 -[UINSSceneViewController observeValueForKeyPath:ofObject:change:context:] + 176
10 Foundation 0x000000018facb0d8 -[NSKeyValueObservance observeValueForKeyPath:ofObject:change:context:] + 388
11 Foundation 0x000000018facb0d8 -[NSKeyValueObservance observeValueForKeyPath:ofObject:change:context:] + 388
12 Foundation 0x000000018fa8f7b4 NSKeyValueNotifyObserver + 252
13 Foundation 0x000000018fb3c560 NSKeyValueDidChange + 388
14 Foundation 0x00000001903149a0 NSKeyValueDidChangeWithPerThreadPendingNotifications + 160
15 AppKit 0x00000001924673d4 -[NSThemeFrame _didChangeContentLayoutRect] + 76
16 AppKit 0x000000019246521c -[NSWindow _oldPlaceWindow:fromServer:] + 744
)
It seems like the system attempts to access a screen object that is already nil after the external monitor is removed. This leads to an assertion failure in UINSWorkspace.
Is there any known workaround or update planned to address this issue?
Thank you.
I found the following statement on the site https://developer.apple.com/documentation/technotes/tn3187-migrating-to-the-uikit-scene-based-life-cycle:
"Soon, all UIKit based apps will be required to adopt the scene-based life-cycle, after which your app won’t launch if you don’t. While supporting multiple scenes is encouraged, only adoption of scene life-cycle is required."
Could you please clarify when exactly apps will no longer be able to launch if they do not adopt the scene-based life-cycle? I would like to confirm the deadline as the impact of this change is significant.
When minimize an app on extended display, then plug out the extended display, the app crashes.
These simple steps, make every iOS app running on Mac crash. Pls fix it.
I first applied a snapshot on the main thread like this:
var snapshot = NSDiffableDataSourceSnapshot<Section, MessageViewModel>()
snapshot.appendSections([.main])
snapshot.appendItems([], toSection: .main)
dataSource.applySnapshotUsingReloadData(snapshot)
After loading data, I applied the snapshot again using:
Task { @MainActor in
await dataSource.applySnapshotUsingReloadData(snapshot)
}
On an iPhone 13 mini, I received the following warning:
Warning: applying updates in a non-thread confined manner is dangerous and can lead to deadlocks. Please always submit updates either always on the main queue or always off the main queue
However, this warning did not appear when I ran the same code on an iPhone 16 Pro simulator.
Can anyone explain it to me? Thank you
Is there any possibility to update constraints for elements inside CollectionViewCell with button tap?
And where to put the code inside CellForItem or Inside CollectionViewCell Class File?
SwiftUI, using LPLinkView through UIViewRepresentable. Default behavior is a long press brings up a context menu and a popover to preview content. I want to replace that default long press behavior with my own custom screen. Adding a UILongPressGestureRecognizer didn't work.
Thanks!
When running UITests on tvOS, tabBar viewIdentifiers (UIKit) are no longer appearing. When you run the test, accessibility identifiers for tabs are no longer locatable but all other identifiers appears except for the tabs in the tabBar. In the stack trace of the debugger, if I print application, I can see all existing viewIdentifiers except those that were set for the tabs (on tvOS only).
If I force an action on the simulator after the app has launched and the view appeared ie move left or right, the identifiers appears (confirmed by stack trace) and the test will continue as expected. This was not an issue in the past (no code changes). I am not sure if this appeared after updating my mac to Sequoia. But for iOS, there is no issue. This bug only appears on tvOS and specifically the tabs.
Issue persists on:
Sequoia 15.4.1
Xcode 16.3
I'm looking for a reliable way to detect when the UIScreen of a UIView changes.
I'm developing a renderer SDK that provides a custom UIView subclass which performs OpenGL / Metal rendering, driven by a CADisplayLink. To support scenarios like screen mirroring or external displays on iPad, I need to ensure the CADisplayLink is created using the correct UIScreen, so the refresh rate is accurate.
Ideally, I’d like a way to be notified in the view itself (without requiring scene delegate integration) whenever self.window.windowScene.screen changes, even if trait values remain the same.
Any ideas or workarounds that work safely in production would be hugely appreciated!
Since iOS 13, the architecture is:
The app can have multiple UIScene instances (typically UIWindowScene).
Each UIWindowScene can have multiple UIWindows.
Each UIWindow hosts a view hierarchy.
To determine the correct UIScreen, I access self.window.windowScene.screen. If any component in that key path changes (window, windowScene, or screen), I need to detect it and react.
Here’s what I’ve tried so far:
Overriding willMoveToWindow: and didMoveToWindow:
This allows me to detect changes to window, but if windowScene (of the window) or screen (of the scene) changes directly, I get no notification.
Overriding traitCollectionDidChange:
This works if the screen change causes a difference in traits (e.g., a different displayScale), but fails if the old and new screens share the same traits (e.g., identical scale).
Listening to UIScene-related notifications
Notifications like UISceneDidDisconnectNotification or UISceneWillEnterForegroundNotification only indicate scene lifecycle events, not that a particular view or window has moved to a different screen.
Using KVO to observe self.window.windowScene.screen
I found WebKit does something similar, but in practice this causes crashes. The error message suggests that "windowScene" is not KVO-compliant, and my experience confirms it's not safe in production.
Apple's official guidance uses UIWindowSceneDelegate
In this example, Apple shows how to update a CADisplayLink in a UIWindowSceneDelegate's windowScene:didUpdateCoordinateSpace:interfaceOrientation:traitCollection:.
However, as an SDK provider delivering just a UIView, I don't have control over the host app's UIWindowSceneDelegate.
I see viewIsAppearing is available on iOS 13 and above, but when I use it, found that the function not be called below iOS 16
https://developer.apple.com/documentation/uikit/uiviewcontroller/4195485-viewisappearing
environment: Macos 14.4.1, Xcode 15.3
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let sub = SubViewController()
addChild(sub)
view.addSubview(sub.view)
}
@available(iOS 13.0, *)
override func viewIsAppearing(_ animated: Bool) {
super.viewIsAppearing(animated)
print("ViewController viewIsAppearing")
}
}
class SubViewController: UIViewController {
@available(iOS 13.0, *)
override func viewIsAppearing(_ animated: Bool) {
super.viewIsAppearing(animated)
print("SubViewController viewIsAppearing")
}
}
In iOS 15 devcice console log:
ViewController viewIsAppearing
iOS 16, 17:
ViewController viewIsAppearing
SubViewController viewIsAppearing
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
My app is a camera app that supports Picture-in-Picture (PiP) mode.
Normally, when the device rotates, I get the device orientation from iOS and use it to rotate the camera feed so that the preview stays correctly aligned.
However, when the app enters PiP mode, it is considered to be in the background, and I can no longer receive orientation updates from the system.
As a result, I can’t apply rotation corrections to the camera video in PiP mode.
Is there any way to retrieve device orientation while the app is in the background (specifically during PiP mode)?
Any guidance would be greatly appreciated.
Thank you!
I have a SwiftUI view that I have wrapped using UIHostingController for use within UIKit.
Requirement: Within the UIKit environment, I want to get all the subviews of this SwiftUI view and determine whether the images within those subviews have finished loading.
For UIKit views, we can use view.subviews to get all the subviews and do the check.
However, for SwiftUI views, I found that the view.subviews turns out to be an empty array, making it impossible to do further checks.
So the question is How can I get the subviews of a SwiftUI view?
For now, my app name length is more than 20 characters, so the iPhone app name displays without a space, and uses the range operator to ensure showing the rest in the next line.
Is it possible to show space and name with 2 lines?