Hello
Is there a way to execute a function (even if the app is closed) at a certain time, for example 12:30 AM?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello
Is there a way to sync notifications that are created locally, on CloudKit, I am using this function to create notifications and I am saving everything in an array
func scheduleNotifications(date: Date, identfier: String) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success {
print("Success")
} else if let error = error {
print(error.localizedDescription)
}
}
let content = UNMutableNotificationContent()
content.title = "Notification"
content.body = "Notification."
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = Int(hourFormatter.string(from: date)) ?? 0
print(hourFormatter.string(from: date))
dateComponents.minute = Int(minuteFormatter.string(from: date)) ?? 0
print(minuteFormatter.string(from: date))
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: identfier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
Thank you
Hello
Is there a way to share data stored in CloudKit and CoreData between iOS and watchOS in SwiftUI? I am using the same CoreData file both, and I am using the same PersistenceController file both, and I am using the same CloudKit container for both.
I tried adding the App Groups capability to all the targets, but it is not working.
(I already enabled iCloud capability, Push notification capability and background Modes capability for both iOS and WatchOS)
PersistenceController:
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Test7")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
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:
struct ContentView: View {
@FetchRequest(
entity: Item.entity(),
sortDescriptors: []
) var items: FetchedResults<Item>
@Environment(\.managedObjectContext) private var context
var body: some View {
NavigationView{
List {
ForEach(items) { item in
Text("Item at \(item.date!)")
}
.onDelete(perform: deleteItems)
}
.toolbar {
Button {
addItem()
} label: {
Image(systemName: "plus")
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: context)
newItem.date = Date()
do {
try context.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(context.delete)
do {
try context.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
Thank you
Hello
How can I set up local notifications that repeat every X minutes from a certain hour to another hour.
For example, I want to receive a notification every 60 minutes starting from 12:00 AM to 10:00 PM?
func scheduleNotifications() {
let content = UNMutableNotificationContent()
content.title = "App"
content.subtitle = "App"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
With this code I can schedule a notification every minute, however, I cannot decide from what time it should start or when it stops.
Any ideas?
Thank you!
Hello
In my app I have a list of items in a ForEach and at the end of the ForEach there is a .onDelete. (This is in a View that I called AllHistoryView)
The items are represented by a CoreData NSManagedObject that I called LifetimeInputs with 3 properties:
date: Date, imageTemplate: String, valori: Double
The problem is that, when I add (in a different View) an item with the date of tomorrow and then I add another to item with the date of today and then go to the AllHistoryView where there are all the items and delete slowly the item with date of tomorrow (especially at the end of the swipe action) instead of deleting the item that I swiped it deletes the on before it, how can I solve this problem?
Here is the AllHistoryView code:
import SwiftUI
import CoreData
struct AllHistoryView: View {
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(entity: LifetimeInputs.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)], animation: .default) var lifetimeInputsModel: FetchedResults<LifetimeInputs>
@State private var text: String = ""
@State private var ascending: Bool = true
@State var sortDescriptor: NSSortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)
@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
}
}
}
var body: some View {
theView()
}
@ViewBuilder
func theView() -> some View{
NavigationView{
if !lifetimeInputsModel.isEmpty{
List{
SectionList(sortDescripter: sortDescriptor, text: $text)
.environment(\.managedObjectContext, viewContext)
.onChange(of: ascending, perform: { _ in
if ascending {
withAnimation {
sortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)
}
} else {
withAnimation {
sortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: false)
}
}
})
}
.searchable(text: $text, placement: .navigationBarDrawer, prompt: "Quantity or date".localized())
.navigationBarTitle("History", displayMode: .inline)
.toolbar{
ToolbarItem(placement: .automatic) {
Image(systemName: "arrow.up.arrow.down.circle")
.foregroundColor(.primary)
.font(.system(size: size))
.rotation3DEffect(.degrees(ascending ? 0 : 180), axis: (x: 1, y: 0, z: 0))
.opacity(0.5)
.onTapGesture {
ascending.toggle()
}
}
}
} else{
VStack{
Text("No Data".localized())
.font(.largeTitle)
.fontWeight(.semibold)
.foregroundColor(.secondary)
}
.padding(.bottom)
.navigationBarTitle("History", displayMode: .inline)
}
}
}
}
struct SectionList: View {
@Environment(\.managedObjectContext) var viewContext
@FetchRequest var lifetimeInputsModel: FetchedResults<LifetimeInputs>
@Binding var text: String
init(sortDescripter: NSSortDescriptor, text: Binding<String>) {
let request: NSFetchRequest<LifetimeInputs> = LifetimeInputs.fetchRequest()
request.sortDescriptors = [sortDescripter]
_lifetimeInputsModel = FetchRequest<LifetimeInputs>(fetchRequest: request)
self._text = text
}
@FetchRequest(entity: Limit.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Limit.date, ascending: true)], animation: .default) 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()
var body: some View {
Section{
ForEach(lifetimeInputsModel.filter { text.isEmpty || "\($0)".contains(text) }){ lifetimeInputs in
HStack{
Text("\(lifetimeInputs.valori, specifier: format(unita: !limit.isEmpty ? limit[0].unita ?? ml : ml)) \(!limit.isEmpty ? limit[0].unita ?? ml: ml)")
.font(.system(size: size))
Spacer()
Text("\(dateFormatter.string(from: lifetimeInputs.date ?? Date()))")
.font(.system(size: size))
}
}
.onDelete(perform: { offsets in
lifeTimeInputsViewModel.deleteItems(offsets: offsets)
})
} header: {
Text("History".localized()).font(.system(size: size - 4))
}
}
}
Thank You very much!
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)?
And in another thread I was told to use...
.onRecevie(books.publisher){ _ in
....
}
...however using this code publishes each member of the sequence as a separate element, I want it to publish just once?
Thank You!
Hello
I created a @propertyWrapper to limit the number a variable can reach. I tried it in a SwiftUI view with a button that increases the value of the variable and it works, the variable stops at the maximum number set in the initializer. However if I try it with a Textflied it doesn't work, if I insert a higher number than the one set nothing happens, it makes me do it. How can I solve this problem, I know the problem has to do with Binding but I don't know exactly what it is, here is the code:
import SwiftUI
struct ContentView: View {
@Maximum(maximum: 12) var quantity: Int
var body: some View {
NavigationView{
Form{
TextField("", value: $quantity, format: .number, prompt: Text("Pizza").foregroundColor(.red))
Button {
quantity += 1
} label: {
Text("\(quantity)")
}
}
}
}
}
@propertyWrapper
struct Maximum<T: Comparable> where T: Numeric {
@State private var number: T = 0
var max: T
var wrappedValue: T {
get { number }
nonmutating set { number = min(newValue, max) }
}
var projectedValue: Binding<T> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
init(maximum: T){
max = maximum
}
}
extension Maximum: DynamicProperty {
}
Thank You for your time
Hello
How do I disable a notification for a day if it is set within one hour and the user has completed a task.
This is my function to set up local notifications:
import UserNotifications
func scheduleNotifications(date: Date, identfier: String) {
let content = UNMutableNotificationContent()
content.title = "App name"
content.body = "Message."
content.sound = .default
content.userInfo = ["Hour": timeFormatter.string(from: date)]
var dateComponents = DateComponents()
dateComponents.hour = Int(hourFormatter.string(from: date)) ?? 0
dateComponents.minute = Int(minuteFormatter.string(from: date)) ?? 0
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: identfier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
Hello
I have this Core Data stack and I have an observer to observe NSPersistentStoreRemoteChange, I would like to filter changes that the user has made to call the mergePersistentHistoryChanges() just when needed, I think it has to be done in the fetchPersistentHistoryTransactionsAndChanges() function but I don't know how to do it. Can you help me. Thank You
Here is my Core Data Stack:
class PersistenceController {
static let shared = PersistenceController()
private var notificationToken: NSObjectProtocol?
init() {
notificationToken = NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: nil, queue: nil) { note in
Task {
await self.fetchPersistentHistory()
}
}
}
deinit {
if let observer = notificationToken {
NotificationCenter.default.removeObserver(observer)
}
}
private var lastToken: NSPersistentHistoryToken?
/// A persistent container to set up the Core Data stack.
lazy var container: NSPersistentCloudKitContainer = {
let fileContainer = URL.storeURL(for: "group name", databaseName: "CoreData")
let container = NSPersistentCloudKitContainer(name: "CoreData")
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()
let localStoreURL = defaultDirectoryURL.appendingPathComponent("Local.sqlite")
let localStoreDescription = NSPersistentStoreDescription(url: localStoreURL)
localStoreDescription.configuration = "Local"
// Create a store description for a CloudKit-backed local store
let cloudStoreDescription = NSPersistentStoreDescription(url: fileContainer)
cloudStoreDescription.configuration = "Cloud"
// Set the container options on the cloud store
cloudStoreDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "containerIdentifier")
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
container.persistentStoreDescriptions = [cloudStoreDescription, localStoreDescription]
container.loadPersistentStores { storeDescription, error in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
// This sample refreshes UI by consuming store changes via persistent history tracking.
/// - Tag: viewContextMergeParentChanges
container.viewContext.automaticallyMergesChangesFromParent = false
container.viewContext.name = "viewContext"
container.viewContext.transactionAuthor = "User"
/// - Tag: viewContextMergePolicy
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.undoManager = nil
container.viewContext.shouldDeleteInaccessibleFaults = true
return container
}()
private func newTaskContext() -> NSManagedObjectContext {
// Create a private queue context.
/// - Tag: newBackgroundContext
let taskContext = container.newBackgroundContext()
taskContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
// Set unused undoManager to nil for macOS (it is nil by default on iOS)
// to reduce resource requirements.
taskContext.undoManager = nil
return taskContext
}
func save() {
if self.container.viewContext.hasChanges {
do {
try self.container.viewContext.save()
} catch {
print(Errors.errorSaving)
}
}
}
func fetchPersistentHistory() async {
do {
try await fetchPersistentHistoryTransactionsAndChanges()
} catch {
print(Errors.fetchPersistentHistory)
}
}
private func fetchPersistentHistoryTransactionsAndChanges() async throws {
let taskContext = newTaskContext()
taskContext.name = "persistentHistoryContext"
try await taskContext.perform {
let changeRequest = NSPersistentHistoryChangeRequest.fetchHistory(after: self.lastToken)
let historyResult = try taskContext.execute(changeRequest) as? NSPersistentHistoryResult
if let history = historyResult?.result as? [NSPersistentHistoryTransaction],
!history.isEmpty {
self.mergePersistentHistoryChanges(from: history)
return
}
throw Errors.fetchPersistentHistoryTransactionsAndChanges
}
}
private func mergePersistentHistoryChanges(from history: [NSPersistentHistoryTransaction]) {
let viewContext = container.viewContext
viewContext.perform {
for transaction in history {
print("Merged by func mergePersistentHistoryChanges ")
viewContext.mergeChanges(fromContextDidSave: transaction.objectIDNotification())
self.lastToken = transaction.token
}
}
}
}
Hello
I have a function to add data to Core Data that has a completion and uses Futures, I wanted to know what is the best way to convert it to use async, because I just started learning how to use async and await. (I am not really sure how to do it)
Here is the function:
func add(context: NSManagedObjectContext, _ body: @escaping (inout Entity) -> Void) -> AnyPublisher<Entity, Error> {
Deferred { [context] in
Future { promise in
context.perform {
var entity = Entity(context: context)
body(&entity)
do {
try context.save()
promise(.success(entity))
} catch {
promise(.failure(error))
}
}
}
}
.eraseToAnyPublisher()
}
Thank You
Hello
What is the best framework for indoor geofencing (with iBeacons devices)? Would the SensorKit framework be any good?
I'm trying to build an indoor geofencing app that uses UWB or BLE devices.
I am thinking of the SensorKit framework because it is used for research and studies and I am looking for the best way to realize indoor geofencing (preferably using UWB devices). The app should also work while it's in the background.
Thank you!
Hello
I have a CoreData PersistenceController and would like to convert it to a SwiftData container. Before converting the whole app to use SwiftData I wanted to know if my conversion is right and preserves old data (in iCloud and local).
Here is the code:
PersistenceController:
import CoreData
import SwiftUI
import Combine
#if os(iOS) || os(macOS) || os(watchOS)
import WidgetKit
#endif
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init() {
let fileContainer = URL.storeURL(for: "group.Water-Alert-App", databaseName: "CoreData")
container = NSPersistentCloudKitContainer(name: "CoreData")
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()
let localStoreURL = defaultDirectoryURL.appendingPathComponent("Local.sqlite")
let localStoreDescription = NSPersistentStoreDescription(url: localStoreURL)
localStoreDescription.configuration = "Local"
// Create a store description for a CloudKit-backed local store
let cloudStoreDescription = NSPersistentStoreDescription(url: fileContainer)
cloudStoreDescription.configuration = "Cloud"
// Set the container options on the cloud store
cloudStoreDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.namel")
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
container.persistentStoreDescriptions = [cloudStoreDescription, localStoreDescription]
container.loadPersistentStores{ (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
}
func save() {
if container.viewContext.hasChanges {
do {
try container.viewContext.save()
} catch {
print("COULD NOT SAVE WITH CORE DATA")
}
}
}
}
ModelContainer:
var container: ModelContainer? = {
let fileContainer = URL.storeURL(for: "group.Water-Alert-App", databaseName: "CoreData")
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()
let localSchema = Schema([Reminder.self])
let cloudSchema = Schema([Goal.self, WaterData.self, Container.self])
let localConfiguration = ModelConfiguration("Local", schema: localSchema, url: defaultDirectoryURL.appendingPathComponent("Local.sqlite"))
let cloudConfiguration = ModelConfiguration("Cloud", schema: cloudSchema, url: fileContainer, cloudKitDatabase: .private("iCloud.Water-Alert-App-Offical"))
let container = try! ModelContainer(for: Reminder.self, Goal.self, WaterData.self, Container.self, configurations: localConfiguration, cloudConfiguration)
return container
}()
Thank you!
Hi everyone,
I’m building a full-screen Map (MapKit + SwiftUI) with persistent top/bottom chrome (menu buttons on top, session stats + map controls on bottom). I have three working implementations and I’d like guidance on which pattern Apple recommends long-term (gesture correctness, safe areas, Dynamic Island/home indicator, and future compatibility).
Version 1 — overlay(alignment:) on Map
Idea: Draw chrome using .overlay(alignment:) directly on the map and manage padding manually.
Map(position: $viewModel.previewMapCameraPosition, scope: mapScope) {
UserAnnotation {
UserLocationCourseMarkerView(angle: viewModel.userCourse - mapHeading)
}
}
.mapStyle(viewModel.mapType.mapStyle)
.mapControls {
MapUserLocationButton().mapControlVisibility(.hidden)
MapCompass().mapControlVisibility(.hidden)
MapPitchToggle().mapControlVisibility(.hidden)
MapScaleView().mapControlVisibility(.hidden)
}
.overlay(alignment: .top) { mapMenu } // manual padding inside
.overlay(alignment: .bottom) { bottomChrome } // manual padding inside
Version 2 — ZStack + .safeAreaPadding
Idea: Place the map at the back, then lay out top/bottom chrome in a VStack inside a ZStack, and use .safeAreaPadding(.all) so content respects safe areas.
ZStack(alignment: .top) {
Map(...).ignoresSafeArea()
VStack {
mapMenu
Spacer()
bottomChrome
}
.safeAreaPadding(.all)
}
Version 3 — .safeAreaInset on the Map
Idea: Make the map full-bleed and then reserve top/bottom space with safeAreaInset, letting SwiftUI manage insets
Map(...).ignoresSafeArea()
.mapStyle(viewModel.mapType.mapStyle)
.mapControls {
MapUserLocationButton().mapControlVisibility(.hidden)
MapCompass().mapControlVisibility(.hidden)
MapPitchToggle().mapControlVisibility(.hidden)
MapScaleView().mapControlVisibility(.hidden)
}
.safeAreaInset(edge: .top) { mapMenu } // manual padding inside
.safeAreaInset(edge: .bottom) { bottomChrome } // manual padding inside
Question
I noticed:
Safe-area / padding behavior
– Version 2 requires the least extra padding and seems to create a small but partial safe-area spacing automatically.
– Version 3 still needs roughly the same manual padding as Version 1, even though it uses safeAreaInset. Why doesn’t safeAreaInset fully handle that spacing?
Rotation crash (Metal)
When using Version 3 (safeAreaInset + ignoresSafeArea), rotating the device portrait↔landscape several times triggers a
Metal crash:
failed assertion 'The following Metal object is being destroyed while still required… CAMetalLayer Display Drawable'
The same crash can happen with Version 1, though less often. I haven’t tested it much with Version 2.
Is this a known issue or race condition between Map’s internal Metal rendering and view layout changes?
Expected behavior
What’s the intended or supported interaction between safeAreaInset, safeAreaPadding, and overlay when embedding persistent chrome inside a SwiftUI Map?
Should safeAreaInset normally remove the need for manual padding, or is that by design?
Hello
Does anyone know how to use real time image recognition in SwiftUI with a Create ML model.
Thank you
Hello, Is there a way to use "switch statement" inside of a NavigationLink Destination?
Example:
NavigationLink(destination:
switch i {
case 0: MatematicaView()
case 1: ArteView()
default: EmptyView()
}){
Text("Hello")
}
(The views are different, that's why I don't put them in one struct)
Thank you