I have a simple test application that attempts to share a CoreData record with another user using NSSharingService. I can create my share and that works,
but when I try to receive the share it opens up the application but doesn't do anything.
I have added CKSharingSupported to my plist.
I have also followed this link to no avail: CloudKit CKShare userDidAcceptCloudKitShareWith Never Fires on Mac App
Here is my code:
SharingServiceApp:
final class AppDelegate: NSObject, NSApplicationDelegate
{
func application(_ application: NSApplication, userDidAcceptCloudKitShareWith metadata: CKShare.Metadata)
{
print ("userDidAcceptCloudKitShareWith")
let shareStore = persistenceController.sharedPersistentStore!
persistenceController.container.acceptShareInvitations(from: [metadata], into: shareStore)
{ _, error in
if let error = error
{
print("acceptShareInvitation error :\(error)")
}
}
}
}
ContentView:
import SwiftUI
import CoreData
import CloudKit
let persistenceController = PersistenceController()
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
NavigationView {
List {
ForEach(items) { item in
NavigationLink {
VStack
{
Text("Item at \(item.timestamp!, formatter: itemFormatter)")
Button("Share")
{
shareRecord(item: item)
}
}
} label: {
Text(item.timestamp!, formatter: itemFormatter)
}
}
}
.toolbar {
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
Text("Select an item")
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
private let itemFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
return formatter
}()
func shareRecord(item: Item)
{
Task
{
if let share = await createShare(item: item)
{
let container = CKContainer(identifier: "iCloud.com.xxxxxxxx.sharingservice")
let item = NSItemProvider()
item.registerCloudKitShare(share, container: container)
DispatchQueue.main.async
{
let sharingService = NSSharingService(named: .cloudSharing)
sharingService!.perform(withItems: [item])
}
}
}
}
private func createShare(item: Item) async -> CKShare?
{
do
{
let (_, share, _) = try await persistenceController.container.share([item], to: nil)
share[CKShare.SystemFieldKey.title] = "MyApp"
return share
}
catch
{
print("Failed to create share")
return nil
}
}
OK I have finally managed to get userDidAcceptCloudKitShareWith to be called.
You need to create the app delegate for your SwiftUI app using @NSApplicationDelegateAdaptor:
@main
struct Sharing_ServiceApp: App
{
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene
{
WindowGroup
{
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
I put that line in and my code instantly started receiving the share requests.