Post

Replies

Boosts

Views

Activity

Notify when @FetchRequest changes?
Hello @FetchRequest( entity: Book(), sortDescriptors: [] ) var books: FetchedResults<Book> How can I get notified when books changes? I was thinking about putting this... .onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave), perform: { _ in}) ... in my main View but this would notify me if anything gets saved and that is not what I want. I want to get notified just if a certain FetchRequest changes (in this case books)? How can I do that? Thank You!
4
1
2.6k
Jan ’23
Siri Shortcuts with SwiftUI and Core Data
Hello, I have created a simple SwiftUI app with Core Data and want to be able to add data via the shortcuts app, I have implemented Intents and the IntentHandler class. When I create a shortcut to add data to my app and run it, nothing happens in the app, the list does not refresh, the only way to see the added data is to close the app completely and reopen it. How can I refresh the UI immediately? I will post my Core Data stack and my SwiftUI view. struct PersistenceController { static let shared = PersistenceController() let container: NSPersistentContainer init() { container = NSPersistentContainer(name: "SiriShort") guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.SiriShortcut2")?.appendingPathComponent("SiriShort.sqlite") else { fatalError("Shared file container could not be created.") } let storeDescription = NSPersistentStoreDescription(url: fileContainer) storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) storeDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) container.persistentStoreDescriptions = [storeDescription] container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy } } View: import SwiftUI import CoreData import Intents struct ContentView: View { @Environment(\.managedObjectContext) private var viewContext @State private var view: Bool = false @FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Item.text, ascending: true)], animation: .default) private var items: FetchedResults<Item> var body: some View { NavigationView { List { ForEach(items) { item in Text(item.text!) } .onDelete(perform: deleteItems) } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } } private func addItem() { withAnimation { let newItem = Item(context: viewContext) newItem.text = "\(Int.random(in: 0...1000))" do { try viewContext.save() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } makeDonation(text: newItem.text!) } } func makeDonation(text: String) { let intent = MakeUppercaseIntent() intent.text = text intent.unit = "1" intent.suggestedInvocationPhrase = "Add \(text) to app" let interaction = INInteraction(intent: intent, response: nil) interaction.donate { (error) in if error != nil { if let error = error as NSError? { print("Donation failed: %@" + error.localizedDescription) } } else { print("Successfully donated interaction") } } } private func deleteItems(offsets: IndexSet) { withAnimation { offsets.map { items[$0] }.forEach(viewContext.delete) do { try viewContext.save() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } } }
4
0
2.2k
Jan ’22
DecimalPad Issues SwiftUI
Hello I have two questions: I'm using a decimalpad keyboard and when I use the comma the app doesn't recognise it How do I dismiss the keyboard? I want that in every country the decimals are written with the comma ( , ) (Can you please write the solution if you know it, thank you for your time) Code: import SwiftUI struct BMIView: View {          @State private var height = ""     @State private var weight = ""     @Environment(\.presentationMode) var presentationMode     var inputAfterConvertions: Float {          let hh = Float(height) ?? 0          let ww  = Float(weight) ?? 0          var ris: Float = 0          if hh > 0 && ww > 0{          ris = (ww / (hh * hh)) * 1000             return ris         }            return 0     }          var health: String{          if inputAfterConvertions < 18.49 && inputAfterConvertions > 0 { return ""         }         else if inputAfterConvertions > 18.5 && inputAfterConvertions < 24.99{             return ""         } else if inputAfterConvertions > 25{             return ""         }                  return ""     }     @State var isWriting: Bool = false     var body: some View {         NavigationView{             Form{                 Section(header: Text("Enter your height in cm")){                     TextField("Input",text: $height)                         .keyboardType(.decimalPad)                 }                 Section(header: Text("Enter your Weight in kg")){                     TextField("Input",text: $weight)                         .keyboardType(.decimalPad)                 }                 Section(header: Text("Check result")){                     Text("\(inputAfterConvertions, specifier: "%.2f")")                 }             }             .navigationBarTitle("BMI")             .navigationBarItems(trailing:                                     Button(action: {                                         presentationMode.wrappedValue.dismiss()                                     }) {                                         Image(systemName: "xmark").font(.title).foregroundColor(.blue)                                     }             )         }     } } Thank you very much for your time
3
0
5.4k
Jun ’21
Problems with ForEach, SwiftUI
Hello I am getting a lot of errors in ForEach and I don't know why at all. Here is the code: The error is at line 12 import SwiftUI import Combine struct ContentView: View { @EnvironmentObject var networkController: NetworkControllerItalia var body: some View { Form{ TextField("Input city name", text: $networkController.cityName) Section { ForEach(networkController.users.weather, id: \.self){ user in } } } } } class NetworkControllerItalia: ObservableObject { private var can: AnyCancellable? @Published var cityName: String = "" @Published var users = [UserItalia(weather: Weather())] init(cityName: String) { self.cityName = cityName let url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=\(cityName)&amp;appid=")! self.can = URLSession.shared.dataTaskPublisher(for: url) .map { $0.data } .decode(type: [UserItalia].self, decoder: JSONDecoder()) .eraseToAnyPublisher() .receive(on: DispatchQueue.main) .sink(receiveCompletion: {completion in print(completion) }, receiveValue: { users in self.users = users }) } } struct UserItalia: Decodable, Hashable{ var weather: Weather } struct Weather: Decodable, Hashable { var main: String? } Thank you
3
0
2.6k
Apr ’21
Errors in ForEach SwiftUI
Hello I get errors in ForEach that I don't know how to solve: Generic struct 'ForEach' requires that 'Main' conform to 'RandomAccessCollection' Unable to infer type of a closure parameter 'user' in the current context Error at line 30 - 31 Code: // // ContentView.swift // ARWeather // // Created by Jad Taljabini on 08/04/21. // import SwiftUI import Combine struct ContentView: View { @EnvironmentObject var networkController: NetworkControllerItalia var body: some View { NavigationView { Form{ TextField("Input city name", text: $networkController.cityName, onEditingChanged: { te_xt in networkController.url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(networkController.cityName)&amp;appid=") ?? URL(string: "https://www.apple.com")! networkController.fun() }, onCommit: { withAnimation{ networkController.url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(networkController.cityName)&amp;appid=") ?? URL(string: "https://www.apple.com")! networkController.fun() } }) Section { ForEach(networkController.users.weather ?? [], id: \.self){ user in Text(user.main ?? "") } ForEach(networkController.users.main ?? Main(temp: 0), id: \.self){ user in Text("\(user.temp)") } } } } } } class NetworkControllerItalia: ObservableObject { private var can: AnyCancellable? @Published var cityName: String = "" @Published var users = UserItalia(weather: []) var url = URL(string: "https://www.apple.com")! func fun(){ self.can = URLSession.shared.dataTaskPublisher(for: url) .map { $0.data } .decode(type: UserItalia.self, decoder: JSONDecoder()) .eraseToAnyPublisher() .receive(on: DispatchQueue.main) .sink(receiveCompletion: {completion in print(completion) }, receiveValue: { users in self.users = users }) }//Funzione che riempe users di dati da internet } struct UserItalia: Decodable, Hashable{ var weather: [Weather]? var main: Main? } struct Weather: Decodable, Hashable { var main: String? } struct Main: Decodable, Hashable { var temp: Float } The JSON API is like this: { "coord": { "lon": -0.1257, "lat": 51.5085 }, "weather": [ { "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d" } ], "base": "stations", "main": { "temp": 285.45, "feels_like": 283.96, "temp_min": 284.82, "temp_max": 285.93, "pressure": 1021, "humidity": 47 }, "visibility": 10000, "wind": { "speed": 5.66, "deg": 220 }, "clouds": { "all": 20 }, "dt": 1617888145, "sys": { "type": 1, "id": 1414, "country": "GB", "sunrise": 1617859180, "sunset": 1617907473 }, "timezone": 3600, "id": 2643743, "name": "London", "cod": 200 } Thank you
3
0
3.6k
Apr ’21
CloudKit and CoreData synchronization
Hello I am developing an app with SwiftUI using CoreData and iCloudKit to sync data between platforms. The problem is that the iCloud background update is not being triggered when staying in the application. If I make changes on both systems, the changes are being pushed, however not visible on the other device. I need to reload the app, close the app and open again. I already enabled iCloud capability, background notifications and push notifications. This is my persistentContainer var persistentContainer: NSPersistentCloudKitContainer = { let container = NSPersistentCloudKitContainer(name: "Test7") container.loadPersistentStores(completionHandler: {(StoreDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy return container }() func saveContext() { let context = persistentContainer.viewContext if context.hasChanges{ do { try context.save() } catch { let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } } This is my model class ItemsModel: ObservableObject { init() { readData() } @Published var dataInputs: [Item] = [] let context = persistentContainer.viewContext func readData(){ let request: NSFetchRequest<Item> = Item.fetchRequest() do { let results = try context.fetch(request) self.dataInputs = results } catch { print(error.localizedDescription) } } func addItem(todo: String, date: Date){ let entity = NSEntityDescription.insertNewObject(forEntityName: "Item", into: context) as! Item entity.todo = todo entity.date = date do { try context.save() self.dataInputs.append(entity) } catch { print(error.localizedDescription) } } func deleteItems(indexSet: IndexSet){ for index in indexSet{ do { let obj = dataInputs[index] context.delete(obj) try context.save() let index = dataInputs.firstIndex(of: obj) dataInputs.remove(at: index!) } catch { print(error.localizedDescription) } } } } and this is my view struct ContentView: View { @EnvironmentObject var items: ItemsModel var body: some View { NavigationView{ List { ForEach(items.dataInputs) { item in Text("Item at \(item.date!)") } .onDelete(perform: items.deleteItems) } .toolbar { Button { items.addItem(todo: "Hello", date: Date()) } label: { Image(systemName: "plus") } } } } } Thank you
3
0
2.5k
Jun ’21
PersistenceController and CloudKit
Hello I am making a To-Do list app where I use CoreData and CloudKit, the problem is that when I added this line of code container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: fileContainer.appendingPathComponent("MJ.sqlite"))] to the PersistenceController, iCloud syncing stopped working. (I need that line of code in order to permit to extensions to access the CoreData database) Any idea to solve the problem? This is all the PersistenceController code struct PersistenceController { static let shared = PersistenceController() let container: NSPersistentCloudKitContainer init(inMemory: Bool = false) { container = NSPersistentCloudKitContainer(name: "MJ") guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.name") else { fatalError("Shared file container could not be created.") } container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: fileContainer.appendingPathComponent("MJ.sqlite"))] container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy } } Thank you!
3
0
2.5k
Dec ’21
App increases size even if I delete data (Core Data)
Hello I noticed that in my app, when I add data (I am using Core Data) the size of the app increases, as expected, the problem occurs when I delete data, the size of the app remains unchanged and sometimes increases, I thought there was an error in the my code and so I created, from scratch, a project for iOS with SwiftUI and Core Data enabled (the default template that Xcode provides) and also with the SwiftUI & Core Data default app the same problem happens. Is there a way to fix it or is there an explanation for this? Thank you!
3
0
1.5k
Aug ’21
Rotate View around an other View SwiftUI
Hello I created a custom shape in SwiftUI and I am trying to rotate it around a circle, but it works just on the top part of the circle, can you help me make it rotate exactly around the circle? (And also can I get the same effect using radians? How?) Here is the code: import SwiftUI struct MyGameView: View { @State private var degress: Double = 0 let timer = Timer.publish(every: 0.05, on: .main, in: .common).autoconnect() var body: some View { VStack{ ZStack{ Circle() .frame(width: 80) ZStack{ Circle() .stroke(lineWidth: 1) .frame(width: 300) BallonShape() .scaledToFit() .scaleEffect(0.2) .foregroundColor(.red) .rotationEffect(.degrees(degress), anchor: .bottom) .offset(x: 0, y: -170) } } } .onReceive(timer) { input in withAnimation(.easeIn(duration: 0.05).speed(10)){ degress += 1 } } } } struct BallonShape: Shape { func path(in rect: CGRect) -> Path { Path { path in path.move(to: CGPoint(x: rect.midX, y: (rect.maxY + rect.midY) / 2)) path.addCurve(to: CGPoint(x: rect.midX, y: rect.minY), control1: CGPoint(x: (rect.midX + rect.minX) / 2, y: rect.minY), control2: CGPoint(x: (rect.midX + rect.minX) / 2, y: rect.minY)) path.addCurve(to: CGPoint(x: rect.midX, y: (rect.maxY + rect.midY) / 2), control1: CGPoint(x: (rect.midX + rect.maxX) / 2, y: rect.minY), control2: CGPoint(x: (rect.midX + rect.maxX) / 2, y: rect.minY)) } } } Thank You very much!
3
0
2.1k
Sep ’21
.onDelete resets NSPredicate (Core Data, SwiftUI)
Hello I have a list of data in SwiftUI. The data shown in the list can be saved or deleted by using Core Data. In the @FetchRequest property that I am using to display data, I initialized an NSPredicate and in the view, I gave the possibility to the user to change the value of the predicate so that he can filter data, and that is all working, the problem shows up when I delete data from the list when I do so the predicate becomes nil and I don't know why. Here is the code struct SectionList: View { @FetchRequest( entity: LifetimeInputs.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)], predicate: nil ) var lifetimeInputsModel: FetchedResults<LifetimeInputs> @FetchRequest(entity: Limit.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Limit.date, ascending: false)]) var limit: FetchedResults<Limit> @Environment(\.dynamicTypeSize) var dynamicTypeSize var size: CGFloat{ if UIDevice.current.userInterfaceIdiom == .phone { switch dynamicTypeSize { case .xSmall: return 11 case .small: return 13 case .medium: return 15 case .large: return 17 case .xLarge: return 19 case .xxLarge: return 21 case .xxxLarge: return 23 default: return 23 } } else { switch dynamicTypeSize { case .xSmall: return 13 case .small: return 15 case .medium: return 17 case .large: return 19 case .xLarge: return 21 case .xxLarge: return 23 case .xxxLarge: return 25 case .accessibility1: return 27 case .accessibility2: return 29 default: return 29 } } } @StateObject var lifeTimeInputsViewModel = LifeTimeInputsViewModel() @Environment(\.managedObjectContext) private var viewContext var conversion: Double { if !limit.isEmpty{ switch limit.last?.unita { case Unit.ml.rawValue: return 1 case Unit.oz.rawValue: return 29.574 default: return 1 } } return 1 } @State private var wantsToFilter: Bool = false @State private var dateSelected = Date() var body: some View { Section{ HStack{ Text("Filter") Spacer() Image(systemName: wantsToFilter ? "checkmark.circle" : "xmark") .font(.system(size: size + 6)) .foregroundColor(wantsToFilter ? .green : .red) .onTapGesture { wantsToFilter.toggle() if wantsToFilter{ lifetimeInputsModel.nsPredicate = NSPredicate( format: "date >= %@ && date <= %@", Calendar.current.dateInterval(of: .day, for: dateSelected)!.start as CVarArg, Calendar.current.dateInterval(of: .day, for: dateSelected)!.end as CVarArg ) } else{ lifetimeInputsModel.nsPredicate = nil } } } DatePicker("Date", selection: $dateSelected, displayedComponents: .date) } header: { Text("Filter") .font(.system(size: size - 4)) } .onChange(of: dateSelected, perform: { _ in if wantsToFilter{ lifetimeInputsModel.nsPredicate = NSPredicate( format: "date >= %@ && date <= %@", Calendar.current.dateInterval(of: .day, for: dateSelected)!.start as CVarArg, Calendar.current.dateInterval(of: .day, for: dateSelected)!.end as CVarArg ) } }) Section{ ForEach(lifetimeInputsModel){ lifetimeInputs in HStack{ Text("\(lifetimeInputs.valori / conversion, specifier: format(unita: !limit.isEmpty ? limit[limit.count - 1].unita ?? ml : ml)) \(!limit.isEmpty ? limit[limit.count - 1].unita ?? ml: ml)") .font(.system(size: size)) Spacer() Text("\(dateFormatter.string(from: lifetimeInputs.date ?? Date()))") .font(.system(size: size)) } } .onDelete{lifeTimeInputsViewModel.deleteItems(offsets: $0, lifetimeInputsModel: lifetimeInputsModel); } } header: { Text("History \(lifetimeInputsModel.count)".localized()).font(.system(size: size - 4)) } } } Thank You!
3
0
1.5k
Jan ’22
Siri Shortcuts with CoreData
Hello I created a simple SwiftUI app with Core Data and I want to be able to add data via the shortcuts app, I created a shortcut that takes some text as input and returns it in uppercase and when I run the shortcut in the shortcuts app, it works, however when I added an "add" function (to save data in the Core Data database) to the intent handle function, and I run it again nothing is saved in the app, here is the code: class MakeUppercaseIntentHandler: NSObject, MakeUppercaseIntentHandling { let persistenceController = PersistenceController() func handle(intent: MakeUppercaseIntent, completion: @escaping (MakeUppercaseIntentResponse) -> Void) { if let inputText = intent.text { let uppercaseText = inputText.uppercased() completion(MakeUppercaseIntentResponse.success(result: add(text: uppercaseText))) } else { completion(MakeUppercaseIntentResponse.failure(error: "The text entred is invalid")) } } func resolveText(for intent: MakeUppercaseIntent, with completion: @escaping (MakeUppercaseTextResolutionResult) -> Void) { if let text = intent.text, !text.isEmpty { completion(MakeUppercaseTextResolutionResult.success(with: text)) } else { completion(MakeUppercaseTextResolutionResult.unsupported(forReason: .noText)) } } func add(text: String) -> String{ let newItem = Item(context: persistenceController.container.viewContext) newItem.text = text do { try persistenceController.container.viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } return text } } Thank You
3
0
1.1k
Dec ’21