I work on a universal app that targets both iPhone and iPad. Our iPad app currently requires full screen. When testing on the latest iPadOS 26 beta, we see the following warning printed to the console:
Update the Info.plist: 1) `UIRequiresFullScreen` will soon be ignored. 2) Support for all orientations will soon be required.
It will take a fair amount of effort to update our app to properly support presentation in a resizable window. We wanted to gauge how urgent this change is. Our testing has shown that iPadOS 26 supports our app in a non-resizable window.
Can someone from Apple provide any guidance as to how soon “soon” is? Will UIRequiresFullScreen be ignored in iPadOS 26? Will support for all orientations be required in iPadOS 26?
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
Hello. There seems to be a bug specifically in the iOS 18.2 (both Beta 1 and 2) and not seen in the previous versions.
The bug is: when LazyVGrid is nested inside NavigationStack and some elements of the LazyVGrid have animations, navigating into any nested view and then going back to the initial view with the LazyVGrid causes all animations to stop working.
Here is the example code inline:
struct ContentView: View {
@State private var count: Int = 0
var body: some View {
NavigationStack {
LazyVGrid(
columns: Array(
repeating: GridItem(spacing: 0),
count: 1
),
alignment: .center,
spacing: 0
) {
VStack {
Text(String(count))
.font(.system(size: 100, weight: .black))
.contentTransition(.numericText())
.animation(.bouncy(duration: 1), value: count)
Button("Increment") {
count += 1
}
NavigationLink(destination: { Text("Test") }, label: { Text("Navigate") })
}
}
}
.padding()
}
}
Once you run the application on iOS 18.2 Beta (I've tried on a real device only), the steps to reproduce are:
Tap on the "Increment button"
You should see the number change with an animation
Tap on the "Navigate" button
Tap "Back" to go to the initial screen
Tap "Increment" again
The number changes without an animation
I can confirm that this affects not only .contentTransition() animation but any animation within the LazyVGrid, I've tested this in my real app.
Let me know if I can provide more details. Thank you!
I need to check the network connection with NWPathMonitor.
import Foundation
import Network
class NetworkViewModel: ObservableObject {
let monitor = NWPathMonitor()
let queue = DispatchQueue(label: "NetworkViewModel")
@Published var isConnected = false
var connectionDescription: String {
if isConnected {
return "You are connected."
} else {
return "You are NOT connected."
}
}
init() {
monitor.pathUpdateHandler = { path in
DispatchQueue.main.async {
self.isConnected = path.status == .satisfied
}
}
monitor.start(queue: queue)
}
}
import SwiftUI
struct ContentView: View {
@StateObject private var networkViewModel = NetworkViewModel()
var body: some View {
VStack {
}
.onAppear {
if networkViewModel.isConnected {
print("You are connected.")
}
else {
print("You are NOT connected.")
}
}
}
}
So there is nothing special, not at all. Yet, if I test it with a totally new Xcode project for iOS, it fails and return !isConnected. I've tested it with a macOS application. And it fails. I've tested it with an actual device. It fails. I've tested it with an old project. It still does work. I have no mere idea why new Xcode projects all fail to detect the WiFi connection. This is a total nightmare. Does anybody have a clue? thanks.
I've posted a couple times now about major issues I'm having with NSLayoutManager and have written to Apple for code-level support, but no one at Apple has responded to me in more than two weeks. So I'm turning to the community again for any help whatsoever.
I'm fairly certain it's a real bug in TextKit. If I'm right about that, I'd love for anyone at Apple to take an interest. And better yet, if I'm wrong (and I hope I am), I'd be incredibly grateful to anyone who can point out where my mistake lies! I've been stuck with this bug for weeks on end.
The crux of the issue is that I'm getting what seemed to be totally incompatible results from back to back calls to textContainer(forGlyphAt:effectiveRange:) and lineFragmentRect(forGlyphAt:effectiveRange:withoutAdditionalLayout:)... I'd lay out my text into a fairly tall container of standard page width and then query the layout manager for the text container and line fragment rect for a particular glyph (a glyph that happens to fall after many newlines). Impossibly, the layout manager would report that that glyph was in said very tall container, but that the maxY of its lineFragmentRect was only at 14 points (my NSTextView's isFlipped is true, so that's 14 points measuring from the top down).
After investigating, it appears that what is happening under the hood is NSLayoutManager is for some reason laying out text back into the first container in my series of containers, rather than overflowing it into the next container(s) and/or giving me a nil result for textContainer(forGlyphAt:...)
I've created a totally stripped down version of my project that recreates this issue reliably and I'm hoping literally anyone at Apple will respond to me. In order to recreate the bug, I've had to build a very specific set of preview data - namely some NSTextStorage content and a unique set of NSTextViews / NSTextContainers.
Because of the unique and particular setup required to recreate this bug, the code is too much to paste here (my preview data definition is a little unwieldy but the code that actually processes/parses it is not).
I can share the project if anyone is able and willing to look into this with me. It seems I'm not able to share a .zip of the project folder here but am happy to email or share a dropbox link.
Hi! I develop an iOS library and I met an issue with SwiftUI previews in iOS app project with my library integrated. After I open preview, build for preview finishes successfully, but preview itself never appears. I failed to find any error messages or any other indicators of what went wrong or how to fix it. Switching to legacy preview execution seems to fix problem, but I think that is not ideal. Could you help fixing this?
Xcode 16.2, Simulator iPhone 16, iOS 18.2
Project to reproduce -
https://drive.google.com/file/d/1cU6JKwshK_wQfe9YIqcMg3UGWq45OYlx/view?usp=sharing
Preview diagnostics - https://drive.google.com/file/d/1kPcgVSSqreiepGuqhdIoCW2rLSicgsWr/view?usp=sharing
I have arrived at a certain architectural solution for my SwiftUI code which is helped by, in certain situations, modifying the state while the body is being evaluated.
Of course, I am always open to realizing that a given solution may be creating difficulties precisely because it is fundamentally ill-advised. However, in this post I won't attempt to explain the details of my architecture or justify my reasoning regarding wanting to change the state in the middle of a view update. I just want to ask, why exactly is it prohibited? Is it not rather like normal recursion, which can of course produce infinite loops if done wrong but which is perfectly logically sound as long as the recursing function eventually stabilizes?
Topic:
UI Frameworks
SubTopic:
SwiftUI
In iOS 18.4.1, DocumentGroup contains the DocumentView twice. (this may cause issues with alerts)
To reproduce (iOS 18.4):
In XCode Version 16.3 (16E140), create new project. Choose iOS, "Document App". No need to make code changes.
Compile and run app on iOS 18.4 (simulator or device).
in iOS (sim or device): Tap create document (once the app launched).
in XCode: click "Debug View Hierarchy"
in XCode: rotate the view Hierarch to reveal duplicated Document View hierarchies (2 Document Hosting Controllers), see screenshot.
This probably affects alert view... I get warnings and it does not work properly (used to work ok on previous versions).
Previous versions
To compare with previous versions of iOS, run the same code and procedure on iOS 18.3 for example (see screenshot).
Will report on Feedback assistant as well...
I'm trying to implement the same UI used by the Settings app on iPad: a split view with two columns that are visible at all times.
This code produces the layout i want, but I would like to hide the "toggle sidebar visibility" button that the system introduces.
Is there a SwiftUI API I can use to hide this button? Maybe an alternate way to setup views that tells the system that the button is not necessary?
struct SomeView: View {
var body: some View {
NavigationSplitView(
columnVisibility: .constant(.all),
sidebar: { Text("sidebar") },
detail: { Text("detail") }
)
.navigationSplitViewStyle(.balanced)
}
}
I honestly thought I was getting somewhere with this, but alas, no. Every time I do anything in my List of ItemRows it jumps back to the top.
Here's the setup:
DataService.swift:
final class DataService {
static let shared = DataService()
private init() {}
let coreData: CoreData = CoreData()
let modelData: ModelData = ModelData()
}
ModelData.swift:
@Observable
class ModelData: ObservableObject {
var allItems: [ItemDetails]
var standardItems: [ItemDetails]
var archivedItems: [ItemDetails]
init() {
allItems = []
standardItems = []
archivedItems = []
}
func getInitialData() {
// Get all items, then split them into archived and non-archived sets, because you can't use `.filter` in a view...
allItems = dataService.coreData.getAllItems()
standardItems.append(contentsOf: allItems.filter { !$0.archived })
archivedItems.append(contentsOf: allItems.filter { $0.archived })
}
}
MainApp.swift:
// Get access to the data; this singleton is a global as non-view-based functions, including the `Scene`, need to access the model data
let dataService: DataService = DataService.shared
@main
struct MainApp: App {
// Should this be @ObservedObject or @StateObject?
@ObservedObject private var modelData: ModelData = dataService.modelData
// I would use @StateObject if the line was...
//@StateObject private var modelData: ModelData = ModelData() // right?
// But then I couldn't use modelData outside of the view hierarchy
var body: some Scene {
WindowGroup {
ZStack {
MainView()
.environment(modelData)
}
}
.onAppear {
modelData.getInitialData()
}
}
}
MainView.swift:
struct MainView: View {
@Environment(ModelData.self) private var modelData: ModelData
var body: some View {
...
ForEach(modelData.standardItems) { item in
ItemRow(item)
}
ForEach(modelData.archivedItems) { item in
ItemRow(item)
}
}
}
ItemRow.swift:
struct ItemRow: View {
@Environment(\.accessibilityDifferentiateWithoutColor) private var accessibilityDifferentiateWithoutColor
var item: ItemDetails
@State private var showDeleteConfirmation: Bool = false
var body: some View {
// Construct the row view
// `accessibilityDifferentiateWithoutColor` is used within the row to change colours if DWC is enabled, e.g. use different symbols instead of different colours for button images.
// Add the .leftSwipeButtons, .rightSwipeButtons, and .contextMenu
// Add the .confirmationDialog for when I want to ask for confirmation before deleting an item
}
}
Now, the problems:
Swipe an item row, tap one of the buttons, e.g. edit, and the list refreshes and jumps back to the top. In the console I see: ItemRow: @self, @identity, _accessibilityDifferentiateWithoutColor changed. Why did accessibilityDifferentiateWithoutColor change? The setting in Settings > Accessibility > Display & Text Size has not been changed, so why does the row's view think it changed?
With a .confirmationDialog attached to the end of the ItemRow (as seen in the code above), if I swipe and tap the delete button the list refreshes and jumps back to the top again. In the console I see: ItemRow: @self, @identity, _accessibilityDifferentiateWithoutColor, _showDeleteConfirmation changed. Right, it changed for the one row that I tapped the button for. Why does every row get redrawn?
I already had to shift from using the colorScheme environment variable to add new asset colours with light and dark variants to cover this, but you can't do that with DWC.
Honestly, managing state in SwiftUI is a nightmare. I had zero problems until iOS 26 started removing one or two rows when I scrolled, and the fix for that - using @Statebject/@ObservedObject - has introduced multiple further annoying, mind-bending problems, and necessitated massive daily refactorings. And, of course, plenty of my time islost trying to figure out where a problem is in the code because "The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions"...
It seems like it is no longer possible to open the main window of an app after the app has been launched by the system if the "Auto Start" functionality has been enabled.
I am using SMAppService.mainApp to enable to auto start of my app. It is shown in the macOS system settings and the app is automatically started - but the main window is not visible.
How can I change this behaviour so the main window of the app is always visible when started automatically?
I have not noticed this behaviour before the release of macOS Sequoia. My app is using Swift 6 and the latest version of macOS and Xcode.
Regards
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have a few view controllers in a large UIKit application that previously started showing content right below the bottom of the top navigation toolbar.
When testing the same code on iOS 26, these same views have their content extend under the navigation bar and toolbar. I was able to fix it with:
if #available(iOS 26, *, *) {
self.edgesForExtendedLayout = [.bottom]
}
when running on iOS 26. I also fixed one or two places where the main view was anchored to self.view.topAnchor instead of self.view.safeAreaLayoutGuide.topAnchor.
Although this seems to work, I wonder if this was an intended change in iOS 26 or just a temporary bug in the beta that will be resolved.
Were changes made to the safe area and edgesForExtendedLayout logic in iOS 26? If so, is there a place I can see what the specific changes were, so I know my code is handling it properly?
Thanks!
Topic:
UI Frameworks
SubTopic:
UIKit
We have encountered a problem on iOS 26. When switching to dark mode, the color of all subviews (font color, background color, etc.) of the Sidebar (Primary View) of UISplitViewController will not change. For example, if it is set to the color of UIColor.label, it will always be black and will not be white in dark mode.
On Xcode, just create a UISplitViewController in Storyboard without changing any settings, and run it directly to see the following:
The title of the Navigation Bar defaults to the label color, and it is still black after switching to dark mode.
There is no such problem in the Secondary View or other places.
This problem has occurred since iOS 26 beta 3, and iOS 26 beta 4 is now the same. But beta 1 and beta 2 have no problem.
I'm not sure if this is a bug, or if there is something that needs to be changed to adapt to iOS 26?
Hi,
I have added widgets to my iOS app and I would like to make this feature only accessible to "pro" users that have made a non-consumable in-app purchase.
Currently, I am doing the following: I store an "isUnlocked" property in the Keychain after the purchase is made
I read data to be displayed in the widget and here I also query the Keychain and store whether the widget is unlocked
I have no refresh policy, but only change the widget data on a significant time change
a different view is displayed when the app is locked
Some dummy code snippets:
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
		let entry = readContents()
		let timeline = Timeline(entries: [entry], policy: .never)
		completion(timeline)
}
struct WidgetEntryView: View {
		let entry: Provider.Entry
@Environment(\.widgetFamily) var family
@ViewBuilder
var body: some View {
switch family {
case .systemSmall:
if !entry.isUnlocked {
LockedWidgetView()
} else if let event = entry.event {
SmallWidgetEventView(event: event)
} else {
NoDataWidgetView()
}
...
func applicationSignificantTimeChange(_ application: UIApplication) {
		if #available(iOS 14.0, *) {
				WidgetCenter.shared.reloadAllTimelines()
		}
...
However, 2 unexpected things happen: the view is refreshed intraday (not only at midnight i.e. at significant time change)
sometimes the LockedWidgetView is displayed.
Especially the latter is problematic, because it gives false information to a user that has already made the in-app purchase.
How can I achieve my goal of only displaying info when the user has made the in-app purchase?
Thanks in advance.
P.S. Although it would not have my preference, I would also find it acceptable if the widget is only shown as option to add once the purchase is made. In other words, I was considering changing the Widget itself:
struct MyWidget: Widget {
private var supportedFamilies: [WidgetFamily] = isUnlocked() ? [.systemSmall, .systemMedium] : []
but I believe I cannot re-initialise the widget from the app when the user makes the in-app purchase, because the only refresh option that I have is
WidgetCenter.shared.reloadAllTimelines()
Hello,
I'm experiencing a navigation bar positioning issue with my UIKit iPad app on iPadOS 26 (23A340) using Xcode 26 (17A321).
The navigation bar positions under the status bar initially, and after orientation changes to landscape, it positions incorrectly below its expected location. This occurs on both real device (iPad mini A17 Pro) and simulator. My app uses UIKit + Storyboard with a Root Navigation Controller.
A stack overflow post has reproduce the bug event if it's not in the same configuration: https://stackoverflow.com/questions/79752945/xcode-26-beta-6-ipados-26-statusbar-overlaps-with-navigationbar-after-presen
I have checked all safe areas and tried changing some constraints, but nothing works.
Have you encountered this bug before, or do you need additional information to investigate this issue?
In my project, I am getting some text from backend which could have html tags. For this, I am converting the string to attributed string. However I noticed that when the string has html tags with color in it and when the text is displayed in toolbar, then the text displays with an ellipsis towards the end. Sharing code below:
import SwiftUI
struct ContentViewA: View {
@State private var displayText: AttributedString?
var body: some View {
NavigationStack {
VStack {
Text(displayText ?? "")
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button {
} label: {
Text("Done").font(.body.bold())
}
}
ToolbarItem(placement: .principal) {
Text(displayText ?? "")
}
}
.onAppear {
let string = "<div><p><span style=\"color:#FF0000;\">Hello World</span></p></div>"
displayText = string.convertToAttributedString
/// Note: If I don't set the font, then the ellipsis are not displayed in the toolbar, but I need this font style.
displayText?.font = .body.bold()
}
}
}
}
extension String {
var convertToAttributedString: AttributedString? {
guard let data = data(using: .utf8) else { return nil }
var attributedString: AttributedString?
if let nsAttributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue],
documentAttributes: nil) {
attributedString = try? AttributedString(nsAttributedString, including: \.uiKit)
}
return attributedString
}
}
I am printing displayText in the body of the view and am not seeing ellipsis at the end of the string, but in toolbar, I am seeing ellipsis. I am unable to figure out what's causing this and what can be the fix for it. However, if I avoid setting the font on attributed string, then the ellipsis are not displayed in toolbar. However, I need to set the string to a specific font style.
How can I avoid ellipsis in toolbar and while also setting the required font on the string?
Topic:
UI Frameworks
SubTopic:
SwiftUI
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic:
UI Frameworks
SubTopic:
SwiftUI
An WWDC 25 a neutral value was demonstrated that allows the Slider to be 'coloured in' from the point of the neutral value to the current thumb position. Trying to use this in Dev release 1 I get errors saying no such modifier.
Was this functionality released in Dev Release 1 or am I using it incorrectly?
Dear Sirs,
I'm writing an audio application that should show up to 128 horizontal peakmeters (width for each is about 150, height is 8) stacked inside a ScrollViewReader. For the actual value of the peakmeter I have a binding to a CGFloat value. The peakmeter works as expected and is refreshing correct. For testing I added a timer to my swift application that is firing every 0.05 secs, meaning I want to show 20 values per second. Inside the timer func I'm just creating random CGFloat values in range of 0...1 for the bound values. The peakmeters refresh and flicker as expected but I can see a CPU load of 40-50% in the activity monitor on my MacBook Air with Apple M2 even when compiled in release mode. I think this is quite high and I'd like to reduce this CPU load. Should this be possible? I.e. I thought about blocking the refresh until I've set all values? How could this be done and would it help? What else could I do?
Thanks and best regards,
JFreyberger
The example code below shows what I am trying to achieve: When the user types a '*', it should be replaced with a '×'.
It looks like it works, but the cursor position is corrupted, even though it looks OK, and the diagnostics that is printed below shows a valid index. If you type "12*34" you get "12×43" because the cursor is inserting before the shown cursor instead of after.
How can I fix this?
struct ContentView: View {
@State private var input: String = ""
@State private var selection: TextSelection? = nil
var body: some View {
VStack {
TextField("Type 12*34", text: $input, selection: $selection)
.onKeyPress(action: {keyPress in
handleKeyPress(keyPress)
})
Text("Selection: \(selectionAsString())")
}.padding()
}
func handleKeyPress(_ keyPress: KeyPress) -> KeyPress.Result {
if (keyPress.key.character == "*") {
insertAtCursor(text: "×")
moveCursor(offset: 1)
return KeyPress.Result.handled
}
return KeyPress.Result.ignored
}
func moveCursor(offset: Int) {
guard let selection else { return }
if case let .selection(range) = selection.indices {
print("Moving cursor from \(range.lowerBound)")
let newIndex = input.index(range.lowerBound, offsetBy: offset, limitedBy: input.endIndex)!
let newSelection : TextSelection.Indices = .selection(newIndex..<newIndex)
if case let .selection(range) = newSelection {
print("Moved to \(range.lowerBound)")
}
self.selection!.indices = newSelection
}
}
func insertAtCursor(text: String) {
guard let selection else { return }
if case let .selection(range) = selection.indices {
input.insert(contentsOf: text, at: range.lowerBound)
}
}
func selectionAsString() -> String {
guard let selection else { return "None" }
switch selection.indices {
case .selection(let range):
if (range.lowerBound == range.upperBound) {
return ("No selection, cursor at \(range.lowerBound)")
}
let lower = range.lowerBound.utf16Offset(in: input)
let upper = range.upperBound.utf16Offset(in: input)
return "\(lower) - \(upper)"
case .multiSelection(let rangeSet):
return "Multi selection \(rangeSet)"
@unknown default:
fatalError("Unknown selection")
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
I had a problem with my app (or in my setup) and searching the web I found a very simple code where part of my problem occurs.
I create a new Multiplatform App and
paste this code in ContentView.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
Text("Navigation article")
.font(.title)
.padding()
NavigationLink("Go to the second view", destination: SecondView())
.padding()
}
.navigationTitle("First View")
}
}
}
struct SecondView: View {
var body: some View {
Text("This is the Second view")
.font(.headline)
.padding()
.navigationTitle("Second View")
}
}
run on iPhone/ iOS no problem
run on a Mac/macOS
Going from view 1 to view 2 work, the back arrow on view 2 is there, and it is working but the second time I go to the view 2, the back arrow is gone.
after looking closely I can see the Arrow Underneath the S of SecondView.
I have tried many things and could not make it work.
I post this in a HackingWithSwift forum and somebody tried the code and said it work. so it seems the problem could be related to my setup but I create another user in my computer , same problem and tried it on my another computer, same problem.
Topic:
UI Frameworks
SubTopic:
SwiftUI