Try this simple code:
import SwiftUI
import StoreKit
struct ReviewView: View {
@Environment(\.requestReview) var requestReview
var body: some View {
Button("Leave a review") {
requestReview()
}
}
}
When the Review Alert shows, the "Not Now" button is disabled for some reason!? It was always tappable in all iOS versions that I remember. And there is no way to opt out, unless the user taps on the stars first. Is it a bug or a feature?
Thanks for looking into it!
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
With iOS 26 there has been a change in behavior with Pickers in the toolbar. The Picker looks expanded unlike other views such as a Button and Menu. See screenshots below. Is this the intended behavior or a bug? (I already submitted a feedback for this at FB19276474)
What Picker looks like in the toolbar:
What Button looks like in the toolbar:
I have a SwiftUI recursive list, created with the (children:) initializer, just like it's shown in the code example here: https://developer.apple.com/documentation/SwiftUI/List#Creating-hierarchical-lists
I would like this tree view to be searchable (i.e a user enters a query into a text field and it searches the entire tree at all levels). Displaying a search result which is not at the top level would require its parents to be programmatically expanded.
How to programmatically expand certain levels of such a list?
The top toolbar looks fine, but in the bottom toolbar, one of the layers is stretched into a capsule shape instead of an ellipse.
Is this intended?
When tap the Button quickly in List, the ButtonStyleConfiguration’s isPressed property don't change properly, always false. When using Button in ScrollView, the same error doesn't exist.
I’m facing an issue in our native iOS app that occurs specifically on iOS 26.1 (not observed on any lower versions). When I update a @State field value, the UI does not reflect the change as expected.
The @State variable updates internally, but the view does not re-render.
This behaviour started after upgrading to iOS 26.1.
Works fine on iOS 26.0 and earlier versions.
Has anyone else encountered this issue or found a workaround? Any insights or suggestions would be greatly appreciated.
I'm trying to revamp the player into a floating style like Apple music. I use tabViewBottomAccessory with tabBarMinimizeBehavior. At the time, I noticed an issue that tabViewBottomAccessory would not automatically collapse when the scroll area was small (but still exceeded the screen height). tabViewBottomAccessory can only be automatically collapsed when the scroll area is large enough. Below is the simplest demo.
I'm not sure if it's intentional or if it's a bug. Besides, I wonder if we can control it programmatically(expanded/inline)?
struct ContentView: View {
var body: some View {
TabView {
Tab("Numbers", systemImage: "number.circle") {
List {
// 200 works well, but 20 not
ForEach(0..<200) { index in
Text("\(index)")
}
}
}
}
.tabBarMinimizeBehavior(.onScrollDown)
.tabViewBottomAccessory {
HStack {
Text("SwiftUI Demo App")
}
}
}
}
I am trying to perform swiftUI instrumentation on my ios app. whenever i hit the rocord button, the app launches on target device and closes with the error:
Failed to start the recording: Failed starting ktrace session.
How do i resolve this please?
Hello,
I'm thinking about how to improve my main tvOS app flow, naively I want to do something like this:
import Combine
import SwiftUI
enum AppState {
case login, onboarding, main
}
class AppStateManager {
let appStatePublisher = PassthroughSubject<AppState, Never>()
func updateState(_ appState: AppState)
}
struct tvOSApp: App {
private var appState: AppState = .login
private let appStateManager = AppStateManager()
var body: some Scene {
WindowGroup {
ZStack {
switch appState {
case .login:
LoginView()
case .onboarding:
OnboardingView()
case .main:
MainView()
}
}
.onReceive(appStateManager.appStatePublisher) {
self.appState = $0
}
}
}
}
So basically, MainView, OnboardingView and LoginView would be the main navigation views of my app, and the appStateManager would be a dependency passed to each of these views and allowing me to update the currently displayed view in the app. (of course I could use an Environment object instead for a 100% SwiftUI solution).
I was wondering, however, if there is a better way to do this, instead of switching in a ZStack, maybe with WindowGroup/Window/Scenes?
Thank you for your help!
I am working on a Live Activity widget.
In it, I want some of the elements to open different deeplink URLs.
I have found that assigning multiple widgetURL doesn't work, only one of the URLs gets opened no matter where you tap. I also found that Buttons don't seem to do anything, tapping them actually just open my app as if I just tapped a naked Live Activity.
I have found that really only Link elements work if I want to open different URLs upon tapping different elements.
And Links are cool and fine, but I am seeing that on tap, my elements become tinted... As in, there is a highlighted state, and it makes the elements inside blue.
I have tried to use button style API on a link, but it didn't work.
How can I disable the highlighted state for a Link element in a live activity widget?
inline-code
How do you achieve this effect in toolbar? Where is the documentation for this?
How to make it appear top toolbar or bottom toolbar?
Thank you!
Here is what I have now...
.toolbar {
ToolbarItem(placement: .destructiveAction) {
Button {
showConfirm = true
} label: {
Image(systemName: "trash")
.foregroundColor(.red)
}
}
}
.confirmationDialog(
"Are you sure?",
isPresented: $showConfirm,
titleVisibility: .visible
) {
Button("Delete Item", role: .destructive) {
print("Deleted")
}
Button("Archive", role: .none) {
print("Archived")
}
Button("Cancel", role: .cancel) { }
}
}
Environment
visionOS 26.1, Xcode 26.1.1
Problem
When a WindowGroup opens an ImmersiveSpace and the user closes the window via X button, the async Task in .onDisappear gets cancelled before dismissImmersiveSpace() completes, leaving the ImmersiveSpace active with no way to exit.
Steps
WindowGroup opens ImmersiveSpace in .onAppear
User clicks X to close window
.onDisappear fires but async cleanup cancelled
ImmersiveSpace remains active, user trapped
Expected
ImmersiveSpace dismissed when window closes
Actual
ImmersiveSpace remains active
Code
.onAppear {
Task {
await openImmersiveSpace(id: "VideoCallMainCamera")
}
}
.onDisappear {
Task {
await dismissImmersiveSpace() // Gets cancelled
}
}
What I've Tried
Task in .onDisappear ❌
scenePhase monitoring ❌
High priority Task ❌
.restorationBehavior(.disabled) + .defaultLaunchBehavior(.suppressed) ✅ (prevents restoration but doesn't fix immediate cleanup)
Question
What's the recommended pattern for ensuring ImmersiveSpace cleanup when WindowGroup closes? Is there a way to block window closure until async cleanup completes, or should ImmersiveSpaces automatically dismiss with their parent window?
Hi Team,
How do I prevent screenshots using SwiftUI. I was using this solution on UIKit:
extension UIView {
func makeSecure() {
DispatchQueue.main.async {
let protectedView = UIView()
self.superview?.addSubview(protectedView)
// constraints...
let secureView = SecureView()
self.superview?.addSubview(secureView)
// constraints...
secureView.addSecureSubview(self)
// constraints...
}
}
}
class SecureView: UIView {
private lazy var secureField: UIView = {
var secureField: UIView = UIView()
// ...
if let secureContainer = SecureField().secureContainer {
secureField = secureContainer
}
...
return secureField
}()
required init() { ... }
}
Is it posible to do the same thing using SwiftUI. Do we have an example? What would you recommend when we work with confidencial information in SwiftUI like bank account information?
Thanks in advance!
The zoom navigation transition with matchedTransitionSource in tabViewBottomAccessory does not work when a Published var in an ObservableObjector Observable gets changed.
Here is an minimal reproducible example with ObservableObject:
import SwiftUI
import Combine
private final class ViewModel: ObservableObject {
@Published var isPresented = false
}
struct ContentView: View {
@Namespace private var namespace
@StateObject private var viewModel = ViewModel()
// @State private var isPresented = false
var body: some View {
TabView {
Button {
viewModel.isPresented = true
} label: {
Text("Start")
}
.tabItem {
Image(systemName: "house")
Text("Home")
}
Text("Search")
.tabItem {
Image(systemName: "magnifyingglass")
Text("Search")
}
Text("Profile")
.tabItem {
Image(systemName: "person")
Text("Profile")
}
}
.sheet(isPresented: $viewModel.isPresented) {
Text("Sheet")
.presentationDragIndicator(.visible)
.navigationTransition(.zoom(sourceID: "tabViewBottomAccessoryTransition", in: namespace))
}
.tabViewBottomAccessory {
Button {
viewModel.isPresented = true
} label: {
Text("BottomAccessory")
}
.matchedTransitionSource(id: "tabViewBottomAccessoryTransition", in: namespace)
}
}
}
However, when using only a State property everything works:
import SwiftUI
import Combine
private final class ViewModel: ObservableObject {
@Published var isPresented = false
}
struct ContentView: View {
@Namespace private var namespace
// @StateObject private var viewModel = ViewModel()
@State private var isPresented = false
var body: some View {
TabView {
Button {
isPresented = true
} label: {
Text("Start")
}
.tabItem {
Image(systemName: "house")
Text("Home")
}
Text("Search")
.tabItem {
Image(systemName: "magnifyingglass")
Text("Search")
}
Text("Profile")
.tabItem {
Image(systemName: "person")
Text("Profile")
}
}
.sheet(isPresented: $isPresented) {
Text("Sheet")
.presentationDragIndicator(.visible)
.navigationTransition(.zoom(sourceID: "tabViewBottomAccessoryTransition", in: namespace))
}
.tabViewBottomAccessory {
Button {
isPresented = true
} label: {
Text("BottomAccessory")
}
.matchedTransitionSource(id: "tabViewBottomAccessoryTransition", in: namespace)
}
}
}
Hello there!
I wanted to give a native scrolling mechanism for the Swift Charts Graph a try and experiment a bit if the scenario that we try to achieve might be possible, but it seems that the Swift Charts scrolling performance is very poor.
The graph was created as follows:
X-axis is created based on a date range,
Y-axis is created based on an integer values between moreless 0-320 value.
the graph is scrollable horizontally only (x-axis),
The time range (x-axis) for the scrolling content was set to one year from now date (so the user can scroll one year into the past as a minimum visible date (.chartXScale).
The X-axis shows 3 hours of data per screen width (.chartXVisibleDomain).
The data points for the graph are generated once when screen is about to appear so that the Charts engine can use it (no lazy loading implemented yet).
The line data points (LineMark views) consist of 2880 data points distributed every 5 minutes which simulates - two days of continuous data stream that we want to present. The rest of the graph displays no data at all.
The performance result:
The graph on the initial loading phase is frozen for about 10-15 seconds until the data appears on the graph.
Scrolling is very laggy - the CPU usage is 100% and is unacceptable for the end users.
If we show no data at all on the graph (so no LineMark views are created at all) - the result is similar - the empty graph scrolling is also very laggy.
Below I am sharing a test code:
@main
struct ChartsTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
Spacer()
}
}
}
struct LineDataPoint: Identifiable, Equatable {
var id: Int
let date: Date
let value: Int
}
actor TestData {
func generate(startDate: Date) async -> [LineDataPoint] {
var values: [LineDataPoint] = []
for i in 0..<(1440 * 2) {
values.append(
LineDataPoint(
id: i,
date: startDate.addingTimeInterval(
TimeInterval(60 * 5 * i) // Every 5 minutes
),
value: Int.random(in: 1...100)
)
)
}
return values
}
}
struct ContentView: View {
var startDate: Date {
return endDate.addingTimeInterval(-3600*24*30*12) // one year into the past from now
}
let endDate = Date()
@State var dataPoints: [LineDataPoint] = []
var body: some View {
Chart {
ForEach(dataPoints) { item in
LineMark(
x: .value("Date", item.date),
y: .value("Value", item.value),
series: .value("Series", "Test")
)
}
}
.frame(height: 200)
.chartScrollableAxes(.horizontal)
.chartYAxis(.hidden)
.chartXScale(domain: startDate...endDate) // one year possibility to scroll back
.chartXVisibleDomain(length: 3600 * 3) // 3 hours visible on screen
.onAppear {
Task {
dataPoints = await TestData().generate(startDate: startDate)
}
}
}
}
I would be grateful for any insights or suggestions on how to improve it or if it's planned to be improved in the future.
Currently, I use UIKit CollectionView where we split the graph into smaller chunks of the graph and we present the SwiftUI Chart content in the cells, so we use the scrolling offered there. I wonder if it's possible to use native SwiftUI for such a scenario so that later on we could also implement some kind of lazy loading of the data as the user scrolls into the past.
The Widget Image display on iOS26 transparency mode is blank
Both of these writing methods show blank Spaces. Is there a problem with my code or a bug in the system?
The current compilation environment is Xcode Version 16.3 (16E140) iOS26.0
I recently added pushWindow to my app, and I discovered that in visionOS 26.2 RC (23N301), pushWindow followed by dismissWindow no longer works as expected.
Specifically, if the user moves the pushed window, then when the pushed window is later dismissed, the parent window's position isn't aligned with the pushed window's new position. Its original position is restored instead.
Curiously, the bug only happens when an app is launched from the visionOS home view, and not when an app is launched from Xcode. It also doesn't happen in the visionOS 26.2 simulator.
Another interesting detail is that while the parent window is hidden, if the user long-presses the Digital Crown and then dismisses the pushed window, the parent window's position seems to be immune from the Digital Crown scene reorientation. It's restored to its original real world position.
Demo video: https://youtu.be/zR3t2ON3Wz0
I've submitted feedback as FB21287011 with a sample app and detailed repro steps.
Has anyone else encountered this issue already and figured out a workaround? It would be nice if I could get pushWindow to work correctly in my app.
Thanks everybody! 😀
When you use .navigationTransition(.zoom(sourceID: "placeholder", in: placehoder)) for navigation animation, going back using the swipe gesture is still very buggy on IOS26. I know it has been mentioned in other places like here: https://developer.apple.com/forums/thread/796805?answerId=856846022#856846022 but nothing seems to have been done to fix this issue.
Here is a video showing the bug comparing when the back button is used vs swipe to go back: https://imgur.com/a/JgEusRH
I wish there was a way to at least disable the swipe back gesture until this bug is fixed.
in this great talk https://developer.apple.com/videos/play/wwdc2023/10111/ the code references usdz models to replace hands. e.g assets/gloves/LeftGlove_v001.usdz. Are these models available to download to explain rigging and how to make hand models (ideally in Blender )
Are the glove assets used in the sample from wwdc2023-10111 available somewhere?
Thanks