Has anyone gotten custom buttons to work on top of tvOS Map()? I've tried many variations of
FocusState
focusSection
.defaultFocus()
and as soon as the map appears at startup the buttons never get focus again. They are on a ZStack over the map. I could post code but truthfully nothing works for me. I'm wondering if anyone has successfully put focusable buttons on top of the map view.
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
Where from and how does an NSRulerView get its magnification from? I am not using the automatic magnification by NSScrollView but using my own mechanism. How do I relay the zoom factor to NSRulerView?
I want to hide some sensitive information when app is visible in the list of process on iOS.
I observed that privacySensitive() modifier is not working for my app in case when view is embedded in UIHostingController.
I works correctly for pure SwiftUI app.
Can someone confirm this?, any workaround to make it working for my case.
Description:
When initiating the print flow via UIPrintInteractionController, and no printer is initially connected, iOS displays all possible paper sizes in the paper selection UI. However, if a printer connects in the background after this view is shown, the list of paper sizes does not automatically refresh to reflect only the options supported by the connected printer.
If the user selects an incompatible paper size (one not supported by the printer that has just connected), the app crashes due to an invalid configuration.
Steps to Reproduce:
Launch the app and navigate to the print functionality.
Tap the Print button to invoke UIPrintInteractionController.
At this point, no printer is yet connected. iOS displays all available paper sizes.
While the paper selection UI is visible, the AirPrint-compatible printer connects in the background.
Without dismissing the controller, the user selects a paper size (e.g., one that is not supported by the printer).
The app crashes.
Expected Result: App should not crash
Once the printer becomes available (connected in the background), the paper size options should refresh automatically.
The list should be filtered to only include sizes that are compatible with the connected printer.
This prevents the user from selecting an invalid option, avoiding crashes.
Actual Result: App crashes
The paper size list remains unfiltered.
The user can still select unsupported paper sizes.
Selecting an incompatible option causes the app to crash, due to a mismatch between UI selection and printer capability.
Topic:
UI Frameworks
SubTopic:
UIKit
Hi,
I have the following swiftUI code:
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.colorEffect(ShaderLibrary.AlphaConvert())
and the following shader:
[[ stitchable ]] half4 AlphaConvert(float2 position, half4 currentColor) {
return half4(currentColor.r>0.5,currentColor.r<=0.5,0,(currentColor.r>0.5));
}
I am loading a full-res image from my photo library (24MP)... The image initially displays fine, with portions of the image red, and the rest black (due to alpha blending)... However, after rotating the device, I get an image that is a combination of red&green... Note, that the green pixels from the shader have alpha 0, hence, should never be seen. Is there something special that needs to be done on orientation changes so that the shader works fine?
We are developing an MacOS app from our iOS app using MacCatalyst.
If I press long on the app icon on the Dock, a list of recent files appears.
If I tap one one of these files nothing happens. I would expect the scene delegate function:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
would be called but it is not. Can somebody maybe explain what I am missing here?
The list of recent files also appears in the Menu under File > Open recent files. There I can tap on a file and it it is opened correctly using the scene delegate method mentioned above.
The files can also be opened with the app using the Finder, so the associated file types with the app are correct.
I have an application named "XY" that has been launched in several countries. Now, I intend to launch it in Turkey, but we are facing legal issues preventing us from using "XY" as the app's display name. Following the documentation, I localized the app's display name to "ZX" for both Turkish and English (Turkey). However, when users change their device settings, they do not see an option for English (Turkey) language selection. I assumed that for Turkish users, English (Turkey) would be the default language, but this is not the case. Could someone please assist me in resolving this issue? I've investigated options for localizing the display name based on region, but it seems that this functionality isn't feasible on iOS. In contrast, it's relatively straightforward to achieve on Android platforms.
I'm attempting to write a macOS version of https://stackoverflow.com/a/74935849/2178159.
From my understanding, I should be able to set the menu property of an NSResponder and it will automatically show on right click.
I've tried a couple things:
A: set menu on an NSHostingController's view - when I do this and right or ctrl click, nothing happens.
B: set menu on NSHostingController directly - when I do this I get a crash Abstract method -[NSResponder setMenu:] called from class _TtGC7SwiftUI19NSHostingControllerGVS_21_ViewModifier_...__. Subclasses must override
C: manually call NSMenu.popup in a custom subclasses of NSHostingController or NSView's rightMouseDown method - nothing happens.
extension View {
func contextMenu(menu: NSMenu) -> some View {
modifier(ContextMenuViewModifier(menu: menu))
}
}
struct ContextMenuViewModifier: ViewModifier {
let menu: NSMenu
func body(content: Content) -> some View {
Interaction_UI(
view: { content },
menu: menu
)
.fixedSize()
}
}
private struct Interaction_UI<Content: View>: NSViewRepresentable {
typealias NSViewType = NSView
@ViewBuilder var view: Content
let menu: NSMenu
func makeNSView(context: Context) -> NSView {
let v = NSHostingController(rootView: view)
// option A - no effect
v.view.menu = menu
// option B - crash
v.menu = menu
return v.view
}
func updateNSView(_ nsView: NSViewType, context: Context) {
// part of option A
nsView.menu = menu
}
}
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
I have a view with some buttons, and add 2 gestures using simultaneously. My app works well when built with XCode less than 16, or run on iOS less than 18.0.
Example code is below:
VStack(spacing: 0) {
Button {
print("button tapped")
} label: {
Rectangle()
.foregroundColor(.red)
}
.frame(height: 100)
}
.gesture(
DragGesture(minimumDistance: 0)
.onEnded { value in
print("single tap")
}
.simultaneously(with:
TapGesture(count: 2).onEnded {
print("double tap")
}
)
)
.frame(width: 200, height: 200)
.border(Color.purple)
I expect the action on Button should be recognized and print out button tapped, but only single tap and double tap are recognized
I have written a calculator app. Its main window is a UIView subclass that usually receives user input from the touchscreen, tapping on a virtual keyboard (not the standard pop-up keyboard).
I recently added hardware keyboard support. In order to receive key events, I implemented canBecomeFirstResponder and made it always return YES, and I'm calling becomeFirstResponder whenever the main window becomes active, and resignFirstResponder when it becomes inactive.
This is working fine except for one scenario: when running the app on an iPad, together with another app, using Split View or Slide Over, and the other app has keyboard focus on a text field, my app doesn't receive keyboard events, even when it's the foreground app. I have to go into the other app, and tap somewhere outside a text field, and then return to my app, before my app is getting key events again.
If the user taps on an actual text field in my app, it gets focus just fine, of course, but apparently my UIView calling becomeFirstResponder is not enough to take away the focus from the other app.
Is there a way to steal the focus from another app's text field in this scenario?
Topic:
UI Frameworks
SubTopic:
UIKit
So I am looking to use a custom NSWindow application (so I can implement some enhanced resizing/dragging behavior which is only possible overriding NSWindow).
The problem is my whole application is currently SwiftUI-based (see the project here: https://github.com/msdrigg/Roam/blob/50a2a641aa5f2fccb4382e14dbb410c1679d8b0c/Roam/RoamApp.swift).
I know there is a way to make this work by dropping my @main SwiftUI app and replacing it with a SwiftUI root view hosted in a standard AppKit root app, but that feels like I'm going backwards.
Is there another way to get access (and override) the root NSWindow for a SwiftUI app?
I'm trying to switch to UIKit's document lifecycle due to serious bugs with SwiftUI's version.
However I'm noticing the template project from Xcode isn't compatible with Swift 6 (I already migrated my app to Swift 6.). To reproduce:
File -> New -> Project
Select "Document App" under iOS
Set "Interface: UIKit"
In Build Settings, change Swift Language Version to Swift 6
Run app
Tap "Create Document"
Observe: crash in _dispatch_assert_queue_fail
Does anyone know of a work around other than downgrading to Swift 5?
I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work.
Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself.
I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be.
Is there a better strategy to leverage here?
final class MyViewController: NSViewController {
@IBAction func buttonClicked(_ sender: NSButton) {
if let presenter = window?.contentViewController {
presenter.presentAsSheet(NSHostingController(rootView: SettingsView()))
}
}
}
struct SettingsView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
Button("Cancel", role: .cancel) {
dismiss() // This call does not dismiss the sheet.
} .keyboardShortcut(.cancelAction)
}
}
}
Thank you.
macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
WKWebView cannot load and display HTTP image resources
Topic:
UI Frameworks
SubTopic:
UIKit
I have a SwiftUI project which has the following hierarchy:
IOSSceneDelegate (App target) - depends on EntryPoint and Presentation static libs.
Presentation (Static library) - Depends on EntryPoint static lib. Contains UI related logic and updates the UI after querying the data layer.
EntryPoint (Static library) - Contains the entry point, AppDelegate (for its lifecycle aspects) etc.
I've only listed the relevant targets here.
SceneDelegate was initially present in EntryPoint library, because the AppDelegate references it when a scene is created.
public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Set the SceneDelegate dynamically
let sceneConfig: UISceneConfiguration = UISceneConfiguration(name: "mainWindow", sessionRole: connectingSceneSession.role)
sceneConfig.delegateClass = SceneDelegate.self
return sceneConfig
}
The intent is to move the SceneDelegate to the Presentation library.
When moved, the EntryPoint library fails to compile because it's referencing the SceneDelegate (as shown above).
To remove this reference, I tried to set up the SceneDelegate in the old way - In the info.plist file, mention a SceneConfiguration and set the SceneDelegate in Presentation.
// In the Info.plist file
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>Presentation.SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
// In the AppDelegate
public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Refer to a static UISceneconfiguration listed in the info.plist file
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
As shown above, the Presentation.SceneDelegate is referred in the Info.plist file and the reference is removed from the AppDelegate (in EntryPoint library).
The app target compiles, but when I run it, the SceneDelegate is not invoked. None of the methods from the SceneDelegate (scene(_:willConnectTo:options:), sceneDidDisconnect(_:), sceneDidEnterBackground(_:) etc.) are invoked. I only get the AppDelegate logs.
It seems like the Configuration is ignored because it was incorrect. Any thoughts? Is it possible to move the SceneDelegate in this situation?
The SwiftUI Playground code below demonstrates that a .jpeg image can be read and written to the iOS file system. While, a.png image can only be read; the writing request appears to be ignored. Can anyone please tell me how to code to save a .png image using SwiftUI to the iOS file system.
Code:
import SwiftUI
import UniformTypeIdentifiers
/*
(Copied from Playground 'Help' menu popup.)
UIImage Summary
An object that manages image data in your app.
You use image objects to represent image data of all kinds, and the UIImage class is capable of managing data for all image formats supported by the underlying platform. Image objects are immutable, so you always create them from existing image data, such as an image file on disk or programmatically created image data. An image object may contain a single image or a sequence of images for use in an animation.
You can use image objects in several different ways:
Assign an image to a UIImageView object to display the image in your interface.
Use an image to customize system controls such as buttons, sliders, and segmented controls.
Draw an image directly into a view or other graphics context.
Pass an image to other APIs that might require image data.
Although image objects support all platform-native image formats, it’s recommended that you use PNG or JPEG files for most images in your app. Image objects are optimized for reading and displaying both formats, and those formats offer better performance than most other image formats. Because the PNG format is lossless, it’s especially recommended for the images you use in your app’s interface.
Declaration
class UIImage : NSObject
UIImage Class Reference
*/
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ImageFileDoc: FileDocument {
static var readableContentTypes = [UTType.jpeg, UTType.png]
static var writableContentTypes = [UTType.jpeg, UTType.png]
var someUIImage: UIImage = UIImage()
init(initialImage: UIImage = UIImage()) {
self.someUIImage = initialImage
}
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents,
let some = UIImage(data: data)
else {
throw CocoaError(.fileReadCorruptFile)
}
self.someUIImage = some
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
switch configuration.contentType {
case UTType.png:
if let data = self.someUIImage.pngData() {
return .init(regularFileWithContents: data)
}
case UTType.jpeg:
if let data = self.someUIImage.jpegData(compressionQuality: 1.0) {
return .init(regularFileWithContents: data)
}
default:
break
}
throw CocoaError(.fileWriteUnknown)
}
}
struct ContentView: View {
@State private var showingExporterPNG = false
@State private var showingExporterJPG = false
@State private var showingImporter = false
@State var message = "Hello, World!"
@State var document: ImageFileDoc = ImageFileDoc()
@State var documentExtension = ""
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text(message)
Button("export") {
if documentExtension == "png" {
message += ", showingExporterPNG is true."
showingExporterPNG = true
}
if documentExtension == "jpeg" {
message += ", showingExporterJPG is true."
showingExporterJPG = true
}
}
.padding(20)
.border(.white, width: 2.0)
.disabled(documentExtension == "")
Button("import") {
showingImporter = true
}
.padding(20)
.border(.white, width: 2.0)
Image(uiImage: document.someUIImage)
.resizable()
.padding()
.frame(width: 300, height: 300)
}
// exporter .png
.fileExporter(isPresented: $showingExporterPNG, document: document, contentType: UTType.png) { result in
switch result {
case .success(let url):
message += ", .\(documentExtension) Saved to \(url.lastPathComponent)"
case .failure(let error):
message += ", Some error saving file: " + error.localizedDescription
}
}
// exporter .jpeg
.fileExporter(isPresented: $showingExporterJPG, document: document, contentType: UTType.jpeg) { result in
switch result {
case .success(let url):
message += ", .\(documentExtension) Saved to \(url.lastPathComponent)"
case .failure(let error):
message += ", Some error saving file: " + error.localizedDescription
}
}
// importer
.fileImporter(isPresented: $showingImporter, allowedContentTypes: [.png, .jpeg]) { result in
switch result {
case .failure(let error):
message += ", Some error reading file: " + error.localizedDescription
case .success(let url):
let gotAccess = url.startAccessingSecurityScopedResource()
if !gotAccess {
message += ", Unable to Access \(url.lastPathComponent)"
return
}
documentExtension = url.pathExtension
guard let fileContents = try? Data(contentsOf: url)
else {
message += ",\n\nUnable to read file: \(url.lastPathComponent)\n\n"
url.stopAccessingSecurityScopedResource()
return
}
url.stopAccessingSecurityScopedResource()
message += ", Read file: \(url.lastPathComponent)"
message += ", path extension is '\(documentExtension)'."
if let uiImage = UIImage(data: fileContents) {
self.document.someUIImage = uiImage
}else{
message += ", File Content is not an Image."
}
}
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags:
Files and Storage
Developer Tools
iPad
Swift Playground
There are two issues about SFSafariViewController.
After rotate from landscape to portrait,
The topAnchor is destroyed.
The specified bar tint color and control tint color are invalidated.(Returns to system color)
Regarding the second issue, I’ve found a temporary workaround.
Override the viewWillTransition(to:with:) and keep it empty. Don't call super.viewWillTransition(to:with:).
Since UIKit is not open source, I don’t know the exact cause, but I found something that could be the key to the issue. So, I reported it to Apple Feedback Assistant. You can check the details and the sample project in the GitHub repository below.
https://github.com/ueunli/SafariViewer
Hi.
I know to know which window gets hardware keyboard events (such as shortcut key) currently on iPad.
Until iPadOS 15.0, UIApplication.shared.keyWindow, which was deprecated on iPadOS 13.0 and didBecomeKeyNotification/didResignKeyNotification.
But after iPadOS 15.0, a keyWindow is managed by UIScene, not by UIApplication.
Each scene of my app always has just one window.
For my purpose, checking deprecated UIApplication.shared.keyWindow is still effective but didBecomeKeyNotification and didResignKeyNotification don't work because they are fired when a change happens only inside the scene.
So my questions are,
What is the new alternative of UIApplication.shared.keyWindow?
I know a wrong hack like
UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first?.windows.filter { $0.isKeyWindow }.first
does not work since the order of connectedScenes is not related with getting hardware keyboard events.
What are the new alternatives of didBecomeKeyNotification/didResignKeyNotification which work on inter-scene?
The second question is more crucial.
Because about the first question, I can still use deprecated UIApplication.shared.keyWindow.
Thanks.
Problem Description
We are developing a app for iOS and iPadOS that involves extensive custom drawing of paths, shapes, texts, etc. To improve drawing and rendering speed, we use CARenderer to generate cached images (CGImage) on a background thread. We adopted this approach based on this StackOverflow post: https://stackoverflow.com/a/75497329/9202699.
However, we are experiencing frequent crashes in our production environment that we can hardly reproduce in our development environment. Despite months of debugging and seeking support from DTS and the Apple Feedback platform, we have not been able to fully resolve this issue. Our recent crash reports indicate that the crashes occur when calling CATransaction.commit().
We suspect that CATransaction may not be functioning properly outside the main thread. However, based on feedback from the Apple Feedback platform, we were advised to use CATransaction.begin() and CATransaction.commit() on a background thread.
If anyone has any insights, we would greatly appreciate it.
Code Sample
The line CATransaction.commit() is causing the crash: [EXC_BREAKPOINT: com.apple.root.****-qos.cooperative]
private let transactionLock = NSLock() // to ensure one transaction at a time
private let device = MTLCreateSystemDefaultDevice()!
@inline(never)
static func drawOnCGImageWithCARenderer(
layerRect: CGRect,
itemsToDraw: [ItemsToDraw]
)
-> CGImage? {
// We have encapsulated everything related to CALayer and its
// associated creations and manipulations within CATransaction
// as suggested by engineers from Apple Feedback Portal.
transactionLock.lock()
CATransaction.begin()
// Create the root layer.
let layer = CALayer()
layer.bounds = layerRect
layer.masksToBounds = true
// Add one sublayer for each item to draw
itemsToDraw.forEach { item in
// We have thousands or hundred thousands of drawing items to add.
// Each drawing item may produce a CALayer, CAShapeLayer or CATextLayer.
// This is also why we want to utilise CARenderer to leverage GPU rendering.
layer.addSublayer(
item.createCALayerOrCATextLayerOrCAShapeLayer()
)
}
// Create MTLTexture and CARenderer.
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(
pixelFormat: .rgba8Unorm,
width: Int(layer.frame.size.width),
height: Int(layer.frame.size.height),
mipmapped: false
)
textureDescriptor.usage = [MTLTextureUsage.shaderRead, .shaderWrite, .renderTarget]
let texture = device.makeTexture(descriptor: textureDescriptor)!
let renderer = CARenderer(mtlTexture: texture)
renderer.bounds = layer.frame
renderer.layer = layer.self
/* ********************************************************* */
// From our crash report, this is where the crash happens.
CATransaction.commit()
/* ********************************************************* */
transactionLock.unlock()
// Rendering layers onto MTLTexture using CARenderer.
renderer.beginFrame(atTime: 0, timeStamp: nil)
renderer.render()
renderer.endFrame()
// Draw MTLTexture onto image.
guard
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB),
let ciImage = CIImage(mtlTexture: texture, options: [.colorSpace: colorSpace]) else {
return nil
}
// Convert CIImage to CGImage.
let context = CIContext()
return context.createCGImage(ciImage, from: ciImage.extent)
}