Am developing an iOS App, which uses a ZipFoundation wrapper around Compression. In XCode, have exported a document type with extension '.MU' in the Info.plist.
On iPhone, when attempting to open archive called: 'Snapshot-test.mu'
can OPEN as a mobile email attachment
but FAILED via Files App referring to "iCloud Drive/Desktop"
Here are the respective URLS
"file:///private/var/mobile/Containers/Data/Application/<UniqueID>/Documents/Inbox/Snapshot-test.mu"
"file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/Desktop/Snapshot-test1.mu"
Two questions:
Is it possible to grant access to files residing remotely in iCloud?
Is "iCloud Drive/Desktop" unique, whereas other iCloud locations would be OK?
iCloud & Data
RSS for tagLearn how to integrate your app with iCloud and data frameworks for effective data storage
Post
Replies
Boosts
Views
Activity
Our app is a document-based app that uses UIDocumentBrowserViewController. We are facing an issue when the user is creating a new document on iOS/iPadOS when in the “Recents” tab (as opposed to the “Browse” tab). Specifically, the document is saved to a hidden ubiquity container. As a result, the user cannot find the file in the document browser. It also does not appear in “Recents”. The expected behaviour would be a folder with our app's icon on it on the user’s iCloud Drive, which contains the files the user creates when in the “Recents” tab.
This issue started to happen when we introduced a new feature that uses iCloud Documents with its own ubiquity container. I'm not sure how UIDocumentBrowserViewController handled saving documents to a default location on iCloud Drive before we had the iCloud Documents entitlement enabled. All I know is that there were no issues.
How to recreate the issue:
Create a document-based app with UIDocumentBrowserViewController. Run the app and create a document while in the recents tab with iCloud enabled. The document will be stored to a folder on iCloud.
Now, enable iCloud Documents and specify a ubiquity container. Then, try to create documents in the Recents tab. The location in which the documents are created cannot be navigated to.
I have a strange crash which I have problems understanding. It only happens on a few devices, after a ModelContainer migration, and it doesn't seem to crash on the migration itself.
The fetch is done in onAppear, and shouldn't necessarily result in a crash, as it is an optional try:
let request = FetchDescriptor<Rifle>()
let data = try? modelContext.fetch(request)
if let data, !data.isEmpty {
rifle = data.first(where: { $0.uuid.uuidString == settings.selectedRifleId }) ?? data.first!
}
When I get logs from users, there seems to be an error in encoding?
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000018e8bfd78
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [71687]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libswiftCore.dylib 0x18e8bfd78 _assertionFailure(_:_:file:line:flags:) + 264
1 SwiftData 0x24e18b480 0x24e14c000 + 259200
2 SwiftData 0x24e193968 0x24e14c000 + 293224
3 SwiftData 0x24e195a78 0x24e14c000 + 301688
4 libswiftCore.dylib 0x18e8e4084 _KeyedEncodingContainerBox.encodeNil<A>(forKey:) + 352
5 libswiftCore.dylib 0x18e8d79f0 KeyedEncodingContainer.encodeNil(forKey:) + 64
6 SwiftData 0x24e19f09c 0x24e14c000 + 340124
7 SwiftData 0x24e1a3dec 0x24e14c000 + 359916
8 libswiftCore.dylib 0x18ec10be8 dispatch thunk of Encodable.encode(to:) + 32
9 SwiftData 0x24e1cd500 0x24e14c000 + 529664
10 SwiftData 0x24e1cd0c8 0x24e14c000 + 528584
11 SwiftData 0x24e1da960 0x24e14c000 + 584032
12 SwiftData 0x24e1ee2ec 0x24e14c000 + 664300
13 SwiftData 0x24e1d97d8 0x24e14c000 + 579544
14 SwiftData 0x24e1eada0 0x24e14c000 + 650656
15 SwiftData 0x24e1d989c 0x24e14c000 + 579740
16 SwiftData 0x24e1eee78 0x24e14c000 + 667256
17 Impact 0x1027403bc 0x10268c000 + 738236
Hi,
I've got an app using SQLLite. Under iOS 17 I could insert and select rows with no issues. Under iOS 18 the same code runs without errors but the select returns no results. Various select statements with and without where clause's, and freshly created database files all behave the same way.
Unless... the phone is in developer mode, then it works same as iOS 17. I'm assuming it's some security change, how do we fix it? Same issue with Swift 5 and Swift 6 for context but I don't think its related to Swift.
Thanks !
Dear Apple Developer Forum
As the title suggests, I have an issue with Swift Data when I want to modify a property of a recursive model class instance. Please consider the following sample project:
import SwiftUI
import SwiftData
@main
struct ISSUEApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
Item.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
@Model
final class Item {
var name: String?
var parent: Item?
init(name: String?, parent: Item?) {
self.name = name
self.parent = parent
}
}
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var items: [Item]
@State private var itemToMove: Item?
@State private var count: Int = 0
@State private var presentMoveView: Bool = false
var body: some View {
NavigationStack() {
List(items, id: \.id) {item in
Button(action: {
itemToMove = item
}, label: {
Text("Id: \(item.name ?? "ERROR") and my parent iD is \(item.parent?.name ?? "root")")
.bold(itemToMove == item)
.italic(itemToMove == item)
})
}
.sheet(isPresented: $presentMoveView, content: {
MoveView(toMove: self.itemToMove!)
})
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
let i = Item(name: "\(count)", parent: nil)
context.insert(i)
try? context.save()
count += 1
}, label: {
Text("Add an item")
})
}
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
presentMoveView.toggle()
}, label: {
Text("Move selected item")
})
}
}
}
}
}
struct MoveView: View {
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
@Query private var items: [Item]
@Bindable var toMove: Item
@State private var selectedFutureParent: Item?
var body: some View {
NavigationStack(){
List(items, id: \.id) {item in
Button(action: {
selectedFutureParent = item
}, label: {
Text("Id: \(item.name ?? "ERROR") and my parent iD is \(item.parent?.name ?? "root")")
.bold(selectedFutureParent == item)
.italic(selectedFutureParent == item)
})
}
.toolbar(){
ToolbarItem{
Button("Move", action: {
toMove.parent = selectedFutureParent
dismiss()
})
}
}
}
}
}
#Preview {
ContentView()
.modelContainer(for: Item.self, inMemory: true)
}
Please launch the preview of this app, add items (as many as you'd like), select one and click on the "Move selected item" button. Select the new parent of the item. As you may have noticed, both selected items (moved item and new parent) are modified, whereas only one equality is used. This issue seems to be independent from the @Bindable property wrapper. I tried many things, such as using index instead of direct elements; using local let constant for the parent but the constant is still modified (very weird...)
Thank you in advance for your help !
Best regards
Using this Apple repository as a basis
https://github.com/apple/sample-cloudkit-zonesharing
I created and verified the shared zone and the same zone is private for the person who shared it and shared for the person who received it, so aren't they the same zones?
[same zone but different id?]
I can make the person who shared the zone (owner) access the zone as a .shared scope just like the person who was shared.
I am working on an app that will have about 200mb of data in a database. I would like to install a json file with 3-4 mb on the phone with the app, and then be able to send small packets of information to the user of the app as they are using the app, for example if they hit a button with a link to an instagram page, I can have the database/server send the link to the app, it will be just small bits of information going from the database to the phone, and perhaps I would do some location tracking and getting some information from the user to build up personal preferences etc. I'm wondering if coredata would be the best way to get smaller packets of information to the phone quickly or if I should think about firebase or something else. I was interested in using Cloudkit, but it seems like Cloudkit is really more about syncing devices and for getting information from the user to the database. It's been really hard to find any information about the strengths versus weaknesses of different databases and how they interact with mobile apps.
I'm using NSPersistentCloudKitContainer to sync CoreData to CloudKit public database but I have the problem that canUpdateRecord always returns true even for objects created by another iCloud user with _icloud role permission set to Read only. Am I missing something?
I have enabled an App Group in my App and the Widget Extension. I use it to share my UserDefaults. Every time the app starts I now get the following error message in the Xcode console:
Couldn't read values in CFPrefsPlistSource<0x303034510> (Domain: group.XX.XXXX.XXXX, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd
The shared UserDefaults itself works without problems.
Any ideas how I could get rid of this warning?
I have a bug I've come across since I've upgraded Xcode (16.0) and macOS (15.0 Sequoia) and figured I'd create a minimal viable example in case someone else came across this and help. I've noticed this in both the macOS and iOS version of my app when I run it.
Essentially I have an area of my code that calls a class that has a step 1 and 2 process. The first step uses async let _ = await methodCall(...) to create some SwiftData items while the second step uses a TaskGroup to go through the created elements, checks if an image is needed, and syncs it. Before this worked great as the first part finished and saved before the second part happened. Now it doesn't see the save and thus doesn't see the insertions/edits/etc in the first part so the second part just isn't done properly. Those step one changes are set and shown in the UI so, in this case, if I run it again the second part works just fine on those previous items while any newly created items are skipped.
I came across this issue when step one handled 74 inserts as each one didn't contain an image attached to it. When I switched the async let _ = await methodCall(...) to a TaskGroup, hoping that would wait better and work properly, I had the same issue but now only 10 to 30 items were created from the first step.
Minimal Viable Example: to reproduce something similar
In my minimal viable sample I simplified it way down so you can't run it twice and it's limited it creating 15 subitems. That said, I've hooked it up with both an async let _ = await methodCall(...) dubbed AL and a TaskGroup dubbed TG. With both types my second process (incrementing the number associated with the subissue/subitem) isn't run as it doesn't see the subitem as having been created and, when run with TaskGroup, only 12 to 15 items are created rather that the always 15 of async let.
Code shared here: https://gist.github.com/SimplyKyra/aeee2d43689d907d7a66805ce4bbf072
And this gives a macOS view of showing each time the button is pressed the sub issues created never increment to 1 while, when using TaskGroup, 15 isn't guaranteed to be created and remembered.
I'm essentially wondering if anyone else has this issue and if so have you figured out how to solve it? Thanks
All of a sudden my app started getting this CloudKit error, and it happens to a lot of users. I had no changes to cloud sync for months and really surprised by seeing this. What confuses me even more, is that there is no information on the web about this kind of error. I have no idea what causes it and how to solve it. Would love to get any feedback from the CloudKit engineer.
Client went away before operation 27761871408C460A could be validated; failing
{
"NSUnderlyingError": "<CKUnderlyingError 0x600002573f30: \"ClientInternalError\" (2005); \"Client went away before operation 27761871408C460A could be validated; failing\">",
"CKErrorDescription": "Client went away before operation 27761871408C460A could be validated; failing",
"NSDebugDescription": "CKInternalErrorDomain: 2005",
"NSLocalizedDescription": "Client went away before operation 27761871408C460A could be validated; failing"
}
Seems to happen only on macOS.
Hello,
After iOS 18 fetchChanges() method of CloudKitSync engine does not work as before. Calling the function doesn't fetch changes always, but it does fetch on iOS 17.
However going background and foreground again fetches changes automatically.
I have a requirement to get all records changed after a certain date.
I have set modifiedTimestamp as Queryable, but when I attempt to do any query at all using the following operators: > < >= <= no results are returned. I have confirmed there are records that should be returned. The only operator that works is == and !=.
I have tried the following:
NSPredicate(format: "modificationDate > %@", lastFetched as NSDate)
NSPredicate(format: "___modTime > %@", lastFetched as NSDate)
Hello!
I deleted an index on the cloudkit console of a container in development environment and re-added it again with the same name. After that my app has been giving error on development environment.
The live version is working fine as I haven't deployed the changes.. Any idea what can cause this issue and is there a way to fix it? Thank you
I'm a bit lost because of a problem I never experienced before: I create entries in 3 Core Data tables and link them. As long as the app is open, everything is fine, I can see the database entries in the three tables. Once the App is closed and restarted, however, the new entries in two of the three tables are gone.
I use Core Data for data storage and DB Browser for SQLite for inspecting the database running in the Simulator.
Here's the relevant function where all Core Data handling happens:
/**
Creates a new ComposedFoodItem from the ComposedFoodItemViewModel.
Creates the related FoodItem and the Ingredients.
Creates all relationships.
- Parameter composedFoodItemVM: The source view model.
- Returns: A Core Data ComposedFoodItem; nil if there are no Ingredients.
*/
static func create(from composedFoodItemVM: ComposedFoodItemViewModel, generateTypicalAmounts: Bool) -> ComposedFoodItem? {
debugPrint(AppDelegate.persistentContainer.persistentStoreDescriptions) // The location of the .sqlite file
let moc = AppDelegate.viewContext
// Create new ComposedFoodItem (1)
let cdComposedFoodItem = ComposedFoodItem(context: moc)
// No existing composed food item, therefore create a new UUID
cdComposedFoodItem.id = UUID()
// Fill data
cdComposedFoodItem.amount = Int64(composedFoodItemVM.amount)
cdComposedFoodItem.numberOfPortions = Int16(composedFoodItemVM.numberOfPortions)
// Create the related FoodItem (2)
let cdFoodItem = FoodItem.create(from: composedFoodItemVM, generateTypicalAmounts: generateTypicalAmounts)
// Relate both (3)
cdComposedFoodItem.foodItem = cdFoodItem
// Add cdComposedFoodItem to composedFoodItemVM
composedFoodItemVM.cdComposedFoodItem = cdComposedFoodItem
// Add new ingredients (4)
if let cdIngredients = Ingredient.create(from: composedFoodItemVM) {
cdComposedFoodItem.addToIngredients(NSSet(array: cdIngredients))
// Save new composed food item
try? moc.save()
// Return the ComposedFoodItem
return cdComposedFoodItem
} else {
// There are no ingredients, therefore we delete it again and return nil
moc.delete(cdComposedFoodItem)
try? moc.save()
return nil
}
}
What the function does:
Creates a new entry in table ComposedFoodItem
Creates another new entry in another table FoodItem
Relates both entries
Creates another 1..n entries in a third table Ingredient and links these to the entry created in step 1
All this works fine, I can see all relations and entries in the database.
Then I quit and restart the app. The entry created in step 2 is still there, but the entries created in steps 1 and 4 are gone, as well as the relationships (of course).
My suspicion: I recently implemented a Core Data migration from Data Model version 1 ("EasyFPU") to version 2 ("EasyFPU 2"). In this migration, I have two custom migration policies for exactly the two tables, which are not stored. The migration policies are pretty simple (and identical for both tables):
/**
No Ingredient is created in the destination model, i.e., there will be no Ingredients
*/
override func createDestinationInstances(forSource sourceIngredient: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
// Do nothing on purpose
debugPrint("Not migrating Ingredient with ID: \((sourceIngredient as? Ingredient)?.id.uuidString ?? "unknown")")
}
And what I suspect is, that this migration policies are somehow called when restarting the app, but I have no idea why, because the migration has already happened before. If I set a breakpoint in the debugPrint line of the code snippet above, I actually never reach this breakpoint - as expected. Nevertheless are the two tables Ingredient and ComposedFoodItem empty after restart.
My AppDelegate Core Data persistentContainer variable looks like this:
lazy var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "EasyFPU")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
I tried to replace "EasyFPU" with "EasyFPU 2", but this apparently is not the version, but the container name.
Any idea? Thanks in advance!
I'm studying sharing through this link. I followed the first steps by changing the bundle identifier of the project, the tests and placing my own container in the config and in the info.plist.
https://github.com/apple/sample-cloudkit-zonesharing
The app appears and in the log it appears that it has managed to access my iCloud, but when I click on share and share something, the following message appears in the console, on the simulator and on the iPhone:
"No options were found, providing default value for access type"
"No options were found, providing default values for permissions"
"connection invalidated"
And finally, when I click on the shared link, the following message appears:
"Item unavailable
The owner stopped sharing, or you don't have permission to open it."
When using Core Data I would override willSave on NSManagedObject to compute alastModified value on a model object. This allowed one simple method to check changed values and set a date if necessary.
It is possible set lastModified in SwiftData, but the approaches I have found all have drawbacks when compared to the previous approach.
Hide saved model properties behind transient versions
private var textSaved: String = ""
var text: String {
get { textSaved }
set {
textSaved = newValue
lastModified = .now
}
}
I could hide every property that should update the lastModified behind a computed value, but this requires additional code for each new property and obfuscates the model definition.
Update all properties through an update function
func update<T>(keyPath: ReferenceWritableKeyPath<Player, T>, to value: T)
Paul Hudson notes a workaround where any changes are made to the model through an update function that takes a keyPath. This will add complexity to every view that wants to modify model properties, and also leaves those properties open to change through other approaches.
Use ModelContext.willSave
ModelContext sends a notification when it is about to save. This could be caught in .onReceive in a view or perhaps in some model-holding singleton, then ALL changes queried and dealt with accordingly. Perhaps the best approach here would to add willSave to all model objects so code external to the model isn't doing the lastModified logic.
This last solution feels like the best way forward that I know (ideally avoiding any .onReceive code in views). Should I prefer another solution or are there better ones I have missed?
Juust before I initiate an App Transfer...
We have sandboxed 'mobile' versions of our app (iOS and mac App) to transfer to the surviving company.
However, we also have a 'full' non-sandboxed legacy desktop dmg version of the app, available for Mac (and Win). This has access to the same iCloud folder
So the question is, what happens to the iCloud app folder on the Mac if they are only using this desktop version, once the transfer takes place? Will it remain visible on the Mac, and will it remain accessible by the desktop version if so?
I expect that although the iCloud entitlement is transferred, as it is another Team ID, the legacy app will not be able to read/write without user prompted permission. What I hope at the least, is that the folder doesn't become invisible on that machine...
I am encountering an issue with the UndoManager functionality in a SwiftUI application that integrates SwiftData for persistence. This issue occurs specifically in macOS 14 (Sonoma) but works as expected on macOS 15 (Sequoia).
The focused test app I have prepared for demonstration allows users to create ParentItem objects, and for each ParentItem, users can add multiple ChildItem objects. The undo functionality (via Cmd+Z) is not working as expected in Sonoma. When I try to undo a ChildItem addition, the UndoManager does not revert just the last ChildItem added, but instead removes all ChildItems that were added in that session.
Expected Behavior
On macOS 14 (Sonoma), I expect the UndoManager to undo only the most recent transaction (in this case, a single ChildItem insert), similar to how it functions on macOS 15 (Sequoia). Each ChildItem insertion should be treated as a separate undoable action.
Current Behavior
In macOS Sonoma, pressing Cmd+Z undoes the entire list of ChildItems added to a ParentItem in the current session, rather than just the most recent ChildItem. This appears to be an issue with undo grouping, but I’ve confirmed that no explicit grouping is being used.
Question
Is this an issue with UndoManager in macOS Sonoma, particularly in how it interacts with SwiftData persistence? What changes should I make to ensure that each ChildItem insert is treated as an individual undo action in macOS Sonoma, just as it works in Sequoia?
Any guidance on isolating the issue or recommended workarounds would be appreciated. I would expect that undo actions for each child addition would be treated as separate transactions, not grouped.
Steps Taken to Solve the Problem
I attempted to manually save the model context (modelContext.save()) after each ChildItem insert to ensure proper persistence.
I also verified that UndoManager was not grouping operations explicitly by calling beginUndoGrouping() or endUndoGrouping() myself.
This issue seems to be tied specifically to macOS Sonoma, as it does not occur on macOS Sequoia, where undoing behaves as expected.
Conditions
macOS 14 Sonoma: The issue occurs consistently.
macOS 15 Sequoia: The issue does not occur.
This issue appears to be independent of hardware, as I’ve tested it on multiple machines.
APIs/Features Potentially Involved
UndoManager in a SwiftUI application
SwiftData for persistence (using modelContext.save())
macOS version-specific behavior
Steps to reproduce
Clone test project (https://github.com/Maschina/SwiftDataUndoManagerExample), compile and run
Create a new ParentItem in the app (via plus toolbar button in the sidebar).
Add multiple ChildItems to the ParentItem (via plus toolbar button in the content / middle column of the navigation split view).
Press Cmd+Z to undo the last addition.
My app needs to share data files with multiple devices owned by a single user.
I also want to implement this mechanism without setting up a server.
Therefore, I want to make it read/write to local data on the user's own cloud drive (e.g. iCloud, Google Drive, One Drive, Dropbox) and read/use them as needed.
I have tried “.fileImporter” to get the URL, but the button is grayed out and cannot be opened.
Sorry for my poor English.
struct FilePathSettingView: View {
@State private var isPickerPresented: Bool = false
var fileControll = FileControll()
var body: some View {
VStack {
Text("Storage Setting")
Button(action:{
isPickerPresented = true
})
{
Text("Select place")
}
.fileImporter(
isPresented: $isPickerPresented,
allowedContentTypes: [.directory, .folder],
allowsMultipleSelection: false,
onCompletion: { result in
switch result {
case .success(let urls):
guard let url = urls.first else { return }
let accessGranted = url.startAccessingSecurityScopedResource()
defer {
if accessGranted {
url.stopAccessingSecurityScopedResource()
}
}
guard accessGranted else {
print("Failed to access security-scoped resource.")
return
}
fileControll.createDirectoryStructure(in: url)
case .failure(let error):
print("Failed to select directory: \(error.localizedDescription)")
}
}
)
}
}
}