I have a JSON file, which I want to share using the ShareLink framework. To do so, I created a Transferable extension for the class containing the data:
extension DataWrapper: Transferable {
static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .foodDataType)
DataRepresentation(importedContentType: .foodDataType) { data in
let wrappedData = try JSONDecoder().decode(DataWrapper.self, from: data)
return wrappedData
}
DataRepresentation(exportedContentType: .foodDataType) { wrappedData in
let data = try JSONEncoder().encode(wrappedData)
return data
}
FileRepresentation(contentType: .foodDataType) { wrappedData in
let docsURL = URL.temporaryDirectory.appendingPathComponent("\(UUID().uuidString)", conformingTo: .foodDataType)
let data = try JSONEncoder().encode(wrappedData)
try data.write(to: docsURL)
return SentTransferredFile(docsURL)
} importing: { received in
let data = try Data(contentsOf: received.file)
let wrappedData = try JSONDecoder().decode(DataWrapper.self, from: data)
return wrappedData
}
}
}
Furthermore, I defined a JSON based UTType:
extension UTType {
static var foodDataType: UTType = .init(exportedAs: "info.rueth.EasyFPU.DataWrapper", conformingTo: .json)
}
... and added it to the Document Types and the Export Type Identifiers sections in my plist file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ".0.dtd">
<plist version="1.0">
<array>
<dict>
<key>CFBundleTypeName</key>
<string>EasyFPU FoodData File</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>info.rueth.EasyFPU.DataWrapper</string>
</array>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>EasyFPU Food Data</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>info.rueth.EasyFPU.DataWrapper</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>fooddata</string>
</array>
<key>public.mime-type</key>
<array>
<string>applications/easyfpu</string>
</array>
</dict>
</dict>
</array>
</plist>
Finally, I'm calling the ShareLink in a swipeAction of a View:
.swipeActions(edge: .leading, allowsFullSwipe: false) {
// Sharing the food item
ShareLink(item: DataWrapper(dataModelVersion: .version2, foodItemVMs: [foodItemVM], composedFoodItemVMs: []), preview: .init("Share"))
.tint(.green)
.accessibilityIdentifierLeaf("ShareButton")
}
When running on a physical device, the Share sheet opens and I can select, e.g., Save to Files. After selecting the folder and confirming, I get the following runtime error in the Xcode console and no file is saved:
Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
Failed to load item provider <NSItemProvider: 0x3033eb870> {types = (
"info.rueth.EasyFPU.DataWrapper"
)}, falling back to original item provider
cancelled request - error: The process was aborted.
Especially the "Client not entitled" seems strange to me.
What am I missing?