Lately I am getting this error.
GenerativeModelsAvailability.Parameters: Initialized with invalid language code: en-GB. Expected to receive two-letter ISO 639 code. e.g. 'zh' or 'en'. Falling back to: en
Does anyone know what this is and how it can be resolved. The error does not crash the app
Swift
RSS for tagSwift is a powerful and intuitive programming language for Apple platforms and beyond.
Posts under Swift tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
I have an iOS app that I’m trying to update with Liquid Glass.
In this app, I’m using a tab bar, which works fine with Liquid Glass, but as soon as I enable the “Reduce Transparency” setting in dark mode, I get a strange effect: at launch, the tab bar appears correctly in dark mode, but after scrolling a bit in the view, it eventually switches to light mode 😅
At launch:
After a bit of scrolling:
I can’t figure out whether this is intended behavior from the framework or not (I don’t have this issue with other apps).
I can reproduce it in a project built from scratch, here is the code (don't forget to set dark mode to the device and activate the reduce transparency option in the accessibility menu):
struct ContentView: View {
var body: some View {
TabView {
ScrollView {
LazyVStack {
ForEach(0..<100) { _ in
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello world").foregroundStyle(.primary)
}
}
.padding()
}
.tabItem {
Label("Menu", systemImage: "list.dash")
}
}
}
}
Do you know if this is expected behavior? Or if there’s something that can be done about it?
Thanks,
I want to check whether a sandboxed application already has access permission to a specific URL.
Based on my investigation, the following FileManager method seems to be able to determine it:
FileManager.default.isReadableFile(atPath: fileURL.path)
However, the method name and description don't explicitly mention this use case, so I'm not confident there aren't any oversights.
Also, since this method takes a String path rather than a URL, I'd like to know if there's a more modern API available.
I want to use this information to decide whether to prompt the user about the Sandbox restriction in my AppKit-based app.
my Objective-C/Swift mixed project using cocoapods started experiencing persistent Swift code highlighting issues. Partial highlighting loss but when i use "compare code" function of the editor, It shows that everything works well on the compared code. rename also can not be used any more. does anyone know ho to fix this?
If the app is launched from LockedCameraCapture and if the settings button is tapped, I need to launch the main app.
CameraViewController:
func settingsButtonTapped() {
#if isLockedCameraCaptureExtension
//App is launched from Lock Screen
//Launch main app here...
#else
//App is launched from Home Screen
self.showSettings(animated: true)
#endif
}
In this document:
https://developer.apple.com/documentation/lockedcameracapture/creating-a-camera-experience-for-the-lock-screen
Apple asks you to use:
func launchApp(with session: LockedCameraCaptureSession, info: String) {
Task {
do {
let activity = NSUserActivityTypeLockedCameraCapture
activity.userInfo = [UserInfoKey: info]
try await session.openApplication(for: activity)
} catch {
StatusManager.displayError("Unable to open app - \(error.localizedDescription)")
}
}
}
However, the documentation states that this should be placed within the extension code - LockedCameraCapture. If I do that, how can I call that all the way down from the main app's CameraViewController?
Title
Why doesn’t this async function see external changes to an inout Bool in Release builds (but works in Debug)?
Body
I have a small helper function that waits for a Bool flag to become true with a timeout:
public func test(binding value: inout Bool, timeout maximum: Int) async throws {
var count = 0
while value == false {
count += 1
try await Task.sleep(nanoseconds: 0_100_000_000)
if value == true {
return
}
if count > (maximum * 10) {
return
}
}
}
I call like this:
var isVPNConnected = false
adapter.start(tunnelConfiguration: tunnelConfiguration) { [weak self] adapterError in
guard let self = self else { return }
if let adapterError = adapterError {
} else {
isVPNConnected = true
}
completionHandler(adapterError)
}
try await waitUntilTrue(binding: &isVPNConnected, timeout: 10)
What I expect:
test should keep looping until flag becomes true (or the timeout is hit).
When the second task sets flag = true, the first task should see that change and return.
What actually happens:
In Debug builds this behaves as expected: when the second task sets flag = true, the loop inside test eventually exits.
In Release builds the function often never sees the change and gets stuck until the timeout (or forever, depending on the code). It looks like the while value == false condition is using some cached value and never observes the external write.
So my questions are:
Is the compiler allowed to assume that value (the inout Bool) does not change inside the loop, even though there are await suspension points and another task is mutating the same variable?
Is this behavior officially “undefined” because I’m sharing a plain Bool across tasks without any synchronization (actors / locks / atomics), so the debug build just happens to work?
What is the correct / idiomatic way in Swift concurrency to implement this kind of “wait until flag becomes true with timeout” pattern?
Should I avoid inout here completely and use some other primitive (e.g. AsyncStream, CheckedContinuation, Actor, ManagedAtomic, etc.)?
Is there any way to force the compiler to re-read the Bool from memory each iteration, or is that the wrong way to think about it?
Environment (if it matters):
Swift: [fill in your Swift version]
Xcode: [fill in your Xcode version]
Target: iOS / macOS [fill in as needed]
Optimization: default Debug vs. Release settings
I’d like to understand why Debug vs Release behaves differently here, and what the recommended design is for this kind of async waiting logic in Swift.
Release notes of Xcode 26.2 https://developer.apple.com/documentation/xcode-release-notes/xcode-26_2-release-notes state that Swift 6.2.3 is shipped with it.
But when trying to check the Swift version with
#if swift(>= 6.2.3)
it returns false.
Running swiftc -version returns
swift-driver version: 1.127.14.1 Apple Swift version 6.2 (swiftlang-6.2.3.3.2 clang-1700.6.3.2)
As you can see, there is a mismatch between the marketing version "6.2" and the build version "6.2.3.3.2".
Being able to check for the 6.2.3 version is important for my team, because we are impatiently awaiting the change to the tabviewbottomaccessory modifier
https://developer.apple.com/documentation/swiftui/view/tabviewbottomaccessory%28isenabled:content:%29
so that it can be hidden when not needed. Without this fix we have the issue that the accessory shows even without content in iOS 26.1.
I just updated to Xcode 26 and some of my Swift Packages have been getting strange build errors that I have not been able to resolve. When I try to build my Swift Package in Xcode I get the following error
Module dependency cycle: 'UIKit.swiftmodule -> .swiftmodule -> SafariServices.swiftmodule -> UIKit.swiftmodule'
It seems like it is related to the change in Xcode 26 that states "Swift explicit modules will be the default mode for building all Swift targets". I see that you can disable this with the build setting SWIFT_ENABLE_EXPLICIT_MODULES=NO, but I don't see a way to do this in Package.swift, as you can't include value assignments like this .define("SWIFT_ENABLE_EXPLICIT_MODULES=NO").
Our private SPM repos use CI/CD and so we need to be able to build them independently of any use in a project. I would appreciate any help on fixing our Swift Package builds in Xcode 26, thanks!
Hi there! I'm making an app that stores data for the user's profile in SwiftData. I was originally going to use UserDefaults but I thought SwiftData could save Images natively but this is not true so I really could switch back to UserDefaults and save images as Data but I'd like to try to get this to work first. So essentially I have textfields and I save the values of them through a class allProfileData. Here's the code for that:
import SwiftData
import SwiftUI
@Model
class allProfileData {
var profileImageData: Data?
var email: String
var bio: String
var username: String
var profileImage: Image {
if let data = profileImageData,
let uiImage = UIImage(data: data) {
return Image(uiImage: uiImage)
} else {
return Image("DefaultProfile")
}
}
init(email:String, profileImageData: Data?, bio: String, username:String) {
self.profileImageData = profileImageData
self.email = email
self.bio = bio
self.username = username
}
}
To save this I create a new class (I think, I'm new) and save it through ModelContext
import SwiftUI
import SwiftData
struct CreateAccountView: View {
@Query var profiledata: [allProfileData]
@Environment(\.modelContext) private var modelContext
let newData = allProfileData(email: "", profileImageData: nil, bio: "", username: "")
var body: some View {
Button("Button") {
newData.email = email
modelContext.insert(newData)
try? modelContext.save()
print(newData.email)
}
}
}
To fetch the data, I originally thought that @Query would fetch that data but I saw that it fetches it asynchronously so I attempted to manually fetch it, but they both fetched nothing
import SwiftData
import SwiftUI
@Query var profiledata: [allProfileData]
@Environment(\.modelContext) private var modelContext
let fetchRequest = FetchDescriptor<allProfileData>()
let fetchedData = try? modelContext.fetch(fetchRequest)
print("Fetched count: \(fetchedData?.count ?? 0)")
if let imageData = profiledata.first?.profileImageData,
let uiImage = UIImage(data: imageData) {
profileImage = Image(uiImage: uiImage)
} else {
profileImage = Image("DefaultProfile")
}
No errors. Thanks in advance
In one of my apps, i am using .glassEffect(_:In) to add glass effect on various elements. The app always crushes when a UI element with glassEffect(_in:) modifier is being rendered. This only happens on device running iOS 26 public beta. I know this for certain because I connected the particular device to xcode and run the app on the device. When i comment out the glassEffect modifier, app doesn't crush.
Is it possible to check particular realeases with #available? If not, how should something like this be handled. Also how do i handle such os level erros without the app crushing. Thanks.
Crash in UIKeyboardStateManager when repeatedly switching text input focus in WKWebView (hybrid app)
We’re building a hybrid iOS app using Angular (web) rendered inside a WKWebView, hosted by a native Swift app.
Recently, we encountered a crash related to UIKeyboardStateManager in UIKit when switching between text inputs continuously within an Angular screen.
Scenario
The screen contains several text input fields.
A “Next” button focuses the next input field programmatically.
After about 61 continuous input field changes, the app crashes.
It seems like this may be related to UIKit’s internal keyboard management while switching focus rapidly inside a WebView.
crash stack:
Crashed: com.apple.main-thread
0 WebKit 0xfbdad0 <redacted> + 236
1 UIKitCore 0x10b0548 -[UITextInteractionSelectableInputDelegate _moveToStartOfLine:withHistory:] + 96
2 UIKitCore 0xd0fb38 -[UIKBInputDelegateManager _moveToStartOfLine:withHistory:] + 188
3 UIKitCore 0xa16174 __158-[_UIKeyboardStateManager handleMoveCursorToStartOfLine:beforePublicKeyCommands:testOnly:savedHistory:force:canHandleSelectableInputDelegateCommand:keyEvent:]_block_invoke + 52
4 UIKitCore 0xa36ae4 -[_UIKeyboardStateManager performBlockWithTextInputChangesIgnoredForNonMacOS:] + 48
5 UIKitCore 0xa160f0 -[_UIKeyboardStateManager handleMoveCursorToStartOfLine:beforePublicKeyCommands:testOnly:savedHistory:force:canHandleSelectableInputDelegateCommand:keyEvent:] + 440
6 UIKitCore 0xa07010 -[_UIKeyboardStateManager handleKeyCommand:repeatOkay:options:] + 5760
7 UIKitCore 0xa2fb64 -[_UIKeyboardStateManager _handleKeyCommandCommon:options:] + 76
8 UIKitCore 0xa2fb08 -[_UIKeyboardStateManager _handleKeyCommand:] + 20
9 UIKitCore 0xa30684 -[_UIKeyboardStateManager handleKeyEvent:executionContext:] + 2464
10 UIKitCore 0xa2f95c __42-[_UIKeyboardStateManager handleKeyEvent:]_block_invoke + 40
11 UIKitCore 0x4b9460 -[UIKeyboardTaskEntry execute:] + 208
12 UIKitCore 0x4b92f4 -[UIKeyboardTaskQueue continueExecutionOnMainThread] + 356
13 UIKitCore 0x4b8be0 -[UIKeyboardTaskQueue addTask:breadcrumb:] + 120
14 UIKitCore 0x4a9ed0 -[_UIKeyboardStateManager _setupDelegate:delegateSame:hardwareKeyboardStateChanged:endingInputSessionIdentifier:force:delayEndInputSession:] + 3388
15 UIKitCore 0xfa290 -[_UIKeyboardStateManager setDelegate:force:delayEndInputSession:] + 628
16 UIKitCore 0xf617c -[UIKeyboardSceneDelegate _reloadInputViewsForKeyWindowSceneResponder:force:fromBecomeFirstResponder:] + 1140
17 UIKitCore 0xf5c88 -[UIKeyboardSceneDelegate _reloadInputViewsForResponder:force:fromBecomeFirstResponder:] + 88
18 UIKitCore 0x4fe4ac -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] + 84
19 WebKit 0xfbe708 <redacted> + 100
20 WebKit 0xfbf594 <redacted> + 340
21 WebKit 0x8a33d8 <redacted> + 32
22 WebKit 0x8cee04 <redacted> + 144
23 WebKit 0x1c83f0 <redacted> + 22692
24 WebKit 0x73f40 <redacted> + 264
25 WebKit 0x162c7c <redacted> + 40
26 WebKit 0x1623b4 <redacted> + 1608
27 WebKit 0x73298 <redacted> + 268
28 WebKit 0x72e48 <redacted> + 660
29 JavaScriptCore 0xdb00 WTF::RunLoop::performWork() + 524
30 JavaScriptCore 0xd744 WTF::RunLoop::performWork(void*) + 36
31 CoreFoundation 0xf92c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
32 CoreFoundation 0xf744 __CFRunLoopDoSource0 + 172
33 CoreFoundation 0xf5a0 __CFRunLoopDoSources0 + 232
34 CoreFoundation 0xff20 __CFRunLoopRun + 840
35 CoreFoundation 0x11adc CFRunLoopRunSpecific + 572
36 GraphicsServices 0x1454 GSEventRunModal + 168
37 UIKitCore 0x135274 -[UIApplication _run] + 816
38 UIKitCore 0x100a28 UIApplicationMain + 336
39 APP1 0xa2ed0 main + 21 (AppDelegate.swift:21)
40 ??? 0x1aa889f08 (シンボルが不足しています)
From reviewing the crash log, it appears that the crash occurs inside UIKeyboardStateManager while handling keyboard or cursor updates.
Questions
Has anyone seen this specific crash pattern involving UIKeyboardStateManager?
Are there known UIKit or WebKit bugs related to UIKeyboardStateManager when continuously changing focus between text fields (especially in WKWebView)?
Any insights or workarounds would be greatly appreciated.
Thanks!
My app has been published by 2 months now I still I cant get Universal Links to work.
I checked a lot of docs as well as videos about setting up universal links. Everyone with clear steps:
Add the well-known json file to the server. Already validated by AASA web validator.
Add the Associated domain on project capabilities, with the Web page root only. Eg: applinks:example:com.
Install the app and trying clicking a link from notepad. Or instead make a long press to deploy contextual menu to see if my app is on the selectable options to open the link.
My app is not been open in any of my attempts and the console always trying to use safari.
I had a couple of screenshots of my testing. I really need help with this.
I'm experiencing an issue where my List selection (using EditButton) gets cleared when a confirmationDialog is presented, making it impossible to delete the selected items.
Environment:
Xcode 16.0.1
Swift 5
iOS 18 (targeting iOS 17+)
Issue Description:
When I select items in a List using EditButton and tap a delete button that shows a confirmationDialog, the selection is cleared as soon as the dialog appears. This prevents me from accessing the selected items to delete them.
Code:
State variables:
@State var itemsSelection = Set<Item>()
@State private var showDeleteConfirmation = false
List with selection:
List(currentItems, id: \.self, selection: $itemsSelection) { item in
NavigationLink(value: item) {
ItemListView(item: item)
}
}
.navigationDestination(for: Item.self) { item in
ItemViewDetail(item: item)
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
EditButton()
}
}
Delete button with confirmation:
Button {
if itemsSelection.count > 1 {
showDeleteConfirmation = true
} else {
deleteItemsSelected()
}
} label: {
Image(systemName: "trash.fill")
.font(.system(size: 12))
.foregroundStyle(Color.red)
}
.padding(8)
.confirmationDialog(
"Delete?",
isPresented: $showDeleteConfirmation,
titleVisibility: .visible
) {
Button("Delete", role: .destructive) {
deleteItemsSelected()
}
Button("Cancel", role: .cancel) {}
} message: {
Text("Going to delete: \(itemsSelection.count) items?")
}
Expected Behavior:
The selected items should remain selected when the confirmationDialog appears, allowing me to delete them after confirmation.
Actual Behavior:
As soon as showDeleteConfirmation becomes true and the dialog appears, itemsSelection becomes empty (count = 0), making it impossible to delete the selected items.
What I've Tried:
Moving the confirmationDialog to different view levels
Checking if this is related to the NavigationLink interaction
Has anyone encountered this issue? Is there a workaround to preserve the selection when showing a confirmation dialog?
Is there any particular reason why ASWebAuthenticationSession doesn't have support for async/await? (example below)
do {
let callbackURL = try await webAuthSession.start()
} catch {
// handle error
}
I'm curious if this style of integration doesn't exist for architectural reasons? Or is the legacy completion handler style preserved in order to prevent existing integrations from breaking?
Problem Description
(1) I am using ARKit in an iOS app to provide AR capabilities. Specifically, I'm trying to use the ARSession's captureHighResolutionFrame(using:) method to capture a high-resolution frame along with its corresponding depth data:
open func captureHighResolutionFrame(using photoSettings: AVCapturePhotoSettings?) async throws -> ARFrame
(2) However, when I attempt to do so, the call fails at runtime with the following error, which I captured from the Xcode debugger:
[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] settings.depthDataDeliveryEnabled must be NO if self.isDepthDataDeliveryEnabled is NO
Code Snippet Explanation
(1) ARConfig and ARSession Initialization
The following code configures the ARConfiguration and ARSession. A key part of this setup is setting the videoFormat to the one recommended for high-resolution frame capturing, as suggested by the documentation.
func start(imagesDirectory: URL, configuration: Configuration = Configuration()) {
// ... basic setup ...
let arConfig = ARWorldTrackingConfiguration()
arConfig.planeDetection = [.horizontal, .vertical]
// Enable various frame semantics for depth and segmentation
if ARWorldTrackingConfiguration.supportsFrameSemantics(.smoothedSceneDepth) {
arConfig.frameSemantics.insert(.smoothedSceneDepth)
}
if ARWorldTrackingConfiguration.supportsFrameSemantics(.sceneDepth) {
arConfig.frameSemantics.insert(.sceneDepth)
}
if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth) {
arConfig.frameSemantics.insert(.personSegmentationWithDepth)
}
// Set the recommended video format for high-resolution captures
if let videoFormat = ARWorldTrackingConfiguration.recommendedVideoFormatForHighResolutionFrameCapturing {
arConfig.videoFormat = videoFormat
print("Enabled: High-Resolution Frame Capturing by selecting recommended video format.")
}
arSession.run(arConfig, options: [.resetTracking, .removeExistingAnchors])
// ...
}
(2) Capturing the High-Resolution Frame
The code below is intended to manually trigger the capture of a high-resolution frame. The goal is to obtain both a high-resolution color image and its associated high-resolution depth data. To achieve this, I explicitly set the isDepthDataDeliveryEnabled property of the AVCapturePhotoSettings object to true.
func requestImageCapture() async {
// ... guard statements ...
print("Manual image capture requested.")
if #available(iOS 16.0, *) { // Assuming 16.0+ for this API
if let defaultSettings = arSession.configuration?.videoFormat.defaultPhotoSettings {
// Create a mutable copy from the default settings, as recommended
let photoSettings = AVCapturePhotoSettings(from: defaultSettings)
// Explicitly enable depth data delivery for this capture request
photoSettings.isDepthDataDeliveryEnabled = true
do {
let highResFrame = try await arSession.captureHighResolutionFrame(using: photoSettings)
print("Successfully captured a high-resolution frame.")
if let initialDepthData = highResFrame.capturedDepthData {
// Process depth data...
} else {
print("High-resolution frame was captured, but it contains no depth data.")
}
} catch {
// The exception is caught here
print("Error capturing high-resolution frame: \(error.localizedDescription)")
}
}
}
// ...
}
Issue Confirmation & Question
(1) Through debugging, I have confirmed the following behavior: If I call captureHighResolutionFrame without providing the photoSettings parameter, or if photoSettings.isDepthDataDeliveryEnabled is set to false, the method successfully returns a high-resolution ARFrame, but its capturedDepthData is nil.
(2) The error message clearly indicates that settings.depthDataDeliveryEnabled can only be true if the underlying AVCapturePhotoOutput instance's own isDepthDataDeliveryEnabled property is also true.
(3) However, within the context of ARKit and ARSession, I cannot find any public API that would allow me to explicitly access and configure the underlying AVCapturePhotoOutput instance that ARSession manages.
(4) My question is:
Is there a way to configure the ARSession's internal AVCapturePhotoOutput to enable its isDepthDataDeliveryEnabled property? Or, is simultaneously capturing a high-resolution frame and its associated depth data simply not a supported use case in the current ARKit framework?
In our app, there is a UIWindow makeKeyAndVisible crash, and for now, it appears once, crash stack:
the crash detail:
crash.txt
in the RCWindowSceneManager class's makeWindowKeyAndVisible method, we check and set a window's windowScene and makeKeyAndVisible:
public func makeWindowKeyAndVisible(_ window: UIWindow?) {
guard let window else {
return
}
if let currentWindowScene {
if window.windowScene == nil || window.windowScene != currentWindowScene {
window.windowScene = currentWindowScene
}
window.makeKeyAndVisible()
}
}
and I set a break point at a normal no crash flow, the stack is:
why it crash? and how we avoid this, thank you.
Starting with iOS 18, UITabBarController no longer updates tab bar item titles when localized strings are changed or reassigned at runtime.
This behavior worked correctly in iOS 17 and earlier, but in iOS 18 the tab bar titles remain unchanged until the app restarts or the view controller hierarchy is reset. This regression appears to be caused by internal UITabBarController optimizations introduced in iOS 18.
Steps to Reproduce
Create a UITabBarController with two or more tabs, each having a UITabBarItem with a title.
Localize the tab titles using NSLocalizedString():
tabBar.items?[0].title = NSLocalizedString("home_tab", comment: "")
tabBar.items?[1].title = NSLocalizedString("settings_tab", comment: "")
Run the app.
Change the app’s language at runtime (without restarting), or manually reassign the localized titles again:
tabBar.items?[0].title = NSLocalizedString("home_tab", comment: "")
tabBar.items?[1].title = NSLocalizedString("settings_tab", comment: "")
Observe that the tab bar titles do not update visually.
Hi everyone,
I’m building a full-screen Map (MapKit + SwiftUI) with persistent top/bottom chrome (menu buttons on top, session stats + map controls on bottom). I have three working implementations and I’d like guidance on which pattern Apple recommends long-term (gesture correctness, safe areas, Dynamic Island/home indicator, and future compatibility).
Version 1 — overlay(alignment:) on Map
Idea: Draw chrome using .overlay(alignment:) directly on the map and manage padding manually.
Map(position: $viewModel.previewMapCameraPosition, scope: mapScope) {
UserAnnotation {
UserLocationCourseMarkerView(angle: viewModel.userCourse - mapHeading)
}
}
.mapStyle(viewModel.mapType.mapStyle)
.mapControls {
MapUserLocationButton().mapControlVisibility(.hidden)
MapCompass().mapControlVisibility(.hidden)
MapPitchToggle().mapControlVisibility(.hidden)
MapScaleView().mapControlVisibility(.hidden)
}
.overlay(alignment: .top) { mapMenu } // manual padding inside
.overlay(alignment: .bottom) { bottomChrome } // manual padding inside
Version 2 — ZStack + .safeAreaPadding
Idea: Place the map at the back, then lay out top/bottom chrome in a VStack inside a ZStack, and use .safeAreaPadding(.all) so content respects safe areas.
ZStack(alignment: .top) {
Map(...).ignoresSafeArea()
VStack {
mapMenu
Spacer()
bottomChrome
}
.safeAreaPadding(.all)
}
Version 3 — .safeAreaInset on the Map
Idea: Make the map full-bleed and then reserve top/bottom space with safeAreaInset, letting SwiftUI manage insets
Map(...).ignoresSafeArea()
.mapStyle(viewModel.mapType.mapStyle)
.mapControls {
MapUserLocationButton().mapControlVisibility(.hidden)
MapCompass().mapControlVisibility(.hidden)
MapPitchToggle().mapControlVisibility(.hidden)
MapScaleView().mapControlVisibility(.hidden)
}
.safeAreaInset(edge: .top) { mapMenu } // manual padding inside
.safeAreaInset(edge: .bottom) { bottomChrome } // manual padding inside
Question
I noticed:
Safe-area / padding behavior
– Version 2 requires the least extra padding and seems to create a small but partial safe-area spacing automatically.
– Version 3 still needs roughly the same manual padding as Version 1, even though it uses safeAreaInset. Why doesn’t safeAreaInset fully handle that spacing?
Rotation crash (Metal)
When using Version 3 (safeAreaInset + ignoresSafeArea), rotating the device portrait↔landscape several times triggers a
Metal crash:
failed assertion 'The following Metal object is being destroyed while still required… CAMetalLayer Display Drawable'
The same crash can happen with Version 1, though less often. I haven’t tested it much with Version 2.
Is this a known issue or race condition between Map’s internal Metal rendering and view layout changes?
Expected behavior
What’s the intended or supported interaction between safeAreaInset, safeAreaPadding, and overlay when embedding persistent chrome inside a SwiftUI Map?
Should safeAreaInset normally remove the need for manual padding, or is that by design?
I’m building a custom input field using UITextField. When the user taps to focus the field and the text is long, the entire text becomes selected by default. This is the same behavior you can see in iOS Safari’s search field or the Messages app search field.
What I want: when the field becomes first responder, the caret should be placed at the end of the text (latest word), without selecting all the text.
Here’s the code that builds my text field:
public func makeTextField() -> UITextField {
let textField = UITextField()
textField.autocorrectionType = .no
textField.setContentCompressionResistancePriority(.required, for: .horizontal)
textField.setContentCompressionResistancePriority(.required, for: .vertical)
if #available(iOS 13.0, *) {
textField.smartInsertDeleteType = .no
}
textField.smartQuotesType = .no
textField.smartDashesType = .no
textField.autocapitalizationType = .none
textField.contentMode = .scaleToFill
if let font = attributes[.font] as? UIFont {
textField.font = font
}
if let color = attributes[.foregroundColor] as? UIColor {
textField.textColor = color
}
// Truncate long text at the head
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingHead
textField.defaultTextAttributes[.paragraphStyle] = paragraphStyle
textField.delegate = self
textField.backgroundColor = .clear
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
return textField
}
Entire text is selected when focusing the field if the text is long.
What I’ve tried
Forcing the caret to the end in textFieldDidBeginEditing:
func textFieldDidBeginEditing(_ textField: UITextField) {
let end = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: end, to: end)
}
Doing the same asynchronously (next runloop) to avoid the system overriding selection:
func textFieldDidBeginEditing(_ textField: UITextField) {
DispatchQueue.main.async {
let end = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: end, to: end)
}
}
Despite these, the system still selects all text on focus when the string is long/truncated at the head.
The following minimal snippet SEGFAULTS with SDK 26.0 and 26.1. Won't crash if I remove async from the enclosing function signature - but it's impractical in a real project.
import Metal
import MetalPerformanceShaders
let SEED = UInt64(0x0)
typealias T = Float16
/* Why ran in async context? Because global GPU object,
and async makeMTLFunction,
and async makeMTLComputePipelineState.
Nevertheless, can trigger the bug without using global
@MainActor
let myGPU = MyGPU()
*/
@main
struct CMDLine {
static func main() async {
let ptr = UnsafeMutablePointer<T>.allocate(capacity: 0)
async let future: Void = randomFillOnGPU(ptr, count: 0)
print("Main thread is playing around")
await future
print("Successfully reached the end.")
}
static func randomFillOnGPU(_ buf: UnsafeMutablePointer<T>, count destbufcount: Int) async {
// let (device, queue) = await (myGPU.device, myGPU.commandqueue)
let myGPU = MyGPU()
let (device, queue) = (myGPU.device, myGPU.commandqueue)
// Init MTLBuffer, async let makeFunction, makeComputePipelineState, etc.
let tempDataType = MPSDataType.uInt32
let randfiller = MPSMatrixRandomMTGP32(device: device, destinationDataType: tempDataType, seed: Int(bitPattern:UInt(SEED)))
print("randomFillOnGPU: successfully created MPSMatrixRandom.")
// try await computePipelineState
// ^ Crashes before this could return
// Or in this minimal case, after randomFillOnGPU() returns
// make encoder, set pso, dispatch, commit...
}
}
actor MyGPU {
let device : MTLDevice
let commandqueue : MTLCommandQueue
init() {
guard let dev: MTLDevice = MPSGetPreferredDevice(.skipRemovable),
let cq = dev.makeCommandQueue(),
dev.supportsFamily(.apple6) || dev.supportsFamily(.mac2)
else { print("Unable to get Metal Device! Exiting"); exit(EX_UNAVAILABLE) }
print("Selected device: \(String(format: "%llX", dev.registryID))")
self.device = dev
self.commandqueue = cq
print("myGPU: initialization complete.")
}
}
See FB20916929. Apparently objc autorelease pool is releasing the wrong address during context switch (across suspension points). I wonder why such obvious case has not been caught before.