for Hi,I am retrieving data from a web service in an URLSession and store all the entries to an arrayself.warehouseOrders.append(warehouseOrder)The array is used in another view as data source for a List() item but now I get this error message:Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.My question is: where is SwiftUI expecting me to put the operator receive(on:)) to fix this?I have kinda solved it by changing the code toDispatchQueue.main.async {
self.warehouseOrders.append(warehouseOrder)
}but I am not sure if that is the correct approach here?See https://forums.developer.apple.com/thread/128068for more details on my code - I have actually posted this already there as a reply but for some reason it still gets moderated for almost 24 hours ...Max
Post
Replies
Boosts
Views
Activity
Hi,I have a view that displays pictures loaded via web service call. The model for the view is@ObservedObject private var pictureController: PictureController = PictureController()The pictures are provided in an array from the controller:@Published var images:[Picture] = []and the View displays the data from the array with a List (my Picture class conforms to the Identifiable protocol)List(pictureController.images){ item in
Text(item.bkey)
}When loading the pictures from the web service, I store them in a buffer array and afterwards copy the array over to the images arrayDispatchQueue.main.async {
self.images = self.imageBuffer
completionHandler(true)
}I call the controller in the View's onAppear()self.pictureController.fetchPicturesByTask(bkey_issue: self.bkey_task, completionHandler: { success in
print(self.pictureController.images.count)
self.pictureController.images.forEach(){picture in
print(picture.id)
print(picture.bkey!)
}
})Here is the thing: self.pictureController.images.count actually return the proper count of items in the array, the prints below show the correct values but for whatever reason, the List in the View does not get updated ...Just for the sake of it I have also added a button to the View that calls a function on the controller to manually add dummy items to the array and that works perfect ...Any ideas what I am missing here?Max
I have noticed that Xcode fails to compile with
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
You can execute the below demo project to recreate the error. Once you uncomment confirmationDialog entries 11+ it fails to compile.
//
// ContentView.swift
// confDialogTest
//
// Created by Max on 13.06.22.
//
import SwiftUI
struct ContentView: View {
@State private var showingConf1 = false
@State private var showingConf2 = false
@State private var showingConf3 = false
@State private var showingConf4 = false
@State private var showingConf5 = false
var body: some View {
Button(role: .destructive) {
self.showingConf1.toggle()
} label: {
Label("Conf 1", systemImage: "trash.fill")
}
.padding()
Button(role: .destructive) {
self.showingConf2.toggle()
} label: {
Label("Conf 2", systemImage: "trash.fill")
}
.padding()
Button(role: .destructive) {
self.showingConf3.toggle()
} label: {
Label("Conf 3", systemImage: "trash.fill")
}
.padding()
Button(role: .destructive) {
self.showingConf4.toggle()
} label: {
Label("Conf 4", systemImage: "trash.fill")
}
.padding()
Button(role: .destructive) {
self.showingConf5.toggle()
} label: {
Label("Conf 5", systemImage: "trash.fill")
}
// .padding()
.confirmationDialog("Select location", isPresented: $showingConf1, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf2, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf3, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf4, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
//next group is dialogs 6-10
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
.confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
Text("Conf")
}
//next group is dialogs 11-15
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
//next group is dialogs 16-20
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
// .confirmationDialog("Select location", isPresented: $showingConf5, titleVisibility: .visible) {
// Text("Conf")
// }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Whiel it is easy to fix here if I just move some confirmationDialogs to another Button view, I have the same problem in another problem where I have to add many modifiers to a NavigationLink in a List View and there I cannot move it around ... :/
Any ideas what to do here?
Max
With the below code I get a very weird scrolling behaviour in my TabViews, LoginView is called on app launch:
struct LoginView: View {
@State private var presentContent = false
var body: some View {
return NavigationView {
ZStack{
NavigationLink(
destination: ContentView(),
isActive: $presentContent,
label: {
EmptyView()
})
Button("TEst") {
self.presentContent.toggle()
}
}
}
}
}
struct ContentView: View {
var body: some View {
TabView{
Group{
List{
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
}
.navigationTitle("Transactions")
.tabItem {
Image(systemName: "list.dash")
Text("Transactions")
}
Group{
List{
Text("Item 11")
Text("Item 12")
Text("Item 13")
}
}
.navigationTitle("Summary")
.tabItem {
Image(systemName: "list.dash")
Text("Summary")
}
}
}
}
Example image below:
Any ideas what that might cause?
Hi,
I want to open a view after taping on a push notification. The views and notifications are all working fine but my problem is when I try to open the view from the push notification via .sheet(isPresented) it is always presenting the view as modal.
I would like to achieve that the view is actually opened embedded in the NavigationView it would usually be when accessing it manually.
To make it more clear:
import SwiftUI
struct ContentView: View {
		var body: some View {
NavigationView{
VStack{
NavigationLink(destination: ListView()){
Text("Going one level down")
}
}
}
		}
}
struct ContentView_Previews: PreviewProvider {
		static var previews: some View {
				ContentView()
		}
}
struct ListView: View {
var body: some View{
NavigationLink(destination: DetailView()){
Text("Click me")
}
}
}
struct DetailView: View {
var body: some View{
Text("I want to display this view after tapping on a notification.")
}
}
After tapping on the push notification, I want to jump directly to the DetailView() down in the NavigationView tree (similar to what the Apple Calendar app is doing when you tap on the notification).
Any ideas? :)
Max
Hi,
After the update to big sur I have the issue that when I go to the Lock Screen and select a different user to log in, the screen freezes and after a few seconds the computer reboots.
Any ideas how to fix this?
Max
Hi,
I am using Cloudkit to download pictures for products in my app.
The pictures as stored as Asset in the record type.
Is there a way to download a picture once, stored it locally in some kind of temp folder (or cache) and then next time just fetch the UUID of the picture and validate if you already have it in cache and if no, download it again?
Max
Hi,
I have an app that is a shopping list. I can store prices per product and vendor in my app, the model is
Product
Vendor
Price
One product can have multiple prices from different vendors.
I store the price information with references to the product and vendor (CKRecord.Reference).
Now I am using the below to fetch all the prices related to a product:
public func fetchDataByProduct(product: Product, completionHandler: @escaping (Bool) -> Void){
self.pricesBuffer = []
let cloudContainer = CKContainer.init(identifier: "iCloud.XYZ")
let publicDatabase = cloudContainer.publicCloudDatabase
let reference = CKRecord.Reference(recordID: product.recordID, action: .deleteSelf)
let predicate = NSPredicate(format: "priceToProduct == %@", reference)
let query = CKQuery(recordType: "Price", predicate: predicate)
let operation = CKQueryOperation(query: query)
operation.recordFetchedBlock = { record in
let price = Price()
price.recordID = record.recordID
price.grossPrice = record.object(forKey: "grossPrice") as? Double
let dummy = record.object(forKey: "priceToVendor") as! CKRecord.Reference
price.vendorRecordID = dummy.recordID
self.pricesBuffer.append(price)
}
operation.queryCompletionBlock = { [unowned self] (cursor, error) in
self.pricesBuffer.forEach({price in
price.retrieveVendor()
})
DispatchQueue.main.async {
if error == nil {
self.prices = self.pricesBuffer
completionHandler(true)
} else {
}
}
}
publicDatabase.add(operation)
}
My problem is now that I cannot retrieve the vendor name which is part of the Vendor object (Vendor.name).
I have tried to loop over the pricesBuffer and run this one per price but the problem seems to be that CloudKit first completes the initial request to fetchDataByProduct() and then afterwards fetches the vendor data but then its too late because that updated data does not get pushed to my View (SwiftUI).
publicDatabase.fetch(withRecordID: self.vendorRecordID, completionHandler: {[unowned self] record, error in
if let record = record {
print(record)
self.vendor.recordID = record.recordID
self.vendor.name = record["name"] as! String
print(self.vendor.name)
}
})
Any ideas how to solve this? I believe I have to add a second CKQueryOperation to the mix and use the .addDependency() but I cannot wrap my head around how that should look like in the end.
Max
Hi,
When trying to validate my app and upload it to the AppStore, I get this message:
An attribute in the provided entity has invalid value
An invalid value was provided for the parameter 'permissions'
Provisioning profile failed qualifications
Profile doesn't support Push Notifications
Provisioning profile failed qualification
Profile doesn't include the asp-environment entitlement.
I have checked the profile in Xcode and it shows that all of those are fulfilled and I have no idea what parameter 'permissions' should be ...
Can you please help me out here?
Regards
Max
Hi,I have a picker of style SegmentedPickerStyle and based on the selection (Inbound, Outbound) a chart below displays different data. How can I send an event to my chart model to reload the data based on the picker selection? I know how to send the picker value to the model but how do I trigger it every time when the picker changes?I have tried something likeSunburstView(configuration: self.sunburstController.configuration).onAppear{
self.sunburstController.loadNodes(countMode: self.selectedCountMode, direction: self.selectedDirection)
}but that obviously only works first time the view is loading and not after every picker change.Thanks for any hints!Max
Hi,I have a view that has navigation bar items and I embed that view in a TabView. But when doing that, the bar items no longer appear. If I call the view outside of a TabView everything works as expected.Below a small sample project to illustrate my issue://
// ContentView.swift
// TabView
//
// Created by Max on 2020-03-30.
// Copyright © 2020 Max. All rights reserved.
//
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView{
NavigationLink(destination: WarehouseOrderTabView()){
Text("Click me")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct WarehouseOrderTabView: View {
var body: some View {
TabView{
TabView1().navigationBarTitle("Dashboard")
.tabItem {
Image(systemName: "gauge")
Text("Dashboard")
}
TabView2().navigationBarTitle("Orders")
.tabItem {
Image(systemName: "list.dash")
Text("Orders")
}
}
}
}
struct TabView1: View {
var body: some View {
Text("TabView 1")
//I would expect to see those bar items when displaying tab 1
.navigationBarItems(trailing: (
HStack{
Button(action: {
}, label: {
Image(systemName: "arrow.clockwise")
.font(.title)
})
.padding(.init(top: 0, leading: 0, bottom: 0, trailing: 20))
Button(action: {
}, label: {
Image(systemName: "slider.horizontal.3")
.font(.title)
})
}
))
}
}
struct TabView2: View {
var body: some View {
Text("TabView 2")
}
}What am I missing here?Max
Hi,I have a view that is triggred by a button touch. It appears nicely, all good. Now I want the View to disappear automatically again after a few seconds. How do I do that?!Below my test project//
// ContentView.swift
// FadeOut
//
// Created by Max on 2020-03-19.
// Copyright © 2020 Max. All rights reserved.
//
import SwiftUI
struct ContentView: View {
@State private var presentClipboardView = false
@State private var scale: CGFloat = 1.0
var body: some View {
VStack{
Button(action: {
let pasteboard = UIPasteboard()
pasteboard.string = "http://I_AM_A_URL.com"
withAnimation(.easeInOut(duration: 2)) {
self.presentClipboardView.toggle()
}
}, label: {
HStack {
Image(systemName: "list.dash")
.padding(.trailing)
VStack(alignment: .leading) {
Text("Open URL")
.font(.headline)
}
Spacer()
}
}
)
if(self.presentClipboardView){
LabelView()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct LabelView: View {
var body: some View {
Text("URL copied to clipboard!")
.padding(10)
.font(.title)
.foregroundColor(.white)
.background(RoundedRectangle(cornerRadius: 8).fill(Color.green).shadow(color: .gray, radius: 3))
}
}
Hi,I have a problem with passing arguments over to a View when calling it. I have this Viewstruct GoodsItemFilterView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject private var goodsItemFilter: GoodsItemFilter
@State var ref1Array: [String] = []
@State var ref2Array: [String] = []
@State var ref3Array: [String] = []
...and when I call it I can pass over the values of the arrays as arguments:GoodsItemFilterView(ref1Array: ["MAX100", "MAX101", "MAX102"], ref2Array: ["REF2_100", "REF2_101"], ref3Array: ["REF3_100", "REF3_101"])Now I have another view which is basically a copy of this one with a few changed names etcstruct OrderHeaderFilterView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var settingStore: SettingStore
@EnvironmentObject private var itemFilter: WarehouseOrderFilter
@State var orderTypeArray: [String] = []
@State var carrierArray: [String] = []
...and when I call it, it is not prompting me to pass over the arrays as arguments:OrderHeaderFilterView()What is the difference between those 2 views that the one is asking for arguments on initilization and the other one isn't? To be clear, in the end I want to pass over the arguments, so GoodsItemFilterView() is doing exactly what I need.Max
Hi,I have a Localizable.strings file for English and German. In there I have these entries"orderOverview" = "Order Overview";
"goal" = "XXXXXXXXXXXrder Overview";in my ContentView I haveNavigationLink(destination: WarehouseOrderOverview().environmentObject(self.settingStore).navigationBarTitle("orderOverview")) {
MenuButtonNavigation(title: "goal", color: Color.gray, icon: "doc.text.magnifyingglass").padding(.top)
}When I now run the app, it actually shows "goal" and "orderOverview" instead of the translated values. Is there anything else I have to do?Max
Hi,My app is being distributed over the Apple Business Manager program and I have noticed that every time I submit an updated version of the app, I have to increment the version number. My other app (regular distribution) only requires an update to the Build version and the version itself could remain identical.Is that supposed to be like that?Max