Hi,
I am looking to display (in SwiftUI) the Tabview page dots like in the weather app in the toolbar, an important thing is I want to keep page controls by tapping and scrubbing.
Actually, I want to do what's on Apple Design's Page Controls page; here's the link and a photo of what I'd like to do.
Could you help me?
https://developer.apple.com/design/human-interface-guidelines/page-controls
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
I'm looking to support toggleable bullet and numbered lists in my IOS 26 app. currently my text editor looks like this
@Binding var text: AttributedString
var requestFocus: Bool = false
@State private var selection = AttributedTextSelection()
@FocusState private var isFocused: Bool
var body: some View {
TextEditor(text: $text, selection: $selection)
.scrollContentBackground(.hidden)
.background(Color.clear)
.focused($isFocused)
.safeAreaInset(edge: .bottom) {
if isFocused {
FormattingToolbar(text: $text, selection: $selection)
.padding(.horizontal)
.padding(.vertical, 8)
.background(Color(UIColor.systemBackground))
}
}
.onChange(of: requestFocus) { _, newValue in
if newValue {
isFocused = true
}
}
}
}
i cant find any useful docs on how to best implement this. anything helps, thanks
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have (had) a view controller that does a bit of manual layout in a -viewDidLayout override.
This was pretty easy to manage - however since introducing NSGlassEffectView into the view hierarchy I sometimes am getting hit with "Unable to simultaneously satisfy constraints" and Appkit would break a constraint to 'recover.' It appears translatesAutoresizingMaskIntoConstraints is creating some really weird fixed width and height constraints. Here I wasn't doing any autolayout - just add the glass view and set its frame in -viewDidLayout.
At runtime since I do manual layout in -viewDidLayout the frames are fixed and there is no real "error" in my app in practice though I wanted to get rid of the constraint breaking warning being logged because I know Autolayout can be aggressive about 'correctness' who knows if they decide to throw and not catch in the future.
In my perfect world I would probably just prefer a view.doesManualLayout = YES here - the subviews are big containers no labels so localization is not an issue for me. Rather than playing with autoresizing masks to get better translated constraints I decided to set translatesAutoresizingMaskIntoConstraints to NO and make the constraints myself. Now I get hit with the following exception:
"The window has been marked as needing another Layout Window pass, but it has already had more Layout Window passes than there are views in the window"
So this happens because the view which now has constraints -- I adjusted the frame of it one point in -viewDidLayout. My question is - is not legal to make changes in -viewDidLayout - which seems like the AppKit version of -viewDidLayoutSubviews.
In UIKit I always thought it was fine to make changes in -viewDidLayoutSubviews to frames - even if constraints were used - this is a place where you could override things in complex layouts that cannot be easily described in constraints. But in AppKit if you touch certain frames in -viewDidLayout it can now cause this exception (also related: https://developer.apple.com/forums/thread/806471)
I will change the constant of one of the constraints to account for the 1 point adjustment but my question still stands - is it not legal to touch frames in -viewDidLayout when autolayout constraints are used on that subview? It is (or at least was if I remember correctly) permitted to change the layout in -viewDidLayoutSubviews in UIKit but AppKit seems to be more aggressive in its checking for layout correctness).
What about calling -sizeToFit on a control in viewDidLayout or some method that has side effect of invalidating layout in a non obvious way, is doing things like this now 'dangerous?'
Shouldn't AppKit just block the layout from being invalidated from within -viewDidLayout - and leave whatever the layout is as is when viewDidLayout returns (thus making -viewDidLayout a useful place to override layout in the rare cases where you need a sledgehammer?)
Views placed inside tabViewBottomAccessory that access @Environment values or contain @State properties experience unstable identity, as shown by Self._printChanges(). The identity changes on every structural update to the TabView, even though the view's actual identity should remain stable. This causes unnecessary view recreation and breaks SwiftUI's expected identity and lifecycle behavior.
Environment
Xcode Version 26.2 (17C52)
iOS 26.2 simulator and device
struct ContentView: View {
@State var showMoreTabs = true
struct DemoTab: View {
var body: some View { Text(String(describing: type(of: self))) }
}
var body: some View {
TabView {
Tab("Home", systemImage: "house") { DemoTab() }
Tab("Alerts", systemImage: "bell") { DemoTab() }
if showMoreTabs {
TabSection("Categories") {
Tab("Climate", systemImage: "fan") { DemoTab() }
Tab("Lights", systemImage: "lightbulb") { DemoTab() }
}
}
Tab("Settings", systemImage: "gear") {
List {
Toggle("Show more Tabs", isOn: $showMoreTabs)
}
}
}
.tabViewBottomAccessory {
AccessoryView()
}
.task {
while true {
try? await Task.sleep(for: .seconds(5))
if Task.isCancelled { break }
print("toggling showMoreTabs")
showMoreTabs.toggle()
}
}
.tabBarMinimizeBehavior(.onScrollDown)
}
}
struct AccessoryView: View {
var body: some View {
HStack {
EnvironmentAccess()
WithState()
Stateless()
}
}
}
struct EnvironmentAccess: View {
@Environment(\.tabViewBottomAccessoryPlacement) var placement
var body: some View {
// FIXME: EnvironmentAccess: @self, @identity, _placement changed.
// Identity should be stable
let _ = Self._printChanges()
Text(String(describing: type(of: self))) }
}
struct WithState: View {
@State var int = Int.random(in: 0...100)
var body: some View {
// FIXME: WithState: @self, @identity, _id changed.
// Identity should be stable
let _ = Self._printChanges()
Text(String(describing: type(of: self)))
}
}
struct Stateless: View {
var body: some View {
// Works as expected: Stateless: @self changed.
let _ = Self._printChanges()
Text(String(describing: type(of: self)))
}
}
This bug seems to make accessing TabViewBottomAccessoryPlacement impossible without losing view identity; the demo code is affected by the bug. Accessing a value like @Environment(\.colorScheme) is similarly affected, making visually adapting the contents of the accessory to the TabView content without losing identity challenging if not impossible.
Submitted as FB21627918.
I have no idea how to do it: on MacOS, in Document.init(configuration: ReadConfiguration) I decode file, and restore objects from data, which in some cases could take a long time. Document isn't fully inited, so I have no access to it. But would like to have a progress bar on screen (easier to wait for done, for now). I know size, progress value, but no idea how to make view from object during init.
I know, this question may be very stupid.
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents
else {
throw CocoaError(.fileReadCorruptFile)
}
let decoder = JSONDecoder()
let flat = try decoder.decode(FlatDoc.self, from: data)
print ("reverting \(flat.objects.count) objects...")
///This takes time, a lot of time, need progress bar
///Total is `flat.objects.count`, current is `objects.count`
/// `Show me a way to the (next) progress bar!`
revertObjects(from: flat.objects)
print ("...done")
}
update: I defined var flatObjects in Document, and I can convert in .onAppear.
struct TestApp: App {
@State var isLoading = false
...
ContentView(document: file.$document)
.onAppear {
isLoading = true
Task {file.document.revertObjects()}
isLoading = false
}
if isLoading {
ProgressView()
}
...
}
But progress bar never shows, only rainbow ball
Do you know if there is a work around to animate the reorder of a table without generating ghost rows?
here is the code:
var id = UUID()
var name: String
var value: Int
}
struct ContentView: View {
@State var selectedNumber: UUID?
@State var sortedBy: [KeyPathComparator<MyNumbers>] = [KeyPathComparator(\.name, order: .reverse)]
@State var numbers: [MyNumbers] = {
var numbersArray = [MyNumbers]()
for i in 0..<100 {
numbersArray.append(MyNumbers(name: "\(i)", value: i))
}
return numbersArray
}()
var body: some View {
Table(numbers, selection: $selectedNumber, sortOrder: $sortedBy) {
TableColumn("names", value: \.name){ number in
Text(number.name)
}
TableColumn("names", value: \.name){ number in
Text(number.name)
}
}.onChange(of: sortedBy) { oldValue, newValue in
withAnimation {
numbers.sort(using: newValue)
}
}
}
}
it generates ghost rows when the top row is selected and reorders twice, as you can see in the screenshot, the first six rows has two labels overlapped.
Topic:
UI Frameworks
SubTopic:
SwiftUI
When I use UIScrollView to Browse photos, sometime was crash.
Issue Details:
App: 美信 (Midea Connect)
Problem: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Feedback generator was deactivated by its client more times than it was activated: <_UIZoomEdgeFeedbackGenerator: 0x33527cdc0>' First throw call stack
Affected: 4 user out of thousands
iOS Version: 18.0.1、26.1、26.2
What Works:
All other users has no crash
Same iOS version, no issues
User Has Tried:
The user experienced two crashes after opening the page hundreds of times
Topic:
UI Frameworks
SubTopic:
UIKit
Our app works fine on iOS 26 on other platforms but on iphone17, the text on the popovers is so light it is unreadable when the device is in Light mode. Is anyone else having this issue and if so, do you have any recommendations?
Topic:
UI Frameworks
SubTopic:
General
I found an issue related to Gmail and Email apps. When I try to fetch text using
controller.textDocumentProxy.documentContext, it works fine every time in my original app and in the Messages app. However, in Gmail or Email apps, after pasting text, controller.textDocumentProxy.documentContext returns nil until the pasted text is edited. The same scenario works correctly in Messages and my original app. i'm trying it from my keyboard extension and my keyboard builded bases on KeyboardKit SDK when i jump to text Document Proxy it's referring me to UITextDocumentProxy
Topic:
UI Frameworks
SubTopic:
UIKit
Since Callkit is not supported in mainland China, 'LiveCommunicationKit' is currently being used. When a VoIP push notification is received, the banner does not display correctly, but the phone icon in the top left corner, the ringtone, and vibration are present. I followed the solution in "https://developer.apple.com/forums/thread/774958?answerId=827083022#827083022" to resolve the crash issue, but the banner is still not displayed.
Topic:
UI Frameworks
SubTopic:
General
Hello,
I'm currently working on an app that will have a different name (and UI) depending on an environment variable that is set by that app's custom installer that I also wrote.
I'm trying to change the app name that is displayed in the menu bar (top left) programmatically. I've done some research and found that it's probably not possible to do so because it's fetched from the app's Info.plist
The answer is probably already there but I'll ask the question: Is it possible to change the app's name in the menu bar without tampering with the Info.plist (as it will break the signature at runtime, and it can't be done at compile time)
The use case here is that I'm shipping a single app with multiple installers, because the app will be the same for all sets of users but it will have minor UI changes (which in my opinion, don't need an entire separate release), the installers will set a flag that the app will, based on, change its UI to the corresponding set of users. For the most part it's been successful but only small issue remain like this one.
The reason it's done like that is when updating I'll ship 1 release for all users to update rather than having to ship multiple releases with no difference between them
For some reason, Carplay 18.x works fine, however in under certain situations in our app, Carplay 26.x breaks.
The expected grid layout should be :
However, this is what we see in some cases when we update our templates.
I have not been able to isolate the cause of this issue. Has anyone ever seen this happen on their CarPlay apps and discovered the cause?
The data sets fed into the templates are identical, the difference is in some of the timing and update order...
Adding '_UIReparentingView' as a subview of UIHostingController.view is not supported and may result in a broken view hierarchy. Add your view above UIHostingController.view in a common superview or insert it into your SwiftUI content in a UIViewRepresentable instead.
how can i fix this issue
Topic:
UI Frameworks
SubTopic:
SwiftUI
I'm attempting to use WebAuthenticationSession from Authentication Services (https://developer.apple.com/documentation/authenticationservices/webauthenticationsession) in a SwiftUI app on macOS.
According to the docs, it is supported since macOS 13.3 and I'm testing on 26.
I'm deploying the same code to iOS as well, and it works there in a simulator, but I sometimes have to tap the button that triggers the authenticate(…) call more than once.
I've attached a simplified and redacted version of the code below. It works on iOS, but on macOS the authenticate call never returns.
There seems to be very little documentation and discussion about this API and I'm running out of ideas for getting this to work. Is this just a bug that Apple hasn't noticed?
import SwiftUI
import AuthenticationServices
import Combine
struct PreAuthView: View {
@Binding var appState: AppState
@Binding var credentials: Credentials?
@Environment(\.webAuthenticationSession) private var webAuthenticationSession
@State private var plist: String = ""
func authenticate() async {
guard var authUrl = URL(string: "REDACTED") else { return }
guard var tokenUrl = URL(string: "REDACTED") else { return }
let redirectUri = "REDACTED"
let clientId = "REDACTED"
let verifier = "REDACTED"
let challenge = "REDACTED"
authUrl.append(queryItems: [
.init(name: "response_type", value: "code"),
.init(name: "client_id", value: clientId),
.init(name: "redirect_uri", value: redirectUri),
.init(name: "state", value: ""),
.init(name: "code_challenge", value: challenge),
.init(name: "code_challenge_method", value: "S256"),
])
let scheme = "wonderswitcher"
do {
print("Authenticating")
let redirectUrl = try await webAuthenticationSession.authenticate(
using: authUrl,
callback: .https(host: "REDACTED", path: "REDACTED"),
additionalHeaderFields: [:],
)
print("Authenticated?")
print(redirectUrl)
let queryItems = URLComponents(string: redirectUrl.absoluteString)?.queryItems ?? []
let code = queryItems.filter({$0.name == "code"}).first?.value
let session = URLSession(configuration: .ephemeral)
tokenUrl.append(queryItems: [
.init(name: "grant_type", value: "authorization_code"),
.init(name: "code", value: code),
.init(name: "redirect_uri", value: redirectUri),
.init(name: "code_verifier", value: verifier),
.init(name: "client_id", value: clientId),
])
var request = URLRequest(url: tokenUrl)
request.httpMethod = "POST"
let response = try await session.data(for: request)
print(response)
} catch {
return
}
}
var body: some View {
NavigationStack {
VStack(alignment: .leading, spacing: 12) {
Text("This is the pre-auth view.")
HStack {
Button("Log in") {
Task {
await authenticate()
}
}
Spacer()
}
Spacer(minLength: 0)
}
.padding()
.navigationTitle("Pre-Auth")
}
}
}
#Preview {
PreAuthView(appState: .constant(.preAuth), credentials: .constant(nil))
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hello, following Apple docs and guidance from WWDC I'm trying to set a minimum size for my scene, for example I want it to minimally be 3/4 the width and height of the device.
I've removed the UIRequiresFullScreen Info.plist property. The app does run in windowed mode and does have a resizing handle.
I've implemented this UISceneDelegate:
var window: UIWindow?
var cameraWindow: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
window = UIWindow(windowScene: scene as! UIWindowScene)
// setup root view controller
let rootViewController: MainViewController = MainViewController(nibName: "Main", bundle: nil)
let navController: NavigationController = NavigationController(rootViewController: rootViewController)
navController.modalPresentationStyle = .fullScreen
// set reasonable minimum sizes for WindowScene
if let windowScene: UIWindowScene = scene as? UIWindowScene {
if #available(iOS 16.0, *) {
let windowSize: CGSize = windowScene.coordinateSpace.bounds.size
windowScene.sizeRestrictions?.minimumSize.width = windowSize.width * 0.75
windowScene.sizeRestrictions?.minimumSize.height = windowSize.height * 0.75
}
}
window?.rootViewController = navController
window?.makeKeyAndVisible()
}
}
And proven via debugger that this code is being executed.
I have the following observations:
After setting these minimumSize properties I see the width and height both contain 0 afterwards, as if the property settings are discarding the value. I've even used hard-coded values instead of reading the coordinateSpace.bounds, to no avail.
The scene is allowing resizing well below these minimums, about 1/3 the width and 1/2 the height.
Anyone else observed this and have suggestions?
Topic:
UI Frameworks
SubTopic:
UIKit
I have some really straight forward code in a sample project. For some reason when the app launches the title is blurred obscured by scrolledgeeffect blur. If I scroll down the title goes small as it should do and all looks fine. If I scroll back to the top, just before it reaches the top the title goes large and it looks correct, but once it actually reaches/snaps to the top, is then incorrectly blurs again.
Is there anything obvious I'm doing wrong? Is this a bug?
struct ContentView: View {
var body: some View {
NavigationStack {
ScrollView {
VStack {
Rectangle().fill(Color.red.opacity(0.2)).frame(height: 200)
Rectangle().frame(height: 200)
Rectangle().frame(height: 200)
Rectangle().frame(height: 200)
Rectangle().frame(height: 200)
}
}
.safeAreaBar(edge: .top) {
Text("Test")
}
.navigationTitle(Title")
}
}
}
I am struggling to change the tint of the back button in an UINavigationItem. In iOS 18.6 it looks like this
while on iOS 26 the same looks like this
I can live without the Dictionary but I'd like to get the blue color back.
In viewDidLoad() I have tried
navigationItem.backBarButtonItem?.tintColor = .link
but this did not work since navigationItem.backBarButtonItem is nil. My second attempt was
navigationController?.navigationBar.tintColor = .link
but this didn't work either.
I have even set the Global Tint to Link Color
but this had no effect either.
Does anyone have an idea how to change the tint of the back button in an UINavigationItem on iOS 26?
Hello,
I'm trying to make a white-Label sort of thing for my app, that is: a script runs before the app launches, sets a certain LaunchAgent command that sets and environment variable, and based on that variable's value tha main app's icon changes to a certain logo (change only happens in the dock because changing the icon on disk breaks the signature)
When the app launches it takes a noticeable time until the dock icon changes to what I want, so I worked around that by setting the app's plist property to hide the dock icon and then when the app is launched I call an objc++ function to display the icon in the dock again (this time it displays as the new icon)
The showing happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
The problem happens when I try to close the app, it returns back to the old logo before closing which is what I want to prevent. I tried hiding the app dock icon before closing but even the hiding itself changes the icon before hiding
The hiding happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
My goal is that the main app icon doesn't appear to the user through the dock, and that the icon that is only visible is the other one that changes during runtime
The reason for this is that I have an app that should be visible differently depending on an environment variable that I set using an installer app. The app is the same for all users with very minor UI adjustments depending on that env variable's value. So instead of creating different versions of the app I'd like to have just 1 version that adjusts differently depending on the env variable's value. Somehow this is the only step left to have a smooth experience
Feel free to ask more clarification questions I'd be happy to help
Thank you
I'm working on a watchOS app using SwiftUI that updates its UI based on regular, time-driven logic. On a real Apple Watch, after the app has been running for ~1 minute, the device enters Always-On / power-saving display mode (screen dimmed, wrist down). From that point on, SwiftUI UI updates become noticeably delayed. The underlying logic continues to run correctly, but the UI only redraws sporadically and often "catches up" once the screen becomes fully active again. The app is running in workout mode, which keeps it alive and maintains WatchConnectivity, but this does not prevent UI redraw throttling. Below is a minimal reproducible example that demonstrates the issue.
PlaybackModel.swift
import SwiftUI
@MainActor
final class PlaybackModel: ObservableObject {
@Published var beat: Int = 0
private var timer: Timer?
func start() {
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
Task { @MainActor in
self.beat += 1
}
}
}
func stop() {
timer?.invalidate()
}
}
ContentView.swift (watchOS)
import SwiftUI
struct ContentView: View {
@StateObject private var model = PlaybackModel()
var body: some View {
VStack {
Text("Beat: \(model.beat)")
.font(.largeTitle)
}
.onAppear {
model.start()
}
.onDisappear {
model.stop()
}
}
}
Observed Behavior
• The beat value continues to increase reliably.
• After the watch enters Always-On / power-saving mode, SwiftUI redraws are delayed or skipped.
• When the screen becomes fully active again, the UI catches up.
Questions:
• Is this UI redraw throttling in Always-On / power-saving mode an unavoidable system limitation on watchOS?
• Is there any supported way to keep consistent SwiftUI update frequency while the app is visible but dimmed?
Are there tools to inspect why a drag-and-drop drop is not triggering in a SwiftUI app?
I've declared .draggable on the dragging view, and .dropDestination on the receiving TabContent Tab view.
This combination of modifiers is working on a smaller demo app that I have, but not on my more complex one.
Is there a means to debug this in SwiftUI? I'd like to see if the drag-and-drop pasteboard actually has what I think it should have on it.
Notably: "TabContent" has a far more restricted list of modifiers that can be used on it.