Post

Replies

Boosts

Views

Activity

Best Practices to Store Multiple Photos Per Entry in SwiftData
Hello everyone, I am currently developing an app using SwiftUI and SwiftData. In my app, I need to store about three photos per entry. But as the number of entries grows, I run into significant performance issues, especially with RAM and CPU utilization. The app slows down as the dataset grows. I'm wondering what would be the best approach to deal with this. Should I continue to store the photos locally using SwiftData, or would it be better to upload them to a server (like AWS S3 or Firebase Storage) and store only the URLs in SwiftData? I also want to implement caching to improve performance, what would be the best methods or practices for caching these images? I would be very grateful for any advice or suggestions from the community. Thank you in advance!
1
0
311
Aug ’24
Changes to SwiftData SubModels do not update the UI
Hello, I'm having a problem with SwiftData that I can't find a solution for. Every change made to the firstArray updates the interface. However, the changes I make on secondArray do not update the interface. The changes on secondArray are saved but the UI is not updated. (I can see that the interface is updated by the text giving the number of elements in the array. ) Model: import Foundation import SwiftData @Model final class Item { var firstArray: [String] var itemDetail: ItemDetail init(firstArray: [String], itemDetail: ItemDetail) { self.firstArray = firstArray self.itemDetail = itemDetail } } @Model class ItemDetail { var secondArray: [String] init(secondArray: [String]) { self.secondArray = secondArray } } Content View: import SwiftUI import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] var body: some View { NavigationStack { List { ForEach(items) { item in NavigationLink("Item") { ItemDetailView(item: item, itemDetail: item.itemDetail) } } } .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Add", systemImage: "plus") { let item = Item(firstArray: ["Mehmet", "Fırat", "Şirin"], itemDetail: ItemDetail(secondArray: ["Mehmet", "Fırat", "Şirin"])) modelContext.insert(item) } } ToolbarItem(placement: .topBarLeading) { Button("Delete", systemImage: "trash", role: .destructive) { try? modelContext.delete(model: Item.self) } .tint(.red) } } } } } Detal View: import SwiftUI struct ItemDetailView: View { let item: Item let itemDetail: ItemDetail // for Version 3 var body: some View { List { //MARK: Version 1 Text(item.firstArray.count.formatted()) Section { ForEach(item.firstArray, id: \.self) { Text($0) } .onDelete { item.firstArray.remove(atOffsets: $0) } } //MARK: Version 2 Text(item.itemDetail.secondArray.count.formatted()) Section { ForEach(item.itemDetail.secondArray, id: \.self) { Text($0) } .onDelete { item.itemDetail.secondArray.remove(atOffsets: $0) } } Button("Delete All") { item.itemDetail.secondArray = [] } //MARK: Version 3 Text(itemDetail.secondArray.count.formatted()) Section { ForEach(itemDetail.secondArray, id: \.self) { Text($0) } .onDelete { itemDetail.secondArray.remove(atOffsets: $0) } } Button("Delete All") { itemDetail.secondArray = [] } } } } Try the versions with only one on the screen. In version 1 everything works fine. In version 2 the deletion works but the interface is not updated. In version 3 everything works fine. I don't think version 3 is a very correct method so I am waiting for your ideas and solutions. Thanks for all the answers.
1
0
323
Aug ’24
Question About Weak Self Usage
Hello everyone. I have a small question about Weak Self. In the example below, I am doing a long process to the data I query with SwiftData. (For this reason, I do it in the background.) I don't know if there is a possibility of a memory leak when the view is closed because this process takes a long time. import SwiftUI import SwiftData struct ActiveRegView: View { @Query(filter: #Predicate<Registration> { $0.activeRegistration }, animation: .default) private var regs: [Registration] @Environment(ViewModel.self) private var vm @State private var totalParkingFee: Decimal = 0 var body: some View { ... .onAppear { var totalParkingFee = Decimal() DispatchQueue.global(qos: .userInitiated).async { for reg in regs { totalParkingFee += vm.parkingFee(from: reg.entryRegistration.entryDate, to: .now, category: reg.category, isCustomPrice: reg.isCustomPrice) } DispatchQueue.main.async { withAnimation { totalParkingFee = totalParkingFee } } } } } } I use ViewModel with @Environment, so I don't initilize ViewModel every time view is initilized. I know it's a simple question and I thank you in advance for your answers.
0
0
262
Jun ’24
Problem with NavigationStack(path:)
Hello everyone. I am developing an application with SwiftUI. I am having trouble with NavigationStack(path: ). 1st problem: After the application runs, after clicking on the first list item, there is a flicker in the title section. I think it is the .navigationDestination that causes this problem, because when I change the navigationLink to Button in the “ActiveRegQueryView” screen, this problem disappears. 2nd Problem: When you click on a list item, sometimes it stays pressed (grayed out) and does not take you to the screen (Video 1). If you try to click on an item more than once, navigatinLink passes more than one value to path and opens more than one page (I noticed this with path.count) (Video 2). I don't have this problem if you edit the back button on the screen it takes you to (ActiveRegDetailView). (vm.path.removeLast()) The reason I use path is to close multiple screens and return to the start screen. Video 1: Video 2: Main View: import SwiftUI struct ActiveRegView: View { @Environment(NavigationViewModel.self) private var navViewModel @AppStorage("sortOption") private var sortOrder: sorting = .byBrand @State private var searchText = "" var body: some View { @Bindable var navViewModel = navViewModel NavigationStack(path: $navViewModel.path) { // <- if i don't use path everything is OK List { ActiveRegQueryView(searchText: searchText, sortOrder: sortOrder) // <- Dynamic Query View } .navigationDestination(for: Registration.self, destination: { ActiveRegDetailView(reg: $0) .toolbar(.hidden, for: .tabBar) }) } } } Dynamic Query View: import SwiftData import SwiftUI struct ActiveRegQueryView: View { @Query private var regs: [Registration] @Environment(NavigationViewModel.self) var vm init(searchText: String, sortOrder: sorting) { var order: SortDescriptor<Registration> switch sortOrder { case .byBrand: order = SortDescriptor(\.brand) case .byDateDescending: order = SortDescriptor(\.entryRegistration.entryDate, order: .reverse) case .byDateAscending: order = SortDescriptor(\.entryRegistration.entryDate) } _regs = Query(filter: #Predicate { if !searchText.isEmpty { if $0.activeRegistration && ($0.brand.localizedStandardContains(searchText) || $0.model.localizedStandardContains(searchText) || $0.plate.localizedStandardContains(searchText)) { return true } else { return false } } else { return $0.activeRegistration } }, sort: [order]) } var body: some View { ForEach(regs) { reg in NavigationLink(value: reg) { ListRowView(reg: reg) } // Button { // vm.path.append(reg) // } label: { // ListRowView(reg: reg) // } // .buttonStyle(.plain) } } } I look forward to your ideas for solutions. Thank you for your time.
0
0
383
May ’24
SwiftUI App Crashes on Simulator When Using @Query Macro in Chart Interaction
I'm developing an app with a chart in SwiftUI. I want the following block of code to run when the chart is clicked. On my personal iPhone, the app works flawlessly. But when I try it in the simulator it crashes and gives me about 5-10 of the following errors. When I remove the @Query macro from the code block, the application does not crash in the simulator, but I continue to get the errors I mentioned. If I do not run the following code block, I do not get the errors I mentioned. struct SaleDetailView: View { @Query(filter: #Predicate<Registration> { !$0.activeRegistration }) private var regs: [Registration] var body: some View { VStack { DailySaleView() } .padding() } } Thank you in advance for your answers. Do not hesitate to ask if you have any questions. Thanks, MFS
1
0
359
May ’24
Persisting User Input Data in SwiftUI
I'm developing an application using SwiftUI and SwiftData. The app includes a pricing section, and I'd like it to have an initial default value for pricing. Additionally, when updating the app on the App Store, I also want to update the prices. However, I'd like users to have the option to create their own prices if they don't want to use the ones I suggest. I want to save these prices obtained from the user because I'll be using these values for some operations later on. I'm wondering how to achieve this. Should I use SwiftData or UserDefaults for managing the data, or should I save the prices to a JSON file? If I opt for saving to a JSON file, would it be possible to update the JSON file when updating the app? Please feel free to ask any questions. Thank you in advance for your responses.
2
0
529
Apr ’24
Using .environment() for Observable Object
Hello everyone, I hope you are well. I have a question about .environment. I have an observable viewModel which has some functions and publishing value. I'm observing this viewModel in only 2 views but I'm using viewModel functions in every view. Should I use it (.environment). if I should use it, should I use this environment macro (@Environment(ViewModel.Self) var vm) for only functions in view? Thank you so much.
1
0
691
Mar ’24
Delay Issue with onChange Modifier in SwiftUI
I'm getting this error : Picker: the selection "3" is invalid and does not have an associated tag, this will give undefined results. Because new brand doesn't have 3 values and .onChange modifier is not working fast enough. Thanks for your help. Picker("Marka", selection: $brandIndex) { Text("Seçin").tag(0) ForEach(cars.indices, id: \.self) { Text(cars[$0].brand).tag($0 + 1) } } .onChange(of: brandIndex) { if modelIndex != 0 { modelIndex = 0 } } Picker("Model", selection: $modelIndex) { Text("Seçin").tag(0) if brandIndex != 0 { let _ = print(modelIndex) // I'm getting first 3 then 0. And I'm getting error. ForEach(cars[brandIndex - 1].models.indices, id: \.self) { Text(cars[brandIndex - 1].models[$0]) .tag($0 + 1) } } }
7
0
977
Mar ’24
App crashes when I try to delete data with SwiftData
I'm getting error when I try to delete my kayit item. And the line causing the error is given below. When I removed this line everything is OK. I can delete my kayit item. @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss @Bindable var kayit: Kayit @FocusState private var focusedField: Field? var body: some View { Form { Section { Text(kayit.ozellikleri) Text(kayit.girisKaydi.baglanmaNedeni) // This line gives error } } .navigationTitle("Edit Registery") .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { modelContext.delete(kayit) try? modelContext.save() dismiss() } label: { Image(systemName: "trash") .foregroundStyle(.red) } } } } When I use giriskaydi in anywhere it gives error. When I remove I can delete my item. This is my model: import Foundation import SwiftData @Model class Kayit { var aktifKayit = true var plaka: String var marka: String var model: String var ozellikleri: String var kategori: Kategori var girisKaydi: GirisKaydi var cikisKaydi: CikisKaydi init(aktifKayit: Bool = true, plaka: String, marka: String, model: String, ozellikleri: String, kategori: Kategori, girisKaydi: GirisKaydi, cikisKaydi: CikisKaydi) { self.aktifKayit = aktifKayit self.plaka = plaka self.marka = marka self.model = model self.ozellikleri = ozellikleri self.kategori = kategori self.girisKaydi = girisKaydi self.cikisKaydi = cikisKaydi } } @Model class GirisKaydi { var baglayanKurum: String var baglanmaNedeni: String var girisTarihi: Date var personel: String var cekiciUcreti: Double init(baglayanKurum: String, baglanmaNedeni: String, girisTarihi: Date, personel: String, cekiciUcreti: Double) { self.baglayanKurum = baglayanKurum self.baglanmaNedeni = baglanmaNedeni self.girisTarihi = girisTarihi self.personel = personel self.cekiciUcreti = cekiciUcreti } } @Model class CikisKaydi { var teslimAd: String var teslimSoyad: String var adres: String var telefon: String var dayanak: String var cikisTarihi: Date var aciklama: String init(teslimAd: String, teslimSoyad: String, adres: String, telefon: String, dayanak: String, cikisTarihi: Date, aciklama: String) { self.teslimAd = teslimAd self.teslimSoyad = teslimSoyad self.adres = adres self.telefon = telefon self.dayanak = dayanak self.cikisTarihi = cikisTarihi self.aciklama = aciklama } } And the error: @Model class Kayit { var aktifKayit = true var plaka: String var marka: String var model: String var ozellikleri: String var kategori: Kategori var girisKaydi: GirisKaydi { @storageRestrictions(accesses: _$backingData, initializes: _girisKaydi) init(initialValue) { _$backingData.setValue(forKey: \.girisKaydi, to: initialValue) _girisKaydi = _SwiftDataNoType() } get { _$observationRegistrar.access(self, keyPath: \.girisKaydi) return self.getValue(forKey: \.girisKaydi) // Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1cb45f898) } set { _$observationRegistrar.withMutation(of: self, keyPath: \.girisKaydi) { self.setValue(forKey: \.girisKaydi, to: newValue) } } } var cikisKaydi: CikisKaydi init(aktifKayit: Bool = true, plaka: String, marka: String, model: String, ozellikleri: String, kategori: Kategori, girisKaydi: GirisKaydi, cikisKaydi: CikisKaydi) { self.aktifKayit = aktifKayit self.plaka = plaka self.marka = marka self.model = model self.ozellikleri = ozellikleri self.kategori = kategori self.girisKaydi = girisKaydi self.cikisKaydi = cikisKaydi } And is says CoreData: warning: Warning: Dropping Transactions prior to 52 for Persistent History in console. Thank you so much.
2
0
759
Mar ’24