I am trying to integrate the new iOS 18 document launching experience with my app, but opening or saving files fails with the RC version of Xcode 16. The error I receive is "Publishing changes from background threads is not allowed."
I downloaded Apple's new sample code ("Writing app"), and it fails with the same error.
Is there an easy fix for this?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
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.
I'm experiencing an issue where my app freezes when built with Xcode 16 on iOS 18.
Additional Information:
The issue does not occur when building the app with Xcode 16 on iOS 17 or lower.
The issue does not occur when building the app with Xcode 15 on iOS 18.
The CPU usage spikes to 100% when the app freezes.
The app specifically freezes after the code runs into .sink(receiveValue:).
Here is the relevant code snippet:
@Published var selectedCardData: CardData?
@Published var selectedRootTab: RootViewTab = .statement
override func load() {
state = .loading
$selectedCardData.ignoreNil()
.removeDuplicates()
.map { [unowned self] cardData in
$selectedRootTab.filter { $0 == .statement }
.first()
.map { _ in cardData }
}
.switchToLatest()
.sink(receiveValue: { value in
print(value) // value not nil
print("Execution reaches this point and the app freezes (CPU 100%).")
})
.store(in: &cancellables)
}
Are there any known changes in iOS 18 or Xcode 16 that might affect this code?
I'm trying to add a ControlWidget to my WidgetBundle like this:
struct MyWidgets: WidgetBundle {
var body: some Widget {
if #available(iOSApplicationExtension 18.0, *) {
LauncherControl()
}
MyLiveActivityWidget()
HomeScreenWidget()
LockScreenWidget()
}
This works exactly as expected on iOS 18. However on iOS 17 my app seems to have no widgets at all.
The workaround described here (https://www.avanderlee.com/swiftui/variable-widgetbundle-configuration/) does not work either since WidgetBundleBuilder.buildBlock does not accept ControlWidget as an argument.
What is the correct way to include a Control widget conditionally on iOS 18?
I've been experiencing random crashes in my app and today, I could finally narrow it down enough to start building an example project that consistently crashes. The error is this:
"com.apple.SwiftUI.AsyncRenderer (19): EXC_BREAKPOINT (code=1, subcode=0x102f103f8)"
It's a very strange bug because the SwiftUI view hierarchy has to be in a very specific shape to cause the crash, but if it is, then it crashes 100% of the time:
It's a button inside a List and a simple "@State var number: Int?" that is being animated when the view appears. You can simply paste the following code into a project and run it (device, simulator or even in a preview):
// Must be in Swift 6 Language Mode!
// iOS 18 Beta 4
struct ContentView: View {
@State var number: Int?
var body: some View {
List { // Must be in a List
// It also crashes if button is here inside the List
}
.overlay {
button
}
.task { // Has to be in a task modifier (or .onAppear + Task {}, so it has to be async)
number = 0
}
}
// Has to be in a separate view property
private var button: some View {
Button {} label: { // Has to be this initializer and not Button(number == nil ? "" : "") {}
if number == nil { // There has to be a conditional with "number" in here
Color.clear
}
}
.animation(.default, value: number) // Animation must be inside the List
.alignmentGuide(VerticalAlignment.center) { dimension in
dimension[VerticalAlignment.center]
}
}
}
The crash only happens under the following conditions, as far as I can tell:
This only happens in the Swift 6 language mode (which I have enabled in the example project)
It's related to an .alignmentGuide modifier attached to a button that also has an .animation modifier
The button has to have a conditional view inside its label that checks for the same variable that is being animated
The button must be inside a separate property that is put either inside a List or inside an overlay of a List
The crash is then triggered when the animated value is asynchronously changed (in a .task modifier for example)
The crash happens at least with Beta 3 and 4 of Xcode 16.0
I have also opened a feedback: FB14510236 but I thought I'd post it here as well because this crash was driving me crazy and maybe others might find it helpful for their debugging. Took me hours to find out what's been causing it 😅
Edit:
Interestingly, when I run this project on an iOS 17 device, it does not crash, but rather print a runtime warning:
"warning: data race detected: @MainActor function at AlignmentGuideCrash/ContentView.swift:27 was not called on the main thread"
Line 27 is:
.alignmentGuide(VerticalAlignment.center) { dimension in
I'm trying to accomplish something like this:
https://x.com/mlaithv/status/1835041850236838265
But it seems like Apple uses a Private API to pull it off. Has anyone managed to create something similar? I know there is a package named Transmission that can do it but it seems hacky & I'm unfamiliar with UIKit. The source uses a "custom modal" but I'm not sure how.
In the customizationID modifier of the TabView, if I use an ID with a SwiftData value, it returns the following error when I open a new window on iPadOS: “Not unique” even when using a UUID. I can't do anything about it, so I'm posting it here.
Any advice that could help me on the way to solving this problem would be appreciated.
Thread 1: "Fatal: supplied item identifiers are not unique. Duplicate identifiers: {(\n "Tab.Custom.1C350509-C28A-4C41-85A0-3EA57779DB1B"\n)}"
Below is a portion of the code that reproduces this phenomenon. I believe it is sufficient for your needs, but if you need more code, we can accommodate.
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@Query private var tags: [Tag]
@AppStorage("Customization") private var customization: TabViewCustomization
@State private var isAdding = false
@State private var tagName = ""
var body: some View {
TabView {
Tab("Home", systemImage: "house") {
NavigationStack {
Label("Home", systemImage: "house")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
isAdding.toggle()
} label: {
Label("Add Tag", systemImage: "plus")
}
}
}
}
}
.customizationID("Tab.Home")
Tab("Workplace", systemImage: "building.2") {
NavigationStack {
Label("Workplace", systemImage: "building.2")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
isAdding.toggle()
} label: {
Label("Add Tag", systemImage: "plus")
}
}
}
}
}
.customizationID("Tab.Workplace")
Tab("Apple Store", systemImage: "apple.logo") {
NavigationStack {
Label("Apple Store", systemImage: "apple.logo")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
isAdding.toggle()
} label: {
Label("Add Tag", systemImage: "plus")
}
}
}
}
}
.customizationID("Tab.AppleStore")
TabSection {
ForEach(tags) { tag in
Tab(tag.name, systemImage: "tag") {
NavigationStack {
Label(tag.name, systemImage: "tag")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
isAdding.toggle()
} label: {
Label("Add Tag", systemImage: "plus")
}
}
}
}
}
.customizationID("Tab.Custom.\(tag.id.uuidString)")
}
} header: {
Label("Custom", systemImage: "tag")
}
.customizationID("TabSection.AppleStore")
.sectionActions {
Button {
isAdding.toggle()
} label: {
Label("Add Tag", systemImage: "plus")
}
}
}
.tabViewCustomization($customization)
.tabViewStyle(.sidebarAdaptable)
.alert("Create Tag", isPresented: $isAdding) {
TextField("Tag Name", text: $tagName)
Button("Cancel") {
tagName = ""
isAdding = false
}
Button("Done") {
let tagList = tagName.components(separatedBy: .whitespaces)
for tagItem in tagList {
if tagItem != "" && tags.filter({return $0.name == tagItem}).isEmpty {
let newTag = Tag(name: tagItem)
modelContext.insert(newTag)
}
}
try? modelContext.save()
tagName = ""
isAdding = false
}
}
}
}
import SwiftData
import Foundation
@Model
final class Tag: Identifiable {
var id: UUID = UUID()
var name: String = ""
init(name: String) {
self.id = UUID()
self.name = name
}
}
How to reproduce
Implement the above code so that it works.
Build the application on the actual iPad device using Xcode.
Add tags (data)
Open a new window and check the UI behavior.
Correct Behavior
The ID is not actually unique. Or, if it is unique, it should not freeze without generating an error.
Actual Behavior
The ID should be set to be unique, but it freezes with an error that it is not unique.
Environment
iPadOS 18 RC (22A3354)
Xcode 16.0 (16A242)
Hi,
Some times long text damage the design of views it might go to a second row and increase view height and damage the overall design, so how to solve this issue, is there a way to set a Max Characters number for Text and TextField views in SwiftUI ? and maybe show few dots as used in some designs ?
Kind Regards
I am currently working on a comments section modeled after TikTok's/Instagram's comment sections for a media app. The view is a sheet view that is presented as follows:
.sheet(isPresented: $showChat) {
TakesChatView(viewModel: viewModel)
.presentationDetents([.medium, .large])
.presentationDragIndicator(.hidden)
.overlay(
VStack {
RoundedRectangle(cornerRadius: 2)
.fill(Color.gray)
.frame(width: 40, height: 5)
.padding(.top, 15)
.opacity(0.8)
Label("Chat", systemImage: "message.badge")
.lineLimit(nil)
.padding(.top, 5)
.padding([.leading, .trailing], 16)
Divider()
.padding(.top, 5)
.padding([.leading, .trailing], 16)
Spacer()
}
.frame(maxWidth: .infinity, alignment: .top)
)
}.ignoresSafeArea(.keyboard, edges: .bottom)
However, some issues arise regarding keyboard avoidance. Currently, when the user taps on the TextField to type a comment, the keyboard shifts the entire view upwards as it pops up. Instead, I need it where I can still view the comments without the keyboard affecting their placement when it pop up.
Below is the associated code for the comment view:
struct TakesChatView: View {
@ObservedObject var viewModel: TakeCommentViewModel
@FocusState var focus: Bool
@State private var selectedMedia: [PhotosPickerItem] = []
@State private var selectedImageData: [Data] = []
@State private var selectedGIFData: [Data] = []
@State private var selectedVideoData: [Data] = []
var textFieldNotEmpty: Bool {
!viewModel.textToPost.isEmpty ||
!selectedImageData.isEmpty ||
!selectedGIFData.isEmpty ||
!selectedVideoData.isEmpty
}
var body: some View {
GeometryReader { _ in
ZStack {
VStack {
contentView
commentTextField
.padding(.top,5)
}
}
}
.ignoresSafeArea(.keyboard, edges: .bottom)
.background(Color.containerBackground)
.onChange(of: viewModel.focus) { focus in
self.focus = focus
}
.onChange(of: selectedMedia) { _ in
loadMedia()
}
}
var contentView: some View {
VStack {
Spacer().frame(height: 105)
ScrollViewReader { scroll in
ScrollView(showsIndicators: true) {
ForEach(viewModel.comments, id: \.self) { comment in
TakeCommentView(
comment: comment,
viewModel: self.viewModel
)
.padding(.horizontal, 10)
.id(comment.documentID)
}
.onChange(of: viewModel.commentAdded) { id in
scroll.scrollTo(id, anchor: .bottom)
viewModel.commentAdded = nil
}
}
.scrollDismissesKeyboard(.immediately)
}
}
}
}
extension TakesChatView {
var commentTextField: some View {
VStack {
mediaPreview
HStack {
TextField("Type your comment", text: $viewModel.textToPost, axis: .vertical)
.keyboardType(.twitter)
.padding([.leading, .vertical], 6)
.focused($focus)
PhotosPicker(selection: $selectedMedia, matching: .any(of: [.images, .videos]), photoLibrary: .shared()) {
ComposeType.media.image
.frame(width: 40, height: 40, alignment: .center)
}
.onAppear {
selectedMedia.removeAll()
selectedImageData.removeAll()
selectedGIFData.removeAll()
selectedVideoData.removeAll()
}
postButton
}
.border(.lightGray, width: 1, cornerRadius: 10)
.padding([.bottom, .horizontal], 10)
}
}
}
I have tried using .ignoresSafeAres(), .safeAreaInset(), and custom keyboard observer functions but to no avail. How do I fix this issue?
I have a small text file which I would like to share via ShareLink with watchOS. If I try to share the text file via Mail oder iMessage the recipient only receives the message without the attachment. The same code works without problems on iOS. Is the is watchOS bug?
I'm trying to create an equivalent to TabView, but with the difference that the 2nd View slides in over the top of the primary view.
Maybe there's a more elegant way of coding this (suggestions appreciated), but I've almost succeeded using the dragGesture. When a user swipes right to left the observed variable showTab2 is set to true, and the 2nd tab glides in over the top of tab 1 and displays 🥳.
The only problem is, that when a user happens to start the swipe over a button, the observed status (showTab2) does change as expected but the main view does not catch this change and does not display tab2. And that despite the showTab2 being an @Observable.
Any clues what I've missed? Or how to capture that the start of a swipe gesture starts over the top of a button and should be ignored.
According to the code in SwipeTabView this screenshot 👆 should never occur.
Here's the code:
@Observable
class myclass {
var showTab2 = false
}
struct SwipeTabView: View {
@State var myClass = myclass()
@State var dragAmount: CGSize = CGSize.zero
var body: some View {
VStack {
ZStack {
GeometryReader { geometryProxy in
VStack {
tab(tabID: 1, selectedTab: myClass.showTab2)
.zIndex(/*@START_MENU_TOKEN@*/1.0/*@END_MENU_TOKEN@*/)
.background(.black)
.transition(.identity)
.swipeable(stateOfViewAdded: $myClass.showTab2, dragAmount: $dragAmount, geometryProxy: geometryProxy, insertion: true)
}
if myClass.showTab2 || dragAmount.width != 0 {
tab(tabID: 2, selectedTab: myClass.showTab2)
.zIndex(2.0)
.drawingGroup()
.transition(.move(edge: .trailing))
.offset(x: dragAmount.width )
.swipeable(stateOfViewAdded: $myClass.showTab2, dragAmount: $dragAmount, geometryProxy: geometryProxy, insertion: false)
}
}
}
}
}
}
extension View {
func swipeable(stateOfViewAdded: Binding<Bool>,
dragAmount: Binding<CGSize>,
geometryProxy: GeometryProxy,
insertion: Bool) -> some View {
self.gesture(
DragGesture()
.onChanged { gesture in
// inserting must be minus, but removing must be positive - hence the multiplication.
if gesture.translation.width * (insertion ? 1 : -1 ) < 0 {
if insertion {
dragAmount.wrappedValue.width = geometryProxy.size.width + gesture.translation.width
} else {
dragAmount.wrappedValue.width = gesture.translation.width
}
}
}
.onEnded { gesture in
if abs(gesture.translation.width) > 100.0 && gesture.translation.width * (insertion ? 1 : -1 ) < 0 {
withAnimation(.easeOut.speed(Double(gesture.velocity.width))) {
stateOfViewAdded.wrappedValue = insertion
}
} else {
withAnimation(.easeOut.speed(Double(gesture.velocity.width))) {
stateOfViewAdded.wrappedValue = !insertion
}
}
withAnimation(.smooth) {
dragAmount.wrappedValue = CGSize.zero
}
}
)
}
}
struct tab: View {
var tabID: Int
var selectedTab: Bool
var body: some View {
ZStack {
Color(tabID == 1 ? .yellow : .orange)
VStack {
Text("Tab \(tabID) ").foregroundColor(.black)
Button(action: {
print("Tab2 should display - \(selectedTab.description)")
}, label: {
ZStack {
circle
label
}
})
Text("Tab2 should display - \(selectedTab.description)")
}
}
}
var circle: some View {
Circle()
.frame(width: 100, height: 100)
.foregroundColor(.red)
}
var label: some View {
Text("\(tabID == 1 ? ">>" : "<<")").font(.title).foregroundColor(.black)
}
}
Hello,
I found that if you apply the new .sidebarAdaptable tab view style, the accessibility identifiers of tab bar buttons are missing.
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
Tab("Received", systemImage: "tray.and.arrow.down.fill") {
Text("Received")
}
.accessibilityIdentifier("tab.received") // 👀
Tab("Sent", systemImage: "tray.and.arrow.up.fill") {
Text("Sent")
}
.accessibilityIdentifier("tab.sent") // 👀
Tab("Account", systemImage: "person.crop.circle.fill") {
Text("Account")
}
.accessibilityIdentifier("tab.account") // 👀
}
.tabViewStyle(.sidebarAdaptable) // 👈 if remove this, ax identifiers are ok
}
}
#Preview {
ContentView()
}
The identifiers automatically appear after a few seconds. But this behaviour breaks a lot of the UI test cases.
I have created a paging app With SwiftUI TabView with TabViewStyle: PageTabViewStyle. In every page there is an UICollectionView holding a list of rows. Now I have used UIViewControllerRepresentable to show the view inside TabView.
It works okay, but the Scroll to top gesture doesn't work here when pressed in the iPhones StatusBar.
Is it a fault of TabView or I am missing Something?
It may happen because of TabViews Scroll property. In UIKIT Views We needed to disable the scrollToTop property of scrollviews (Other then the desired one) is there any public API's for SwiftUI Views in replacement for setting scrollsToTop property?
When I copy and paste example code in apple developer documentation, LongPressGesture does not work as expected in Xcode Version 16.0 (16A242) and iOS 18. It seems updating(_:body:) method does not work when used with LongPressGesture.
When I make a breakpoint in updating(_:body:) method and long press the blue circle on the screen of simulator(or device), it is expected to be caught in breakpoint or it is expected that color of circle turns from blue to red to green. However, it is not caught in breakpoint and never turns to red.
Question of Stackoverflow is about same issue and I can not use onLongPressGesture method to implement required feature of my app.
Development environment: Xcode Version 16.0 (16A242), macOS 14.5
Run-time configuration: iOS 18.0
Info
watchOS: 11.0 (22R5348a) *Though has been present since watchOS 10.
Issue: Other apps playing music cancel out WKHaptics from firing (low volume and no vibrations)
Description
When another app is playing music (ex: spotify) in the background while using my app, that uses WKHaptics. The WKHaptics vibrations are non existent as long as headphones are connected.
When the headphones are disconnected the vibrations return.
Test
MVP test app >> https://github.com/mazefest/AppleCodeSupportTestApp
import SwiftUI
extension Int: Identifiable {
public var id: Int { return self }
}
struct ContentView: View {
@State var shareSheet: Bool = false
@State var selectedNo : Int?
var body: some View {
VStack {
ForEach(0..<2, id: \.self, content: { rowNo in
Text("world \(rowNo)")
Button(action: {
shareSheet.toggle()
selectedNo = rowNo
}) {
Text("Go to world\(rowNo)")
}
})
}
.padding()
.sheet(item: $selectedNo) { row in
// BUG: when replacing 'row' below with 'selectedNo' nil is passed.
ShareView(message:"Hello \(row)" )
}
}
struct ShareView: View {
let message: String
var body: some View {
Text(message)
}
}
}
Hello, I am working on an application that utilizes both AppDelegate and SceneDelegate. We are looking to convert the top level app to SwiftUI and start using the SwiftUI App lifecycle. When implementing, I see that deep links when the app is backgrounded will only route to the onOpenURL modifier. This means that information we relied on before like referrerURL and annotation present in the NSUserActivity object delivered to the app is no longer available. Is there any work around for this? It seems like missing functionality because there is no way to route the deep links through AppDelegate or SceneDelegate if you are using the SwiftUI App protocol.
When adding more than 7 items, the Tab bar wiggles or may not reappear when switching back to it. Is this a bug? or could this be a problem with focus management? or any other cause?
Tried sample code https://developer.apple.com/documentation/swiftui/enhancing-your-app-content-with-tab-navigation
var body: some View {
VStack {
List {
ForEach(starSigns) {ZodiacSign in
NavigationLink(destination: ZodiacSign.DestinationView) {
Text(ZodiacSign.Symbol)
Text(ZodiacSign.name)
}
}
}
}
}
}
I have this basic view which gets information from a list I created, but how do I get the destination view to work where an example of it would be AriesView(), I would like the destination to be there. Currently it comes up with an error of "Protocol 'View ' cannot conform to the protocol itself"
Sorry for the complexity of this question, I was struggling to explain it.
THANK YOU IN ADVANCE!!!
When using PhotosPicker in SwiftUI to let users pick a photo, it will fail to load after switching to the "Collections" tab on iOS 18. This issue doesn't occur on iOS 17. Additionally, using PHPickerViewController will still have the same issue.
The code is pretty simple:
struct ContentView: View {
@State private var selection: PhotosPickerItem? = nil
var body: some View {
VStack {
PhotosPicker("Pick photo", selection: $selection)
}
.padding()
}
}
And I create a repo for this code: https://github.com/JuniperPhoton/PhotosPickerIssueiOS18
This issue has been reported via Feedback app, and the report ID is FB15069998.
I tested in the Xcode 16 Beta 6 and iOS 18 Beta 8. However with the Xcode 16 RC and the iOS 18 RC, this issue still exists.
Hoping to find out any workaround to resolve this issue. Thanks.