This is a problem from Beta 1, but since there is no fix yet in Beta 3, I'd like to raise it.
The app is built with macCatalyst, and we have pretty simple tab bar controller setup:
viewController = UITabBarController()
viewController.tabBar.tintColor = .buttonForegroundColor
importWorkflow = ModelImportWorkflow(
userInterfaceIdiom: userInterfaceIdiom, workspace: workspace)
mergeWorkflow = ModelMergeWorkflow(userInterfaceIdiom: userInterfaceIdiom, workspace: workspace)
listWorkflow = ModelListWorkflow(workspace: workspace, userInterfaceIdiom: userInterfaceIdiom)
viewController.viewControllers = [
listWorkflow.viewControllable, importWorkflow.viewControllable,
mergeWorkflow.viewControllable,
]
viewController.modalPresentationStyle = .formSheet
We don't do any customizations on the tab bar and in Beta 3 (26.2), there is no way to found the tab bar (attached a user reported image).
Please advise what's the course of action. Thanks.
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
Created
Dear Apple Developer Support,
I am writing to seek guidance regarding App Clips launch source differentiation in our restaurant application.
Background:
Our restaurant uses QR codes that are permanently associated with specific table numbers. These QR codes successfully launch our App Clip and pass the table information via NSUserActivity with NSUserActivityTypeBrowsingWeb.
Current Issue:
We are facing a significant challenge in distinguishing between different launch sources:
Camera Scan/URL Launch: When customers scan the QR code using the native camera or tap a URL, the App Clip launches with the correct table information.
App Library Launch: When customers launch the App Clip from the App Library, it restores the previous NSUserActivity with potentially outdated table information.
The Problem:
Since we cannot determine whether the App Clip was launched from the camera/URL or from the App Library, we cannot reliably decide whether to use the table information carried by userActivity. This causes customers to be directed to incorrect tables when launching from the App Library.
What We've Tried:
We have attempted various approaches to differentiate the launch source:
Checking for AppClipActivationPayload - but it exists in both scenarios
Examining UIApplicationLaunchOptionsKey and UISceneConnectionOptions
Analyzing URL parameters and timestamps
Implementing custom state management
However, none of these methods provide reliable differentiation between camera scan launches and App Library restorations.
Question:
Is there any official API or recommended approach to programmatically determine if an App Clip was launched:
From a camera scan/URL tap (fresh launch), OR
From the App Library (state restoration)
Any guidance on how to properly handle this scenario would be greatly appreciated, as it significantly impacts the user experience in our restaurant ordering system.
Thank you for your time and assistance.
Best regards
Trying to make a sheet-like view that attaches at the bottom to another view so I'd like to have only the top two corners rounded.
This works for a blurred effect:
let glassView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))
glassView.layer.cornerRadius = 20
glassView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
glassView.layer.masksToBounds = true
but if I try to use the iOS 26 UIGlassEffect, all 4 corners become rounded:
let glassView = UIVisualEffectView(effect: UIGlassEffect())
glassView.layer.cornerRadius = 20
glassView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
glassView.layer.masksToBounds = true
[Submitted as FB21078443]
When using .matchedTransitionSource with .navigationTransition(.zoom), swiping back from the left edge to return from a detail view causes the source item to disappear once the transition finishes. It’s only a visual issue—the item is still there and can be tapped to open again.
This doesn’t happen when using the Back button; only the swipe-back gesture triggers it. Also, it only reproduces on a physical device, not in Simulator.
SYSTEM INFO
Xcode 26.1.1 (17B100)
macOS 26.1 (25B78)
iOS 26.1 (23B85)
iOS 26.2 (23C5044b)
REPRO STEPS
Run the code below on a physical device, tap an image, then swipe from the left edge to dismiss the detail view.
ACTUAL
The image zooms back to its origin, then disappears once the animation settles.
EXPECTED
The image card remains visible.
SCREENSHOTS
CODE
import SwiftUI
struct Item: Identifiable, Hashable {
let id = UUID()
let imageName: String
let title: String
}
struct ContentView: View {
@Namespace private var namespace
let items = [
Item(imageName: "SampleImage", title: "Sample Card 1"),
Item(imageName: "SampleImage2", title: "Sample Card 2")
]
var body: some View {
NavigationStack {
ScrollView {
VStack(spacing: 16) {
ForEach(items) { item in
NavigationLink(value: item) {
CardView(item: item)
.matchedTransitionSource(id: item.id, in: namespace)
}
.buttonStyle(.plain)
}
}
.padding()
}
.navigationTitle("Zoom Transition Issue")
.navigationSubtitle("Tap image, then swipe back from left edge")
.navigationDestination(for: Item.self) { item in
DetailView(item: item, namespace: namespace)
.navigationTransition(.zoom(sourceID: item.id, in: namespace))
}
}
}
}
struct CardView: View {
let item: Item
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .bottom) {
Image(item.imageName)
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}
.frame(height: 200)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
struct DetailView: View {
let item: Item
let namespace: Namespace.ID
var body: some View {
Image(item.imageName)
.resizable()
.scaledToFill()
.clipped()
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi, I faced with the issue on iOS 26.1 with PHPickerViewController. After first selection I save assetIdentifier of PHPickerResult for images.
next time I open the picker I expect to have the images selected based on assetIdentifier
Code:
var config = PHPickerConfiguration(photoLibrary: .shared())
config.selectionLimit = 10
config.filter = .images
config.preselectedAssetIdentifiers = images.compactMap(\.assetID)
let picker = PHPickerViewController(configuration: config)
picker.delegate = self
present(picker, animated: true)
But on iOS 26.1 they aren't selected. On lower iOS version all works fine.
Does anybody faced with similar issue?
Topic:
UI Frameworks
SubTopic:
UIKit
Hi,
I am trying to add a custom (create) button next to the automatic "toggle sidebar" button in a NavigationSplitView.
When the sidebar is collapsed that button should be displayed in a group with that automatic toggle button.
Basically I want exact the same behaviour as in the Apple "Reminders" App.
How could I archive that?
Thanks for your help :-)
Jan
I have checked the sample project from the documentation page
and noticed there is an issue with image/images not being preselected. The issue happens on iOS 26.1 and above (checked iOS 26.2 beta).
I couldn't find any change to the PhotoPicker in the documentation.
Topic:
UI Frameworks
SubTopic:
UIKit
Description of the current implementation:
A section, UIView, has been added to UITableView. This section is a UICollectionView that displays an array of images. Each UICollectionViewCell is an image displayed via a UIImageView.
Issue:
When UITableView is scrolled vertically, the section with the image collection flickers.
Attempts made to solve the problem:
if #available(iOS 26.0, *) {
tableView.bottomEdgeEffect.isHidden = true
tableView.topEdgeEffect.isHidden = true
tableView.leftEdgeEffect.isHidden = true
tableView.rightEdgeEffect.isHidden = true
} else {
// Fallback on earlier versions
}
This helped with a similar issue. I tried it on UITableView and UICollectionView, but it didn't work.
I’m working on a SwiftUI screen where I need to hide a header when the user scrolls down and show it again when the user scrolls up. I’m currently using a ScrollView combined with GeometryReader to detect scroll offset changes and update state variables like isScrolling or isScrollingDown.
The issue is that the behavior is inconsistent. When I scroll down, the header hides correctly, but when I scroll back up, the header often doesn’t appear again even though the offset is changing. Sometimes the header comes back with a delay, and other times it never appears at all. Along with this, I’m also seeing noticeable UI lag whenever I try to calculate content height or read multiple geometry values inside the ScrollView. It looks like the frequent state updates inside the scroll offset tracking are causing layout recalculations and frame drops.
I’ve tried placing the header in different positions (inside a ZStack aligned to the top, inside the VStack above the ScrollView, and with transitions like .push(from: .top)), but the result is still the same: smooth scrolling breaks, and the header doesn’t reliably animate back when scrolling upward.
What I’m looking for is a minimal and efficient approach to detect scroll direction and trigger the header hide/show animation without causing performance issues or recomputing expensive layout values. Any guidance or a simplified pattern that works well for dynamic headers in SwiftUI would be very helpful.
if isScrolling {
headerStackView() //Includes Navigation Bar
.transition(
.asymmetric(
insertion: .push(from: .top),
removal: .push(from: .bottom)
)
)
}
GeometryReader { outer in
let outerHeight = outer.size.height
ScrollView(.vertical) {
VStack {
content() // Heavy view + contains its own ScrollView
}
.background {
GeometryReader { proxy in
let contentHeight = proxy.size.height
let minY = max(
min(0, proxy.frame(in: .named("ScrollView")).minY),
outerHeight - contentHeight
)
if #available(iOS 17.0, *) {
Color.clear
.onChange(of: minY) { oldVal, newVal in
// Scroll direction detection
if (isScrolling && newVal < oldVal) ||
(!isScrolling && newVal > oldVal) {
isScrolling = newVal > oldVal
}
}
}
}
}
}
.coordinateSpace(name: "ScrollView")
}
.padding(.top, 1)
After updating from iOS 26 to iOS 26.1, all my transparent system elements (i.e. UITabBar, UIBarButtonItem) started rendering with a dark background tint. In iOS 26 the same configuration looked fully transparent / glassy.
The strange part is that the tint only appears in normal UIViewControllers. In UITableViewController the tab bar still looks correct and transparent, even on iOS 26.1.
I am using the same appearance code as before:
func setupTabBarAppearance() {
guard let tabBar = tabBarController?.tabBar else { return }
if #available(iOS 26.0, *) {
let appearance = UITabBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = .clear
appearance.backgroundEffect = nil
appearance.shadowColor = .clear
tabBar.standardAppearance = appearance
tabBar.scrollEdgeAppearance = appearance
tabBar.isTranslucent = true
tabBar.backgroundColor = .clear
tabBar.barTintColor = .clear
} else {
tabBar.isTranslucent = true
tabBar.backgroundImage = UIImage()
tabBar.shadowImage = UIImage()
tabBar.backgroundColor = .clear
}
}
I tried removing backgroundEffect, forcing .clear colors, using configureWithDefaultBackground, changing edgesForExtendedLayout, extendedLayoutIncludesOpaqueBars, etc. I noticed that if I change Liquid Glass in iOS 26 settings from Clear to Tinted, then I get a black tint everywhere and the interface becomes consistent, but not the way I want.
Nothing removes the new dark tint in iOS 26.1. Is this an intentional change in iOS 26.1, a bug, or is there a new way to make the tab bar fully transparent again?
Hello. I'm making an app with several different views. I'm trying to switch views using a button but I can't seem to figure out how. I know Navigation Links work, but my case doesn't work. The reasons for this are because I need to run other code when they click the button and I don't want them to be able to navigate back (to CustomizationView/CreateAccountView). I know that you can hide the back button but my problem with that is the fact that i will be navigating to a view (MainView) that will also have navigation buttons in it, so if i'm thinking correctly, the button will be hidden but when they press the next navigationlink (in MainView) it will show again and then they can go back (to CustomizationView/CreateAccountView). i don't want them to go back because they will be navigating from a login/account view that wont be needed anymore. I'm currently using .fullScreenCover() and it works fine except for performance (I'm assuming). here's the code:
import SwiftUI
struct CustomizationView: View {
@State private var showMain = false
var body: some View {
Button("Done") {
// some more code here
showMain = true
}
.fullScreenCover(isPresented: $showMain) {
MainView()
}
}
}
here's a visual for the navigation if you're confused
I’m trying to implement smooth zoom and drag interactions for an image on watchOS—similar to the Photos app. DTS recommended using digitalCrownRotation + scaleEffect in SwiftUI, and ChatGPT also suggests a similar approach. However, the experience still isn’t as smooth or polished as the Photos app.
Before I commit fully to this direction, I want to confirm:
1. Is SwiftUI with digitalCrownRotation, scaleEffect, and DragGesture the officially recommended approach for zoom + pan on watchOS?
2. Is there any public API that provides built-in Photos-style behavior, or is a custom SwiftUI implementation expected?
3. Are there best-practice patterns for smooth scaling, maintaining image bounds, and constrained panning?
Thanks for any guidance
Topic:
UI Frameworks
SubTopic:
SwiftUI
When a subclass of UIInputView is created programmatically, a memory leak occurs.
This issue can be easily reproduced even with a very simple sample project, so I’m submitting this report along with a minimal reproducible example.
When a custom view subclassing UIInputView is instantiated in code,
_InputViewContent retains the custom view, and the custom view also holds a reference back to _InputViewContent,
creating a strong reference cycle that prevents deallocation.
The issue consistently occurs and has been confirmed on Xcode 16.4, 26.0, and 26.1.
As a workaround, initializing the view via Storyboard allows it to be properly deallocated from memory.
(Please refer to the CustomInputView in the attached sample code.)
import UIKit
final class LeakInputView: UIInputView {
deinit {
print("LeakInputView deinit") // not called
}
}
final class CustomInputView: UIInputView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect, inputViewStyle: UIInputView.Style) {
super.init(frame: frame, inputViewStyle: inputViewStyle)
}
deinit {
print("CustomInputView deinit") // called
}
}
extension CustomInputView {
static func loadFromNib() -> CustomInputView {
let nib = UINib(nibName: "CustomInputView", bundle: nil)
guard let view = nib.instantiate(withOwner: nil, options: nil).first as? CustomInputView else {
fatalError("Failed to load CustomInputView from nib.")
}
return view
}
}
final class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
LeakInputView()
LeakInputView()
LeakInputView()
CustomInputView.loadFromNib()
CustomInputView.loadFromNib()
CustomInputView.loadFromNib()
DispatchQueue.main.async {
print("Next runloop tick")
}
}
}
Topic:
UI Frameworks
SubTopic:
UIKit
I use the following bit of code to snapshot a View as a UIImage, but it's causing a memory leak:
extension View {
@ViewBuilder func snapshot(trigger: Bool, onComplete: @escaping (UIImage) -> ()) -> some View {
self.modifier(SnapshotModifier(trigger: trigger, onComplete: onComplete))
}
}
fileprivate struct SnapshotModifier: ViewModifier {
var trigger: Bool
var onComplete: (UIImage) -> ()
@State private var view: UIView = .init(frame: .zero)
func body(content: Content) -> some View {
content
.background(ViewExtractor(view: view))
.compositingGroup()
.onChange(of: trigger) {
generateSnapshot()
}
}
private func generateSnapshot() {
if let superView = view.superview?.superview {
let render = UIGraphicsImageRenderer(size: superView.bounds.size)
let image = render.image { _ in
superView.drawHierarchy(in: superView.bounds, afterScreenUpdates: true)
}
onComplete(image)
}
}
}
fileprivate struct ViewExtractor: UIViewRepresentable {
var view: UIView
func makeUIView(context: Context) -> UIView {
view.backgroundColor = .clear
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
// No process
}
}
Taking the snapshot is triggered like this:
struct ContentView: View {
@State private var triggerSnapshot: Bool = false
var body: some View {
Button("Press to snapshot") {
triggerSnapshot = true
}
TheViewIWantToSnapshot()
.snapshot(trigger: triggerSnapshot) { image in
// Save the image; you don't have to do anything here to get the leak.
}
}
}
I'm not the best at Instruments, and this is what the Leaks template produces. There are no method names, just memory addresses:
Is this leak in an internal iOS library, is there something wrong with Instruments, or am I missing something obvious in my code?
Thanks.
Why a TipKit configured with a weekly frequency, on the following example, when the app is launched on the View1, the tip is displayed. I thought that going to View2 and come back to View1 should not redisplayed the tip (at least until one week).
What do I miss?
import SwiftUI
import TipKit
struct FavoriteLandmarkTip: Tip {
var title: Text {
Text("Save as a Favorite")
}
var message: Text? {
Text("Your favorite landmarks always appear at the top of the list.")
}
var image: Image? {
Image(systemName: "star")
}
}
@main
struct LandmarkTips: App {
var body: some Scene {
WindowGroup {
TabView {
View1()
.tabItem {
Label("View1", systemImage: "house")
}
View2()
.tabItem {
Label("View2", systemImage: "house")
}
}
.task {
do {
// uncomment to reset all tips status
// try? Tips.resetDatastore()
try Tips.configure([
.displayFrequency(.weekly),
.datastoreLocation(.applicationDefault)
])
}
catch {
print("Error initializing TipKit \(error.localizedDescription)")
}
}
}
}
}
struct View1: View {
let favoriteLandmarkTip = FavoriteLandmarkTip()
var body: some View {
VStack {
TipView(favoriteLandmarkTip, arrowEdge: .bottom)
Image(systemName: "star")
}
}
}
struct View2: View {
var body: some View {
Text("View2")
}
}
When I run the following code and change "Is On", I get a problem with the layout of the Picker.
There is no problem when using Text(), but when using only Image, it works fine on iOS but there is a problem on macOS.
Tested on macOS 26.1, Xcode 26.1.
import SwiftUI
struct ContentView: View {
@State var model = Model()
var body: some View {
Form {
Picker("Category", selection: $model.category) {
ForEach(Category.allCases) { item in
Image(systemName: item.icon)
.tag(item)
}
}
.pickerStyle(.segmented)
Toggle("Is On", isOn: $model.isOn)
}
.formStyle(.grouped)
}
}
struct Model {
var category: Category = .a
var isOn: Bool = false
}
enum Category: Int, Identifiable, CaseIterable {
case a, b, c
var id: Int { rawValue }
var icon: String {
switch self {
case .a: return "a.circle.fill"
case .b: return "b.circle.fill"
case .c: return "c.circle.fill"
}
}
var name: String {
switch self {
case .a: return "a"
case .b: return "b"
case .c: return "c"
}
}
}
code-block
We are creating a Replicated FileProvider based application, where we need to change folder icons for root level folders.
I tried below two approaches.
This using NSFileProviderDecorations + Custom UTType, this changed the UI as shown:
This using Custom UTType, this had no UI change:
How can we change the default folder icon, to our custom icon?
Description
On iOS 26.1, a ToolbarItem placed in .keyboard is no longer exposed to the accessibility hierarchy. As a result:
VoiceOver cannot focus or activate the toolbar button
XCUITest cannot discover the element, making the UI impossible to test
TextEditor()
.toolbar {
ToolbarItem(placement: .keyboard) {
Button("Done") { /* action */ }
}
}
This worked correctly on previous iOS versions.
The button appears visually but is missing from both VoiceOver navigation and XCUI accessibility queries.
Steps to Reproduce
Create a new SwiftUI project.
Use a simple text field with a keyboard toolbar button.
Run on an iOS 26.1 device or simulator.
Focus the text field to show the keyboard.
Turn on VoiceOver and attempt to navigate to the toolbar button.
Run an XCUITest attempting to locate the button
I know iPhone Cannot prohibit screenshots, but I have seen someone else's solution, which is to capture a white page instead of the current design page when taking screenshots. I want to use swift implement iPhone The photo generated when taking a screenshot is a white screen, and I don't want my page to be seen by others
Topic:
UI Frameworks
SubTopic:
General
Looking at Brainrot's UI, they display both "Screen Time: 6h 31m" and a calculated "Health: 91/100" score with a "Tap to Fix" button. This suggests manual sync or a workaround.
Specific Questions:
Can DeviceActivityReport extensions communicate data back to the main app? (CloudKit, Notifications, Shared files?)
Can extensions write to UserDefaults on physical devices?
Do commercial apps rely on manual user sync?
Is there an alternative API I'm overlooking?
Do threshold-based approximations work reliably for daily tracking?
I can extract exact minutes in the extension but can't export them to the main app due to sandbox restrictions. Either a technical solution or confirmation that manual sync is the industry standard would help greatly.