Hello Apple forum !
I spotted a weird behaviour with LazyVStack in a ScrollView. I understand that it loads its views only once upon appearance unlinke VStack that loads everything in one shot.
What I noticed also, it seems to reload its views sometimes when scrolling back up to earlier loaded views. The thing is, it isn't always the case.
struct LazyVStackTest: View {
var body: some View {
ScrollView {
LazyVStack {
ForEach(0..<1000, id: \.self) { _ in
// if true {
MyText()
// }
}
}
}
}
struct MyText: View {
var body: some View {
let _ = Self._printChanges()
HStack {
Text("hello")
}
}
}
}
If we consider the code above on XCode 26 beta 7 on an iOS 26 or iOS 18.2 simulator.
Scroll to the bottom : you'll see one "LazyVStackTest.MyText: @self changed" for each row.
Then scroll back up to the top, we'll see again the same message printed multiple times.
--> So I gather from this that LazyVStack not only loads lazily but also removes old rows from memory & recreates them upon reappearance.
What I don't get however is that if you uncomment the "if true" statement, you won't see the reloading happening. And I have absolutely no clue as to why 😅
If someone could help shed some light on this weird behaviour, it would be greatly appreciated ^^
PS : the issue is also present with XCode 16.2 but at a deeper lever (ex: if we embed another custom View "MyText2" inside "MyText", the reloading is in "MyText2" & not "MyText")
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
Environment
iOS Version: iOS 26 Beta 8
Xcode Version: iOS 26 Beta 6
StoreKit: StoreKit 2
Description
When calling AppStore.showManageSubscriptions(in:) on iOS 26 beta, I'm experiencing an unusual presentation behavior that wasn't present in earlier versions.
An empty/blank view appears first
Then the actual StoreKit manage subscriptions sheet appears on top
When dismissing the StoreKit sheet, it closes properly
But then I have to dismiss the empty view underneath as well
This creates a poor user experience showing double sheets.
Code Sample
@MainActor
func showManageSubscriptions() {
guard let scene = UIApplication.shared.connectedScenes
.first(where: { $0 is UIWindowScene }) as? UIWindowScene else {
return
}
Task {
do {
try await AppStore.showManageSubscriptions(in: scene)
} catch {
// Handle error
}
}
}
Expected Behavior
The StoreKit manage subscriptions sheet should present directly without any intermediate empty view, as it did in previous iOS versions.
Actual Behavior
An empty view layer appears between my app and the StoreKit sheet, requiring users to dismiss twice.
Questions
Is anyone else experiencing this issue with iOS 26 beta?
Is this a known beta issue that will be addressed?
Are there any recommended workarounds while waiting for a fix?
Already filed a feedback in case this is a bug, but posting here in case I'm doing something wrong?
I'd like the search field to automatically be displayed with the keyboard up when the view appears. This sample code works in iOS 18, but it does not work in iOS 26 beta 7
I also tried adding a delay to setting searchIsFocused = true but that did not help
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink(destination: ListView()) {
Label("Go to list", systemImage: "list.bullet")
}
}
.ignoresSafeArea()
}
}
struct ListView: View {
@State private var searchText: String = ""
@State private var searchIsPresented: Bool = false
@FocusState private var searchIsFocused: Bool
var body: some View {
ScrollView {
Text("Test")
}
.searchable(text: $searchText, isPresented: $searchIsPresented, placement: .automatic, prompt: "Search")
.searchFocused($searchIsFocused)
.onAppear {
searchIsFocused = true
}
}
}
I'm building a SwiftUI app for iPad using a NavigationSplitView as the navigation root. Below is a simplified version of the app's navigation. There are a Home Page and a Settings Page, each with its own NavigationStack. The page that appears in the detail column depends on the sidebar's selection value. The issue I'm facing is that when I navigate deeply into the Home Page's NavigationStack (e.g., to a Home Page Child view), switch to the Settings Page, and then switch back to the Home Page, the Home Page's navigation path has been reset to [] and the previous state is lost. The same issue occurs if I navigate deeply into the Settings Page (e.g., to a Settings Page Child view), switch to the Home Page, and then return to the Settings Page: the navigation state for the Settings Page is lost, and it reverts to the root of the NavigationStack. Why is this happening and how can I fix it so that switching pages in the sidebar doesn't reset the NavigationStack of each individual page in the detail column? Thank you.
struct ContentView: View {
@State var selection: String?
@State var firstPath = [String]()
@State var secondPath = [String]()
var body: some View {
NavigationSplitView {
List(selection: $selection) {
Text("Home")
.tag("home")
Text("Settings")
.tag("settings")
}
} detail: {
if selection == "home" {
HomePage(path: $firstPath)
} else {
SettingsPage(path: $secondPath)
}
}
}
}
struct HomePage: View {
@Binding var path: [String]
var body: some View {
NavigationStack(path: $path) {
NavigationLink("Home Page", value: "Home")
.navigationDestination(for: String.self) { _ in
Text("Home Page Child")
}
}
}
}
struct SettingsPage: View {
@Binding var path: [String]
var body: some View {
NavigationStack(path: $path) {
NavigationLink("Settings Page", value: "Settings")
.navigationDestination(for: String.self) { _ in
Text("Settings Page Child")
}
}
}
}
#Preview {
ContentView()
}
I have an NSSplitViewController with three columns:
sidebar
full-height content view with NSScrollView/NSTableView
detail view.
There's no (visible) titlebar and no toolbar.
This layout has worked fine for years, but in Tahoe an unwanted overlay (~30-50px high) appears at the top of any column containing a scroll view with table content. Xcode suggests it's an NSScrollPocket.
My research suggests it...
Only affects columns with NSScrollView
Plain NSView columns are unaffected
Overlay height varies (~50px or ~30px depending on how I mess with title / toolbar settings)
Disabling titlebar/toolbar settings reduces but doesn't eliminate the overlay
The overlay obscures content and there doesn't appear to be any API
to control its visibility. Is this intended behavior, and if so, is
there a way to disable it for applications that don't need this UI
element?
If it helps visualise the desired result, the app is https://indigostack.app
Any guidance would be appreciated!
Topic:
UI Frameworks
SubTopic:
AppKit
I am trying to get integer input by using textfield. However, I noticed that if I changed the binding variable as optional with an initial value of null, the textfield would not work. I would like to keep it as null initially because I want the placeholder to show text before the input, and if the int variable starts with any valid value, the text would not be shown. Is there a way to fix things here?
struct TextFieldNumberInputView: View {
@Binding var intVariable: Int?
@State var isEditing: Bool = false
@State var placeholderText: String
@State var number: Int = 0
var body: some View {
VStack(alignment: .leading, spacing: 2){
TextField(placeholderText, value: $number, formatter: NumberFormatter()){
}
.textFieldStyle(InputTextFieldStyle())
.keyboardType(.numberPad)
.onReceive(Just(number)) {_ in
print("number pad being editing")
if isEditing == false && intVariable != nil {
isEditing = true
print("number is being edited")
} else if isEditing == true && intVariable != nil{
isEditing = false
}
}
Text(placeholderText)
.font(.caption2)
.foregroundColor(isEditing ? Color(.systemGray3):Color.clear)
.padding(.horizontal)
.padding(.horizontal, 12)
}.onTapGesture {
print("number pad being tapped, intVariable \(intVariable), \(number)")
if number != nil {
print("checking number")
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)
}
}
}
}
Anytime I have 1 item, then add another, the app crashes with the following error:
Swift/IntegerTypes.swift:8835: Fatal error: Double value cannot be converted to Int because it is either infinite or NaN
I'm not working with Int values though, so I'm not sure why this is happening. It's also not point me towards any specific line. I've printed out all of the values being used for the chart and none of them are showing as infinite or NaN.
The data being used is created in a View.
@State private var pieChartData: [PieChartDataPoint] = []
Then in the onAppear and onChange its gets loaded using the following function:
func getPieChartDataPoints() -> [PieChartDataPoint] {
self.map({ PieChartDataPoint(label: $0.name, value: $0.monthlyAmount()) })
}
That's an extension on a SwiftData model type I have called Recurring.
@Model
final class Recurring {
var id = UUID()
enum Kind: String, CaseIterable, Codable {
case income = "Income"
case bill = "Bill"
func plural() -> String {
switch self {
case .income:
"Income"
case .bill:
"Bills"
}
}
}
enum Frequency: String, CaseIterable, Codable, Identifiable {
var id: Frequency { self }
case weekly = "Weekly"
case biweekly = "Biweekly"
case monthly = "Monthly"
case quarterly = "Quarterly"
case annually = "Annually"
}
var name: String = ""
var kind: Kind = Kind.income
var frequency: Frequency = Frequency.biweekly
var amount: Double = 0
init(name: String, kind: Kind, frequency: Frequency, amount: Double) {
self.name = name
self.kind = kind
self.frequency = frequency
self.amount = amount
}
func amount(from cycle: Cycle) -> Double {
switch cycle {
case .weekly:
monthlyAmount() * 12 / 52
case .biweekly:
monthlyAmount() * 12 / 26
case .monthly:
monthlyAmount()
}
}
func monthlyAmount() -> Double {
switch frequency {
case .weekly:
amount * 52 / 12
case .biweekly:
amount * 26 / 12
case .monthly:
amount
case .quarterly:
amount * 4 / 12
case .annually:
amount / 12
}
}
}
Here is the DataPoint structure.
struct PieChartDataPoint: Identifiable, Equatable {
var id = UUID()
var label: String
var value: Double
}
Finally here is the chart.
Chart(sorted, content: { dataPoint in
SectorMark(
angle: .value(dataPoint.label, getValue(from: dataPoint)),
innerRadius: 50,
angularInset: 5
)
.foregroundStyle(by: .value("Label", dataPoint.label))
.cornerRadius(10)
.opacity(getSectorMarkOpacity(for: dataPoint))
})
.scaledToFill()
.chartLegend(.hidden)
.chartAngleSelection(value: $chartSelection)
.onChange(of: chartSelection, checkSelection)
For testing purposes, I have removed all of the modifiers and only had a simple SectorMark in the Chart, however, that was still crashing.
Does anyone know why this is happening?
I want to be able to disable all liquid glass effects from my Navigation bar, and it's bar buttons. But I still want to be able to have the liquid glass effect on my UITabbar.
Is there a way to disable glass effects from navbar and still retain them all for tabbars using UIKit?
Hello !
I manage to displays tips on tvOS no issue.
However when I want to add actions, they are not visible. Is there something specific to do here ?
I just provided the actions attributes to my tips.
The documentation does not say anything more.
Thanks!
I created a Radar for this FB14766095, but thought I would add it here for extra visibility, or if anyone else had any thoughts on the issue.
Basic Information
Please provide a descriptive title for your feedback:
iOS 18 hit testing functionality differs from iOS 17
What type of feedback are you reporting?
Incorrect/Unexpected Behavior
Description:
Please describe the issue and what steps we can take to reproduce it:
We have an issue in iOS 18 Beta 6 where hit testing functionality differs from the expected functionality in iOS 17.5.1 and previous versions of iOS.
iOS 17: When a sheet is presented, the hit-testing logic considers subviews of the root view, meaning the rootView itself is rarely the hit view.
iOS 18: When a sheet is presented, the hit-testing logic changes, sometimes considering the rootView itself as the hit view.
Code:
import SwiftUI
struct ContentView: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View One")
Button {
isPresentingView.toggle()
} label: {
Text("Present View Two")
}
}
.padding()
.sheet(isPresented: $isPresentingView) {
ContentViewTwo()
}
}
}
#Preview {
ContentView()
}
struct ContentViewTwo: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View Two")
}
.padding()
}
}
extension UIWindow {
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
/// Get view from superclass.
guard let hitView = super.hitTest(point, with: event) else { return nil }
print("RPTEST rootViewController = ", rootViewController.hashValue)
print("RPTEST rootViewController?.view = ", rootViewController?.view.hashValue)
print("RPTEST hitView = ", hitView.hashValue)
if let rootView = rootViewController?.view {
print("RPTEST rootViewController's view memory address: \(Unmanaged.passUnretained(rootView).toOpaque())")
print("RPTEST hitView memory address: \(Unmanaged.passUnretained(hitView).toOpaque())")
print("RPTEST Are they equal? \(rootView == hitView)")
}
/// If the returned view is the `UIHostingController`'s view, ignore.
print("MTEST: hitTest rootViewController?.view == hitView", rootViewController?.view == hitView)
print("MTEST: -")
return hitView
}
}
Looking at the print statements from the provided sample project:
iOS 17 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 17 dismiss from presented view:
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 18 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103342080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x000000010333e3c0
RPTEST Are they equal? true
MTEST: hitTest rootViewController?.view == hitView true
You can see here ☝️ that in iOS 18 the views have the same memory address on the second call and are evaluated to be the same. This differs from iOS 17.
iOS 18 dismiss
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
The question I want to ask:
Is this an intended change, meaning the current functionality in iOS 18 is expected?
Or is this a bug and it's something that needs to be fixed?
As a user, I would expect that the hit testing functionality would remain the same from iOS 17 to iOS 18.
Thank you for your time.
According to the UtilityWindow documentation:
• They receive FocusedValues from the focused main scene in an application, similar to commands in the main menu, which can be used to display information on the active content as the user focuses on different scenes.
This makes me think that any UtilityWindow, even across Scenes, should always receive @FocusedValues from the currently focused window of any scene.
However, the following code doesn't quite work:
@Observable class Info: Identifiable {
let id = UUID()
}
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView() // Inside, it uses .focusedSceneValue(info)
}
UtilityWindow("Test") {
UtilityWindowContent()
}
}
}
struct UtilityWindowContent: View {
@FocusedValue(Info.self) var info
var body: some View {
Text(info?.id ?? "<nil>") // This always shows "<nil>"
}
}
Here's some annotated screenshots of what's happening in a project:
Menu bar commands do work with the same setup:
As a workaround, attempting to use @FocusedValue in the App struct works, but as a result, the value appears to instantiate multiple times in the background, and they re-instantiate with every focus change.
The @FocusedValue variable gets the correct instance, but it's needlessly initializing others in the background.
This is on macOS 26.0 Tahoe Beta 8 (25A5349a).
Summary
In a SwiftUI drag-and-drop flow, the only robust way I’ve found to detect cancellation (user drops outside any destination) is to rely on the NSItemProvider created in .onDrag and run cleanup when it’s deallocated, via a custom onEnded callback tied to its lifecycle.
On iOS 26, the provider appears to be deallocated immediately after .onDrag returns (unless I keep a strong reference), so a deinit/onEnded-based cancel hook fires right away and no longer reflects the true end of the drag session.
I’d like to know:
1. Is there a supported, reliable way to detect when a drag ends outside any drop target so I can cancel and restore the source row?
2. Is the iOS 26 NSItemProvider deallocation timing a bug/regression or intended behavior?
Minimal SwiftUI Repro
This example shows:
• creating a custom NSItemProvider subclass with an onEnded closure
• retaining it to avoid immediate dealloc (behavior change on iOS 26)
• using performDrop to mark the drag as finished
import SwiftUI
import UniformTypeIdentifiers
final class DragProvider: NSItemProvider {
var onEnded: (() -> Void)?
deinit {
// Historically: called when the system drag session ended (drop or cancel).
// On iOS 26: can fire immediately after .onDrag returns unless the provider is retained.
onEnded?()
}
}
struct ContentView: View {
struct Item: Identifiable, Equatable { let id = UUID(); let title: String }
@State private var pool: [Item] = (1...4).map { .init(title: "Option \($0)") }
@State private var picked: [Item] = []
@State private var dragged: Item?
@State private var dropFinished: Bool = true
@State private var activeProvider: DragProvider? // Retain to avoid immediate dealloc
private let dragType: UTType = .plainText
var body: some View {
HStack(spacing: 24) {
// Destination list (accepts drops)
VStack(alignment: .leading, spacing: 8) {
Text("Picked").bold()
VStack(spacing: 8) {
ForEach(picked) { item in
row(item)
}
}
.padding()
.background(RoundedRectangle(cornerRadius: 8).strokeBorder(.quaternary))
.onDrop(of: [dragType], delegate: Dropper(
picked: $picked,
pool: $pool,
dragged: $dragged,
dropFinished: $dropFinished,
activeProvider: $activeProvider
))
}
.frame(maxWidth: .infinity, alignment: .topLeading)
// Source list (draggable)
VStack(alignment: .leading, spacing: 8) {
Text("Pool").bold()
VStack(spacing: 8) {
ForEach(pool) { item in
row(item)
.onDrag {
startDrag(item)
return makeProvider(for: item)
} preview: {
row(item).opacity(0.9).frame(width: 200, height: 44)
}
.overlay(
RoundedRectangle(cornerRadius: 8)
.fill(item == dragged ? Color(.systemBackground) : .clear) // keep space
)
}
}
.padding()
.background(RoundedRectangle(cornerRadius: 8).strokeBorder(.quaternary))
}
.frame(maxWidth: .infinity, alignment: .topLeading)
}
.padding()
}
private func row(_ item: Item) -> some View {
RoundedRectangle(cornerRadius: 8)
.strokeBorder(.secondary)
.frame(height: 44)
.overlay(
HStack { Text(item.title); Spacer(); Image(systemName: "line.3.horizontal") }
.padding(.horizontal, 12)
)
}
// MARK: Drag setup
private func startDrag(_ item: Item) {
dragged = item
dropFinished = false
}
private func makeProvider(for item: Item) -> NSItemProvider {
let provider = DragProvider(object: item.id.uuidString as NSString)
// NOTE: If we DO NOT retain this provider on iOS 26,
// its deinit can run immediately (onEnded fires too early).
activeProvider = provider
provider.onEnded = { [weak self] in
// Intended: run when system drag session ends (drop or cancel).
// Observed on iOS 26: may run too early unless retained;
// if retained, we lose a reliable "session ended" signal here.
DispatchQueue.main.async {
guard let self else { return }
if let d = self.dragged, self.dropFinished == false {
// Treat as cancel: restore the source item
if !self.pool.contains(d) { self.pool.append(d) }
self.picked.removeAll { $0 == d }
}
self.dragged = nil
self.dropFinished = true
self.activeProvider = nil
}
}
return provider
}
// MARK: DropDelegate
private struct Dropper: DropDelegate {
@Binding var picked: [Item]
@Binding var pool: [Item]
@Binding var dragged: Item?
@Binding var dropFinished: Bool
@Binding var activeProvider: DragProvider?
func validateDrop(info: DropInfo) -> Bool { dragged != nil }
func performDrop(info: DropInfo) -> Bool {
guard let item = dragged else { return false }
if let idx = pool.firstIndex(of: item) { pool.remove(at: idx) }
picked.append(item)
// Mark drag as finished so provider.onEnded won’t treat it as cancel
dropFinished = true
dragged = nil
activeProvider = nil
return true
}
}
}
Questions
Is there a documented, source-side callback (or best practice) to know the drag session ended without any performDrop so we can cancel and restore the item?
Has the NSItemProvider deallocation timing (for the object returned from .onDrag) changed intentionally on iOS 26? If so, what’s the recommended replacement signal?
Is there a SwiftUI-native event to observe the end of a drag session that doesn’t depend on the provider’s lifecycle?
Hi, i'm using the PasteButton component to paste content from clipboard. On the docs it says that the PasteButton will handle internally permissions and will not present the prompt. But in my case seems to be not true.
I removed all the occurrencies of
UIPasteboard.general.string
since i read that this will cause the prompt to appear. Also as you can see on the code below i'm not doing fancy or weird things, even with the base component this behaviour is still there.
PasteButton(payloadType: String.self) { strings in
if let first = strings.first {
print("clipboard text: \(first)")
}
}
I can see other apps using this paste button without asking for permissions every time, but i cannot see any issue in my code.
Hello,
I am experiencing a crash in a SwiftUI app.
It happens when I place multiple views inside a ScrollView.
The crash occurs only on a physical device (it does not reproduce in the Simulator).
It happens during runtime, seemingly while SwiftUI is updating or laying out the view hierarchy.
I have not been able to determine the exact cause.
I am attaching a text file with the entire backtrace from LLDB.
swiftui_crash_backtrace
Is this a known SwiftUI issue?
Any recommendations on how to further investigate or work around it?
Any help or suggestions would be appreciated.
Xcode 16.3 / iOS 18.6.2
Thank you!
Hello,
I’ve encountered what seems to be a bug with the keyboard dismissal animation on iOS 26.0 Beta (25A5349a), Xcode Version 26.0 beta 5 (17A5295f).
When dismissing the keyboard from a SwiftUI TextField using @FocusState, the keyboard does not animate downward as expected. Instead, it instantly disappears, which feels jarring and inconsistent with system behavior.
I am attaching a short video demonstrating the issue. Below is the minimal reproducible code sample:
//
// ContentView.swift
// TestingKeyboardDismissal
//
// Created by Sasha Morozov on 27/08/25.
//
import SwiftUI
struct ContentView: View {
@State private var text: String = ""
@FocusState private var isFocused: Bool
var body: some View {
ZStack {
Color.clear.ignoresSafeArea()
VStack(spacing: 20) {
TextField("Enter text here...", text: $text)
.textFieldStyle(.roundedBorder)
.focused($isFocused)
.padding(.horizontal)
HStack {
Button("Focus") { isFocused = true }
.buttonStyle(.borderedProminent)
Button("Unfocus") { isFocused = false }
.buttonStyle(.bordered)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.padding()
}
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
#Preview {
ContentView()
}
Steps to reproduce:
Run** the app on iOS 26.0 beta 5 (17A5295f).
Tap Focus → keyboard appears as expected.
Tap Unfocus → keyboard disappears instantly without the usual slide-down animation.
Expected result:
Keyboard should animate smoothly downwards when dismissed.
Actual result:
Keyboard instantly vanishes without animation.
p.s. we should be really able to upload videos here for demostration
Description:
1. 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.
2. 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.
Demo App Crash : https://drive.google.com/file/d/19PV02wzOJhc2DYI6kAe-uxHuR1Qg15Bu/view?usp=sharing
Apple Files App Crash: https://drive.google.com/file/d/1flHKuU_xaxHSzRun1dYlh8w7nBPJZeRb/view?usp=sharing
I’m trying to understand the exact role of the return value in the UITextFieldDelegate method textFieldShouldReturn(_:).
From my experiments in Xcode, I observed:
Returning true vs false does not seem to cause any visible difference (e.g., the keyboard does not automatically dismiss either way).
I know that in shouldChangeCharactersIn returning true allows the system to insert the character, and returning false prevents it. That’s clear.
For textFieldShouldReturn, my current understanding is that returning true means “let the OS handle the Return press,” and returning false means “I’ll handle it myself.”
My confusion: what is it that the OS actually does when it “handles” the Return press?
Does UIKit do anything beyond calling this delegate method?
If the system is supposed to dismiss the keyboard when returning true, why doesn’t it happen automatically?
I’d appreciate clarification on the expected use of this return value — specifically, what default behavior the system performs (if any) when we return true.
Thanks!
On testing my app with tvOS 18, I have noticed the Siri Remote back button no longer provides system-provided behavior when interacting with tab bar controller pages. Instead of moving focus back to the tab bar when pressed, the back button will close the app, as if the Home button was pressed. This occurs both on device and in the Simulator.
Create tvOS project with a tab bar controller.
Create pages/tabs which contain focusable items (ie. buttons)
Scroll down to any focusable item (ie. a button or UICollectionView cell)
Hit the Siri Remote back button. See expect behavior below:
Expected behavior: System-provided behavior should move focus back to the tab bar at the top of the screen.
Actual results: App is closed and user is taken back to the Home Screen.
Has anyone else noticed this behavior?
(NSString*)getClienttime
{
NSDate* currentDate = [NSDate date];
NSDateFormatter* dateformatter = [[NSDateFormatter alloc] init];
dateformatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:8*3600];
dateformatter.locale= [NSLocale systemLocale];
[dateformatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [dateformatter stringFromDate:currentDate]?:@"";
}
the info of crash
1
libicucore.A.dylib
icu::UnicodeString::copyFrom(icu::UnicodeString const&, signed char) (in libicucore.A.dylib) + 36
2
libicucore.A.dylib
icu::DecimalFormatSymbols::operator=(icu::DecimalFormatSymbols const&) (in libicucore.A.dylib) + 64
3
libicucore.A.dylib
icu::DecimalFormatSymbols::operator=(icu::DecimalFormatSymbols const&) (in libicucore.A.dylib) + 64
4
libicucore.A.dylib
icu::DecimalFormat::DecimalFormat(icu::DecimalFormat const&) (in libicucore.A.dylib) + 188
5
libicucore.A.dylib
icu::DecimalFormat::clone() const (in libicucore.A.dylib) + 48
6
libicucore.A.dylib
icu::NumberFormat::createInstance(icu::Locale const&, UNumberFormatStyle, UErrorCode&) (in libicucore.A.dylib) + 188
7
libicucore.A.dylib
icu::SimpleDateFormat::initialize(icu::Locale const&, UErrorCode&) (in libicucore.A.dylib) + 580
8
libicucore.A.dylib
icu::SimpleDateFormat::SimpleDateFormat(icu::Locale const&, UErrorCode&) (in libicucore.A.dylib) + 332
9
libicucore.A.dylib
icu::DateFormat::create(icu::DateFormat::EStyle, icu::DateFormat::EStyle, icu::Locale const&) (in libicucore.A.dylib) + 264
10
libicucore.A.dylib
udat_open (in libicucore.A.dylib) + 396
11
CoreFoundation
__cficu_udat_open (in CoreFoundation) + 72
12
CoreFoundation
__ResetUDateFormat (in CoreFoundation) + 508
13
CoreFoundation
__CreateCFDateFormatter (in CoreFoundation) + 324
14
Foundation
-[NSDateFormatter _regenerateFormatter] (in Foundation) + 204
15
Foundation
-[NSDateFormatter stringForObjectValue:] (in Foundation) + 104
16
ABC
+[JMAContext getClienttime] (in DadaStaff) (JMAContext.m:73)
Topic:
UI Frameworks
SubTopic:
UIKit
Note: in this post I discuss sceneDidEnterBackground/WillResignActive but I assume any guidance provided would also apply to the now deprecated applicationDidEnterBackground/applicationWillResignActive and SwiftUI's ScenePhase (please call out if that's not the case!).
A common pattern for applications with sensitive user data (banking, health, private journals, etc.) is to obsurce content in the app switcher. Different apps appear to implement this in two common patterns. Either immediately upon becoming inactive (near immediately upon moving to task switcher) or only upon becoming backgrounded (not until you've gone to another app or back to the home screen).
I’d like to make sure we’re aligned with Apple’s intended best practices and am wondering if an anti-pattern of using sceneWillResignActive(_:) may be becoming popularized and has minor user experience inconviences (jarring transitions to the App Switcher/Control Center/Notification Center and when the system presents alerts.)
Our applications current implementation uses sceneDidEnterBackground(_:) to obscure sensitive elements instead of sceneWillResignActive(_:), based on the recomendations from tech note QA1838 and the documentation in sceneDidEnterBackground(_:)
... Shortly after this method [sceneWillEnterBackground] returns, UIKit takes a snapshot of your scene’s interface for display in the app switcher. Make sure your interface doesn’t contain sensitive user information.
Both QA1838 and the sceneDidEnterBackground documentation seem to indicate backgrounding is the appropriate event to respond to for this pattern but I am wondering if "to display in the app switcher" may be causing confusion since your app can also display in the app switcher upon becoming inactive and if some guidance could be added to sceneWillResignActive that it is not nesscary to obsure content during this state (if that is true).
In our testing, apps seems to continue to play any in-progress animations when entering the app switcher from the application (inactive state), suggesting no snapshot capture. We also discovered that it appears sceneWillResignActive not always be called (it usually is) but occasionally you can swipe into the app switcher without it being called but that sceneDidEnterBackground is triggered more consistently.
It appears the Wallet app behaves as I'd expect with sceneDidEnterBackground on card details screens as well (ejecting you to the card preview if you switch apps) but will keep you on the card details screen upon becoming inactive.
Questions:
Is sceneDidEnterBackground(_:) still Apple’s recommended place to obscure sensitive content, or should apps handle this earlier (e.g. on inactive)?
Would it actually be recommended against using sceneWillResignActive active given it seems to not be gauranteed to be called?
Ask:
Provide an updated version of QA1838 to solidfy the extrapolation of applicationDidEnterBackground -> sceneDidEnterBackground
Consider adding explicit guidance to sceneWillResignActive documentation