Did you change datum to a simple var and not a State var ?
Could you show the complete code, to see how Binding is used.
Logically,
@Binding var index: Int
should be in the ContentView
and the
@State var index = 0
in the other view
But I would need to check.
PS: don't forget to close the thread, eventually starting a new one where you reference this one.
Post
Replies
Boosts
Views
Activity
Another point.
In DataView, index should not be a State variable.
Add a button in ContentView
VStack {
if showView && (index >= 0) && (index < data.count) {
DataView(datum: data[index])
}
Spacer()
HStack {
Text("Index: \(index) -> ")
Button("Next") {
index += 1
if index >= data.count { index = 0 }
}
}
}
You will see that text in DataView does not change
Text("DataView \(datum.str)")
always says DataView String 1
Now change DataView as follows to get it updated on index change by button press:
struct DataView: View {
/*@State*/ var datum: Data2
var body: some View {
Text("DataView \(datum.str)")
}
}
Note: I renamed data to datum for an array item, to differentiate from the array.
Now, I have to update my initial answer.
In fact, no need for showView and Dispatch (even though that made it work).
Just test index:
if (index < data.count) {
DataView(datum: data[index])
Without the index test, it crashes…
Swift/ContiguousArrayBuffer.swift:691: Fatal error: Index out of range
Reason is that DataView is not called immediately but only when State var data is populated by getData (then count changes) and has all its elements.
So the test has a similar effect as Dispatch to wait for data to be fetched.
It is a question of timing.
When onAppear returns, and DataView is called, the array is not yet populated, even though its count is already OK.
You have to wait for a short time in onAppear (0.01 s should be OK).
Here is the solution.
I had to rename Data to avoid the error above (Data is a Foundation type). I renamed to Data2
struct Data2: Decodable, Hashable {
let index: Int
let str: String
}
struct DataView: View {
@State var data: Data2
var body: some View {
Text("DataView \(data.str)")
}
}
struct ContentView: View {
@State var showView = false // To wait for array to be populated before we display the view
@State var data: [Data2]
@State var index: Int = 0
var body: some View {
VStack {
if showView {
DataView(data: data[index])
// Text("Hello \(data.count)") // To test if needed ; without async, data.count is 2. Seems OK, but…
// Text("Hello \(data.count) index \(index) \(data[0].str)") // but without async, it will crash, as data is not populated yet, even if count is already 2
}
}
.onAppear {
let filePath = Bundle.main.path(forResource: "data", ofType: "json")
let url = URL(fileURLWithPath: filePath!)
data = getData(url: url)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <<-- THE KEY POINT 0.1 sec delay
self.showView = true
}
}
}
func getData(url: URL) -> [Data2] {
do {
let data = try Data(contentsOf: url)
let jsonDecoded = try JSONDecoder().decode([Data2].self, from: data)
return jsonDecoded
} catch let error as NSError {
print("Fail: \(error.localizedDescription)")
} catch {
print("Fail: \(error)")
}
return []
}
}
Credit: https://stackoverflow.com/questions/62355428/how-do-i-show-a-new-view-after-some-delay-amount-of-time-swiftui
A simpler option is to use an init:
struct ContentView: View {
@State var data: [Data2]
@State var index: Int = 0
init() {
let filePath = Bundle.main.path(forResource: "data", ofType: "json")
let url = URL(fileURLWithPath: filePath!)
// data = getData(url: url) // We cannot call getData in init
do {
let dataRead = try Data(contentsOf: url)
let jsonDecoded = try JSONDecoder().decode([Data2].self, from: dataRead)
data = jsonDecoded
return
} catch let error as NSError {
print("Fail: \(error.localizedDescription)")
} catch {
print("Fail: \(error)")
}
data = []
return
}
var body: some View {
VStack {
DataView(data: data[index])
}
}
}
Thanks.
But your code does not compile, with the following errors:
Does it compile for you ?
I succeeded moving Xcode 16.4, MacMini, MacOS 15.6 (24G84):
Here is the initial tabbar
I click on the tabor in the TabBarController
it turns blue
I click on icon of item 1 and start dragging (I had to take care to hold the mouse pressed). A position caret appears (I cannot screenshot the caret) and icon starts to move and the other to rearrange
I move the caret (and the icon) to the desired position) and drop it
The icons are reordered
If that's OK, don't forget to close the thread on this answer ; otherwise please explain where it fails.
As you noticed, there is another way to do it, by creating the segues in desired order.
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
Could you provide complete code as well as the json file ?
Is Data a structure you have defined ?
If it is an empty set, it should crash at:
DataView(data: data[index])
Do you get Fail messages ?
Problem is not in onAppear. I tested by replacing getData by a dummy call
.onAppear {
// let filePath = Bundle.main.path(forResource: "data", ofType: "json")
// let url = URL(fileURLWithPath: filePath!)
//
// data = getData(url: url)
data = [Data()]
}
And data DataView is not empty, as I could check with the following
struct DataView: View {
@State var data: Data
var body: some View {
Text("DataView \(data)")
}
}
So, it looks like you return from getData by line 29 and not 22.
So, could you change line 29, to return a custom single data to check ?
Did you try to set the placement, such as:
.searchable(text: $searchText, isPresented: $isSearchPresented, placement: .navigationBarDrawer, prompt: "Search...")
Topic:
UI Frameworks
SubTopic:
UIKit
Tags:
Welcome to the forum.
Could you show (screenshots) what you get and what you'd expect.
And please also post the complete code.
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags:
@Ed Ford, for this useful clarification.
So that means there is no urgency to switch to Swift 6 mode, unless of course there are concurrency issues or we need specific Swift 6 feature ?
I understand however that it is wise to set concurrency checking at the max level, even in Swift 5 mode. Is it correct ?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
@eskimo
that was when testing with Swift6 and Xcode 16.4.
But after encapsulating the code using IBOutlet in
MainActor.assumeIsolated({
// using textField.text
})
I could remove the nonIsolated declaration for IBOutlet and get it working.
Unfortunately, I've not kept a version to reproduce the error.
In any case, I will not switch to Swift6 before using Xcode 26.
Topic:
Programming Languages
SubTopic:
Swift
Tags:
Logically, users would receive an error message from your app if backend is off.
In any case, if you don't update the app for 3 years, it will be removed automatically.
May be the best is just to wait ?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
No feedback. Closing the thread.
Topic:
Developer Tools & Services
SubTopic:
Apple Developer Program
Tags:
@Engineer
Thanks for reply. Some more crash info. On simulator (did not test on device at this stage).
Here is crash report:
Error occurs in #4 notifyMe IBAction
@IBAction func notifyMe(_ sender: UIButton) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined {
center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
DispatchQueue.main.async {
if !granted {
// Alert user
}
}
}
} else if settings.authorizationStatus == .denied {
DispatchQueue.main.async {
// Alert user
}
} else if settings.authorizationStatus == .authorized {
DispatchQueue.main.async {
self.alarmButton.isHidden = self.duree <= 120
}
}
})
var alertStyle = UIAlertController.Style.alert
let alertController = UIAlertController(
title: NSLocalizedString("M'avertir", comment: ""),
message: NSLocalizedString("Attention", comment: ""), preferredStyle: alertStyle)
var title = NSLocalizedString("5'", comment: "")
let ok = UIAlertAction(title: title, style: .default, handler: {(action) -> Void in
self.sendInitialNotification(beforeEnd: 5)
DispatchQueue.main.async { sender.isHidden = true }
})
alertController.addAction(ok)
let cancelAction = UIAlertAction(title: NSLocalizedString("Non", comment: ""), style: .default, handler: { (action) -> Void in
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
Crash apparently occurs on calling userNotificationCenter:
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if notification.request.identifier == requestIdentifier {
completionHandler( [.alert,.sound,.badge])
}
}
Topic:
App & System Services
SubTopic:
Notifications
Tags:
Thanks Quinn.
I removed the nonisolated for IBOutlet.
But, as shown in your example, I had to mark all func în a class that uses UNUserNotificationCenterDelegate as nonIsolated, such as
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
I also note in your example that you marked response for didReceive as async.
I tried to, but got the error:
Instance method 'userNotificationCenter(_:didReceive:withCompletionHandler:)' nearly matches optional requirement 'userNotificationCenter(_:didReceive:withCompletionHandler:)' of protocol 'UNUserNotificationCenterDelegate'
with the advice to
Make 'userNotificationCenter_:didReceive:withCompletionHandler:)' private to silence this warning
Converting to Swift 6 is definitely not an easy ride…
I'll do extensive testing.
Topic:
Programming Languages
SubTopic:
Swift
Tags:
Thanks for the answer.
didReceive was already non isolated. So problem likely does not come from here.
For willPresent, if I don't make it nonIsolated, I get an Xcode 16.4 compiler error:
Main actor-isolated instance method 'userNotificationCenter(_:willPresent:withCompletionHandler:)' cannot be used to satisfy nonisolated requirement from protocol 'UNUserNotificationCenterDelegate'
n Xcode 26, no error in func declaration if I remove nonIsolated.
But error at UIViewController class definition level
Conformance of 'CalcViewController' to protocol 'UNUserNotificationCenterDelegate' crosses into main actor-isolated code and can cause data races
Topic:
App & System Services
SubTopic:
Notifications
Tags:
Did you change datum to a simple var and not a State var ?
Could you show the complete code, to see how Binding is used.
Logically,
@Binding var index: Int
should be in the ContentView
and the
@State var index = 0
in the other view
But I would need to check.
PS: don't forget to close the thread, eventually starting a new one where you reference this one.
- Replies
- Boosts
- Views
- Activity
Another point.
In DataView, index should not be a State variable.
Add a button in ContentView
VStack {
if showView && (index >= 0) && (index < data.count) {
DataView(datum: data[index])
}
Spacer()
HStack {
Text("Index: \(index) -> ")
Button("Next") {
index += 1
if index >= data.count { index = 0 }
}
}
}
You will see that text in DataView does not change
Text("DataView \(datum.str)")
always says DataView String 1
Now change DataView as follows to get it updated on index change by button press:
struct DataView: View {
/*@State*/ var datum: Data2
var body: some View {
Text("DataView \(datum.str)")
}
}
Note: I renamed data to datum for an array item, to differentiate from the array.
Now, I have to update my initial answer.
In fact, no need for showView and Dispatch (even though that made it work).
Just test index:
if (index < data.count) {
DataView(datum: data[index])
Without the index test, it crashes…
Swift/ContiguousArrayBuffer.swift:691: Fatal error: Index out of range
Reason is that DataView is not called immediately but only when State var data is populated by getData (then count changes) and has all its elements.
So the test has a similar effect as Dispatch to wait for data to be fetched.
- Replies
- Boosts
- Views
- Activity
It is a question of timing.
When onAppear returns, and DataView is called, the array is not yet populated, even though its count is already OK.
You have to wait for a short time in onAppear (0.01 s should be OK).
Here is the solution.
I had to rename Data to avoid the error above (Data is a Foundation type). I renamed to Data2
struct Data2: Decodable, Hashable {
let index: Int
let str: String
}
struct DataView: View {
@State var data: Data2
var body: some View {
Text("DataView \(data.str)")
}
}
struct ContentView: View {
@State var showView = false // To wait for array to be populated before we display the view
@State var data: [Data2]
@State var index: Int = 0
var body: some View {
VStack {
if showView {
DataView(data: data[index])
// Text("Hello \(data.count)") // To test if needed ; without async, data.count is 2. Seems OK, but…
// Text("Hello \(data.count) index \(index) \(data[0].str)") // but without async, it will crash, as data is not populated yet, even if count is already 2
}
}
.onAppear {
let filePath = Bundle.main.path(forResource: "data", ofType: "json")
let url = URL(fileURLWithPath: filePath!)
data = getData(url: url)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <<-- THE KEY POINT 0.1 sec delay
self.showView = true
}
}
}
func getData(url: URL) -> [Data2] {
do {
let data = try Data(contentsOf: url)
let jsonDecoded = try JSONDecoder().decode([Data2].self, from: data)
return jsonDecoded
} catch let error as NSError {
print("Fail: \(error.localizedDescription)")
} catch {
print("Fail: \(error)")
}
return []
}
}
Credit: https://stackoverflow.com/questions/62355428/how-do-i-show-a-new-view-after-some-delay-amount-of-time-swiftui
A simpler option is to use an init:
struct ContentView: View {
@State var data: [Data2]
@State var index: Int = 0
init() {
let filePath = Bundle.main.path(forResource: "data", ofType: "json")
let url = URL(fileURLWithPath: filePath!)
// data = getData(url: url) // We cannot call getData in init
do {
let dataRead = try Data(contentsOf: url)
let jsonDecoded = try JSONDecoder().decode([Data2].self, from: dataRead)
data = jsonDecoded
return
} catch let error as NSError {
print("Fail: \(error.localizedDescription)")
} catch {
print("Fail: \(error)")
}
data = []
return
}
var body: some View {
VStack {
DataView(data: data[index])
}
}
}
- Replies
- Boosts
- Views
- Activity
Thanks.
But your code does not compile, with the following errors:
Does it compile for you ?
- Replies
- Boosts
- Views
- Activity
I succeeded moving Xcode 16.4, MacMini, MacOS 15.6 (24G84):
Here is the initial tabbar
I click on the tabor in the TabBarController
it turns blue
I click on icon of item 1 and start dragging (I had to take care to hold the mouse pressed). A position caret appears (I cannot screenshot the caret) and icon starts to move and the other to rearrange
I move the caret (and the icon) to the desired position) and drop it
The icons are reordered
If that's OK, don't forget to close the thread on this answer ; otherwise please explain where it fails.
As you noticed, there is another way to do it, by creating the segues in desired order.
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
- Replies
- Boosts
- Views
- Activity
Could you provide complete code as well as the json file ?
Is Data a structure you have defined ?
If it is an empty set, it should crash at:
DataView(data: data[index])
Do you get Fail messages ?
Problem is not in onAppear. I tested by replacing getData by a dummy call
.onAppear {
// let filePath = Bundle.main.path(forResource: "data", ofType: "json")
// let url = URL(fileURLWithPath: filePath!)
//
// data = getData(url: url)
data = [Data()]
}
And data DataView is not empty, as I could check with the following
struct DataView: View {
@State var data: Data
var body: some View {
Text("DataView \(data)")
}
}
So, it looks like you return from getData by line 29 and not 22.
So, could you change line 29, to return a custom single data to check ?
- Replies
- Boosts
- Views
- Activity
Did you try to set the placement, such as:
.searchable(text: $searchText, isPresented: $isSearchPresented, placement: .navigationBarDrawer, prompt: "Search...")
Topic:
UI Frameworks
SubTopic:
UIKit
Tags:
- Replies
- Boosts
- Views
- Activity
Welcome to the forum.
Could you show (screenshots) what you get and what you'd expect.
And please also post the complete code.
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags:
- Replies
- Boosts
- Views
- Activity
@Ed Ford, for this useful clarification.
So that means there is no urgency to switch to Swift 6 mode, unless of course there are concurrency issues or we need specific Swift 6 feature ?
I understand however that it is wise to set concurrency checking at the max level, even in Swift 5 mode. Is it correct ?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
- Replies
- Boosts
- Views
- Activity
@eskimo
that was when testing with Swift6 and Xcode 16.4.
But after encapsulating the code using IBOutlet in
MainActor.assumeIsolated({
// using textField.text
})
I could remove the nonIsolated declaration for IBOutlet and get it working.
Unfortunately, I've not kept a version to reproduce the error.
In any case, I will not switch to Swift6 before using Xcode 26.
Topic:
Programming Languages
SubTopic:
Swift
Tags:
- Replies
- Boosts
- Views
- Activity
Logically, users would receive an error message from your app if backend is off.
In any case, if you don't update the app for 3 years, it will be removed automatically.
May be the best is just to wait ?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
- Replies
- Boosts
- Views
- Activity
No feedback. Closing the thread.
Topic:
Developer Tools & Services
SubTopic:
Apple Developer Program
Tags:
- Replies
- Boosts
- Views
- Activity
@Engineer
Thanks for reply. Some more crash info. On simulator (did not test on device at this stage).
Here is crash report:
Error occurs in #4 notifyMe IBAction
@IBAction func notifyMe(_ sender: UIButton) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined {
center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
DispatchQueue.main.async {
if !granted {
// Alert user
}
}
}
} else if settings.authorizationStatus == .denied {
DispatchQueue.main.async {
// Alert user
}
} else if settings.authorizationStatus == .authorized {
DispatchQueue.main.async {
self.alarmButton.isHidden = self.duree <= 120
}
}
})
var alertStyle = UIAlertController.Style.alert
let alertController = UIAlertController(
title: NSLocalizedString("M'avertir", comment: ""),
message: NSLocalizedString("Attention", comment: ""), preferredStyle: alertStyle)
var title = NSLocalizedString("5'", comment: "")
let ok = UIAlertAction(title: title, style: .default, handler: {(action) -> Void in
self.sendInitialNotification(beforeEnd: 5)
DispatchQueue.main.async { sender.isHidden = true }
})
alertController.addAction(ok)
let cancelAction = UIAlertAction(title: NSLocalizedString("Non", comment: ""), style: .default, handler: { (action) -> Void in
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
Crash apparently occurs on calling userNotificationCenter:
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if notification.request.identifier == requestIdentifier {
completionHandler( [.alert,.sound,.badge])
}
}
Topic:
App & System Services
SubTopic:
Notifications
Tags:
- Replies
- Boosts
- Views
- Activity
Thanks Quinn.
I removed the nonisolated for IBOutlet.
But, as shown in your example, I had to mark all func în a class that uses UNUserNotificationCenterDelegate as nonIsolated, such as
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
I also note in your example that you marked response for didReceive as async.
I tried to, but got the error:
Instance method 'userNotificationCenter(_:didReceive:withCompletionHandler:)' nearly matches optional requirement 'userNotificationCenter(_:didReceive:withCompletionHandler:)' of protocol 'UNUserNotificationCenterDelegate'
with the advice to
Make 'userNotificationCenter_:didReceive:withCompletionHandler:)' private to silence this warning
Converting to Swift 6 is definitely not an easy ride…
I'll do extensive testing.
Topic:
Programming Languages
SubTopic:
Swift
Tags:
- Replies
- Boosts
- Views
- Activity
Thanks for the answer.
didReceive was already non isolated. So problem likely does not come from here.
For willPresent, if I don't make it nonIsolated, I get an Xcode 16.4 compiler error:
Main actor-isolated instance method 'userNotificationCenter(_:willPresent:withCompletionHandler:)' cannot be used to satisfy nonisolated requirement from protocol 'UNUserNotificationCenterDelegate'
n Xcode 26, no error in func declaration if I remove nonIsolated.
But error at UIViewController class definition level
Conformance of 'CalcViewController' to protocol 'UNUserNotificationCenterDelegate' crosses into main actor-isolated code and can cause data races
Topic:
App & System Services
SubTopic:
Notifications
Tags:
- Replies
- Boosts
- Views
- Activity