Hey, I have been working on the app that implements both Content Filter Providers and DNS Proxy for custom network security app. However, I would like to display traffic logs from Content Filter. What's the best way to do that?
I know that it works with UserDefaults under shared container with App Group. But I am not sure that it's the best approach for storing data that is constantly changing. I also tried to use CoreData with:
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
But I receive error that "The file couldn’t be saved because you don’t have permission., ["reason": No permissions to create file; code = 1]" because my FilterDataProvider has access to CoreData model.
Core Data
RSS for tagSave your application’s permanent data for offline use, cache temporary data, and add undo functionality to your app on a single device using Core Data.
Posts under Core Data tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Suppose I have two iPhones that are offline. On the first iPhone, at 1 PM, I create a Person object with the details: name: "John", lastName: "Smith", and age: 40. Then, on the second iPhone, which is also offline, I also create Person object at 2 PM with the same name: "John" and lastName: "Smith", but with a different age: 30.
Both iPhones come online at 3 PM and sync with CloudKit. I would expect CloudKit to reconcile these two records and end up with a single record—specifically, Person(name: "John", lastName: "Smith", age: 30), assuming a "last writer wins" approach.
Any guidance or best practices for handling this situation would be greatly appreciated!
My idea is that I could generate a 128bit UUID as hash from first name and last name and then I would have to force this UUID to be used as recordName in CKRecord as this would trigger a conflict on CloudKit side and prevent two instance to be created. But how do I accomplish this with SwiftData or CoreData?
Hi there,
In short, I'm trying to use CoreData in my ShieldConfigurationDataSource extension. Trying to fetch from core data at all seems to cause the shield to render it's default look. I already added the extension to an app group + configured my persistence store to use the app group. Below is my code, any help is appreciated:
// Shield extension
override func configuration(shielding application: Application) -> ShieldConfiguration {
do {
let appSelectionId = "***"
let blockedItemReq = ...
blockedItemReq.predicate = ...
let moc = PersistenceController.shared.container.viewContext // Commenting this and the bottom out makes it work, but I need the data!
let blockedItemRes = try moc.fetch(blockedItemReq)
let shieldTitle = ShieldConfiguration.Label(text: "Hello there", color: .red)
return ShieldConfiguration(backgroundColor: .black, title: shieldTitle)
}
catch {
let shieldTitle = ShieldConfiguration.Label(text: "ERROR \(error.localizedDescription)", color: .white)
return ShieldConfiguration(backgroundColor: .black, title: shieldTitle)
}
}
// Persistence Controller
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "AppBlockerOne")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
else {
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.appblockerone")!
let storeURL = containerURL.appendingPathComponent("AppBlockerOne.sqlite")
let description = NSPersistentStoreDescription(url: storeURL)
container.persistentStoreDescriptions = [description]
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
Any insights on how to incorporate CloudKit (or CoreData) in the WidgetKit extension? Where in the WidgetKit api do I make the asynchronous call to load the data to be available for the TimelineProvider?
I create a CKShare and then I set the title:
share[CKShare.SystemFieldKey.title] = title
I even call:
if let cloudStore = coreDatabase.cloudStore {
try await persistentContainer.persistUpdatedShare(share, in: cloudStore)
}
but when I retrieve this share again using
persistentContainer.fetchShares(matching: [id])
the title is not set. I even checked CloudKit console and I can't see there title either...
How can I retrieve the previously set title for a share?
It is possible to append a record to a CKShare using
NSPersistentCloudKitContainer.share(objects, to: share)
but how can I reverse this operation and remove the object from share?
The workaround would be to delete and recreate the object, but is there any SDK function to do it right? The more I work with CoreData+CloudKit the more it seems like everything there is a workaround or hack or bug... This SDK is still in Alpha at best.
I need to know which records belong to a specific CKShare. I can retrieve a share for a single record, but then having the CKShare I can't check what other records belong to it.
Is there any better way to do it without fetching shares for the whole database and grouping them?
It seems that when an entity has and ordered to-many relationship to the same entity, inserting an object into the ordered set causes other objects of the set to turn into faults during the next save of the managed object context.
I verified it with several applications.
For the sake of example, the entity will be called Folder and the ordered to-many relationship subfolders (an NSOrdereset), with a cascade delete rule. The reciprocal to-one relationship is called parent.
Assuming you have a Folder object with two subfolders, removing the last subfolder from the set (setting its parent to nil) and reinserting it at index 0 with insertObject:<>inSubfoldersAtIndex:0 will turn the other subfolder into a fault at the next save.
Now assuming that other folder has a name attribute (NSString) that is bound to a textfield in your UI, the name of that subfolder will disappear when the context saves, since it becomes nil while the subfolder is turned into a fault.
Is this expected behavior?
Note: I'm using Objective C, Xcode 15 and macOS sonoma, but I've seen this issue occur on previous macOS versions.
My app started crashing a ton with Xcode 16 beta 1 / iOS 18 because of "Thread 1: Fatal error: Never access a full future backing data". I was hoping this would be resolved with beta 2, but unfortunately this is not the case. I'm having a tough time reproducing this bug in a small sample project – I'd appreciate any hints as to what might be causing this.
Full error:
Thread 1: Fatal error: Never access a full future backing data - PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://10A5A93C-DC7F-40F3-92DB-F4125E1C7A73/MyType/p2), implementation: SwiftData.PersistentIdentifierImplementation) with Optional(3BF44A2D-256B-4C40-AF40-9B7518FD9FE6)
Hi, guys. When I update a value in a Core Data object, the view is not updated to show the change. I don't understand what I'm doing wrong, since this worked before. Right now I have Xcode 16 Beta installed, but it happens with Xcode 15. Here is an example.
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var selectedItem: Item?
var body: some View {
NavigationStack {
VStack {
Text("Year: \(selectedItem?.year ?? 0)")
.onTapGesture {
changeYear()
}
Spacer()
}
.onAppear {
// Load an item from the database
let request: NSFetchRequest<Item> = Item.fetchRequest()
request.fetchLimit = 1
if let item = try? viewContext.fetch(request).first {
selectedItem = item
}
}
}
}
private func changeYear() {
let year = Int16.random(in: 1900..<2020)
print("Random year: \(year)")
selectedItem?.year = year
try? viewContext.save()
}
}
#Preview {
ContentView()
.environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
I think it is easy to follow. There is an entity called Item with an attribute called year. I preloaded a few objects for the preview. This view loads one item and assigns it to a state property. When you tap on the Text view, the changeYear() method is executed. In this method I select a random year, assign it to the object in the selectedItem property and save the context. A message is printed on the console with the new value, but the view never updates. I'm also having similar problems with SwiftData and To Many relationships. They also do not update the views when they are modified.
In case you want to test it, you can just create a new project with Core Data set in, change the name of the attribute in the Item entity to year and select Int16 as the data type, and then update the following method to preload some values.
@MainActor
static let preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.year = Int16.random(in: 1900..<2020)
}
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
Thanks for any help.
I am using SwiftData for my model. Until Xcode 15 beta 4 I did not have issues. Since beta 5 I am receiving the following red warning multiple times:
'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
This seems to be a CoreData warning. However, I am not using CoreData directly. I have no way to change the config of CoreData as used by SwiftData.
My model just uses UUID, Int, String, Double, some of them as optionals or Arrays. I only use one attribute (.unique).
I have a simple app that generates a record based on some user input. I'd like to take it to a summary of that record after taking in the input and generating a report from that input. The way I've rigged it so far is that the button fires off actions that generate the record also fires off the following code that redirects the UI to the record view.
if let window = windowScene?.windows.first {
window.rootViewController = UIHostingController(rootView: ReadingSpreadView(history: historyEntry, spread: spread, spreadTitles: spreadTitles))
window.makeKeyAndVisible()
}
However, when I hit my custom back button my MOC context is being lost somewhere as I'm getting:
Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x30398c4e0>
When I try to browse the history view.
I suspect the reason why I need the custom back button and that I'm losing the MOC context is that I'm doing something wrong with CoreData, or SwiftUI or something.
What's the appropriate way of doing this? Most of my experience has been in MVC frameworks on the Web with JavaScript frontend if that helps.
We have a crash regarding to Core Data access that was not reproducible in our side but the crash count keeps increasing with the last stack trace is assertionFailure from Apple internal SDK.
The last stack trace before the assertionFailure by system is our code initializing CoreData in DataContainer.init(name:bundle:inMemory:) where we will try to access CoreData and the error message we found from our 3rd party crash reporter is something like this DataStore/DataContainer.swift:30: Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=256 "The file “Content.sqlite” couldn’t be opened. UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/9DBF262C-851A-486B-90CC-4397A8896525/Library/Application Support/Content.sqlite, NSSQLiteErrorDomain=13}, ["NSSQLiteErrorDomain": 13, "NSFilePath": /var/mobile/Containers/Data/Application/9DBF262C-851A-486B-90CC-4397A8896525/Library/Application Support/Content.sqlite]
That sqlite file is supposed to be file used by Core Data (since we have no other code that access it) and we are quite confused on why sometimes the CoreData cannot be accessed with that kind of error message. So far, we still have no idea to reproduce it and what do to resolve it.
I have submitted the report with bug number: FB14433998
I attached an example of the crash report here too.
Please gave us insight on why it happened and how we can prevent it from happening again.
crash log 1.crash
On top of unstable CloudKit sync, we've got also extremely unstable sharing/collaboration functionality.
I mean, it's quite impressive how easy it is to enable sharing, but this feature should not be released at this point. It feels like using software in the alpha version.
Let's take NSPersistentCloudKitContainer.share(_:to:) (https://developer.apple.com/documentation/coredata/nspersistentcloudkitcontainer/3746834-share), the documentation says:
Sharing fails if any of the following conditions apply:
Any objects in managedObjects, or those the traversal finds, belong to > an existing share record.
However, it's wrong... if you pass any object from the existing share, it will return the same share... It never fails in this case.
Things are getting even weirder if you experiment a little bit with shares. So let's assume you share a couple of objects:
persistentContainer.share([A, B, C, D], to: nil)
Now you stop sharing those via UICloudSharingController and you want to share again but just C. So you call:
persistentContainer.share([C], to: nil)
and surprise, surprise, you get a new share URL, but you share all previously shared objects (A, B, C, D), not as you would have expected only C...
On top of that, you keep getting some weird errors like:
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _requestAbortedNotInitialized:](2190): <NSCloudKitMirroringDelegate: 0x3029b84b0> - Never successfully initialized and cannot execute request '<NSCloudKitMirroringExportRequest: 0x30359f1b0>123123123123' due to error: <CKError 0x3018699b0: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 12312312312312; container ID = "iCloud.some.id"; partial errors: {
com.apple.coredata.cloudkit.share.123123123123123:__defaultOwner__ = <CKError 0x30186a3d0: "Invalid Arguments" (12/2006); server message = "Only shared zones can be accessed in the shared DB"; op = 12312312312312; uuid = 123123123123>
}>
Even though the only thing I use is
persistentContainer.share
and
UICloudSharingController(share: share, container: cloudKitContainer)
And the cherry on the top, from time to time if you play a little with sharing multiple objects at once, it happens that it randomly wipes out some records from that share...
I don't even know where to start reporting issues and if its worth it, because every ticket will be dismissed anyway because "we need thousands of your logs, we require you to do all the job for us".
What is the recommended way of intercepting and processing errors?
As far as I know, there are 4 main areas:
iCloud account status - this can be checked and intercepted via notifications
exceptions from fetch/execute/save - it can be a simple do..catch, but what exceptions can we expect here, what should be handled, and how?
there could be some asynchronous issues with synchronization. How should we intercept them and how should they be handled?
issues with iCloud storage - quota exceeded, etc. How to intercept & handle those?
I'm trying to achieve production-ready implementation, but there are many pitfalls and hidden issues that are not well documented. Could you provide some advice on how to handle properly all these situations?
Hello,
I'm using NSPersistentCloudKitContainer. If the user disables iCloud sync for my app in the system settings and opens the app, all records are immediately wiped out, even if there are unsynced changes (like records added offline).
Disabling iCloud sync doesn't even show any warning, so the user may lose all data (if it's not already synced to Cloud).
Is it possible to intercept that the store will be wiped out when the app is launching? I would copy all records to the local storage then to avoid losing data by the user.
Is there any version of UICloudSharingController available on macOS or do we need to handle it manually?
How to manually configure a share and send an invitation from macOS?
CloudKit sync is very unstable. Sometimes it just stops syncing for no reason, other times it works almost instantly.
The core issue with synchronization is that CoreData relies mostly on two things:
silent push notifications, which are by design unreliable and can be throttled
user interactions, I noticed that the local database is updated most likely periodically and also based on some app events like entering the foreground.
Unfortunately, there is no SDK function that allows us to force sync with CloudKit, which basically prevents us from providing some features to recover if a user encounters problems.
After thousands of tests, I finally discovered what was wrong and how to make the synchronization stable. Basically, I noticed that at some point CoreData decides that it won't synchronize data unless you deactivate and activate the application, which is crazy. It's getting even worse if we talk about extensions like the keyboard extension on iOS. The same happens on all platforms.
Therefore, knowing that I implemented a trick that happened to work perfectly. The workaround requires to periodically sending an event pretending that the app is going foreground.
macOS:
var cancellable = Set<AnyCancellable>()
// ...
Timer.publish(every: 20.0, on: RunLoop.main, in: .common)
.autoconnect()
.sink { _ in
NotificationCenter.default.post(.init(name: NSApplication.willBecomeActiveNotification))
}
.store(in: &cancellable)
iOS:
var cancellable = Set<AnyCancellable>()
// ...
Timer.publish(every: 20.0, on: RunLoop.main, in: .common)
.autoconnect()
.sink { _ in
NotificationCenter.default.post(.init(name: UIApplication.didBecomeActiveNotification))
}
.store(in: &cancellable)
After that, everything works perfectly. Pitty that the solution mostly meant for enterprise is so unstable and there is not even a single SDK function to recover from that (force sync).
Any plans to fix CoreData+CloudKit? I also created a ticket: #FB14531806.
On iOS 13 I used to use optional @State properties to adapt views. In my case, the presented view would either create a new object (an assignment) if the state that is passed into it is nil, or edit the assignment if an assignment was passed in. This would be done in the action block of a Button and it worked beautifully.
On iOS 14 / Xcode 12 this no longer seems to work. Given the following code which creates a new assignment and passes it into the editor view when the user taps a "New Assignment" button, the value of assignment remains nil. Is anyone else experiencing similar behaviour?
struct ContentView: View {
		@Environment(\.managedObjectContext) var context
		@State var assignmentEditorIsPresented = false
		@State var assignment: Assignment? = nil
		var Body: some View {
				[...]
				Button("New Assignment", action: {
						self.assignment = Assignment(context: context)
						self.assignmentEditorIsPresented = true
				})
				.sheet(isPresented: assignmentEditorIsPresented) {
						[...]
				}
		}
}
What's even weirder is that I tried adding a random piece of state, an Int, to this view and modifying it right before the assignment state (between lines 9 and 10) and it didn't change either.
I have undoManager working with a CoreData backed app but I would like to either pause undoManager during certain data changes or be able to pop the last undo off the undoManager “stack".
Ideally, I would like to
Delete Object A
Pause undoManager
Delete Object B
Unpause undoManager
Delete Object C
So the undo stack looks like:
Undo Delete Object C
Undo Delete Object A
In this instance, object B was created by an unfinished multi-screen workflow that was canceled by the user - but there are a few other examples in my app as well.
So far I have tried disableUndoRegistration() like so:
container.viewContext.processPendingChanges()
container.viewContext.undoManager?.disableUndoRegistration()
This has no effect. The undo action is still recorded.
I have tried swapping the undoManager to nil after parking it elsewhere and then reassigning it after deleting object B. This effectively works the same as undoManager.removeAllActions().
And I have tried removing all actions for the target Object B after deleting Object B. Also with no effect.
viewContext.undoManager?.removeAllActions(withTarget: objectB)
My workaround is to simply reset the entire stack with .removeAllActions() but that’s not ideal.
Any ideas on how to make this work?
Thanks.