我有一个 iOS/iPadOS 应用程序。当我在 Mac 上将应用程序作为“为 iPad 设计”应用程序运行时,共享表上的“保存”按钮会使应用程序崩溃。
我想与 ImageRenderer 共享视图,但这里有一个更简单的示例,我尝试将 SF 符号作为图像共享。
ShareLink(item: Image(systemName: "swift"), preview: SharePreview(Text("PNG"), image: Image(systemName: "swift")))
共享按钮有效。它打开共享表。 “添加到照片”有效。 “复制”有效。按“复制”后,我可以将图像文件粘贴到 Finder 中。但是当我按下“保存”按钮时,我的应用程序崩溃并出现错误:
Thread 1: "-[NSItemProvider pathExtension]: unrecognized selector sent to instance 0x600001c1e290"
如何修复这个错误?如何使保存图像起作用?也许我需要 plist 中的额外权限?我已经有“隐私 - 照片库添加使用说明”并且 iOS 和 iPadOS 上的所有内容都可以正常工作。
在 Mac 上将 iOS/iPadOS 应用程序作为“Designed for iPad”应用程序运行时,使用
ShareLink
共享图像会导致在按下共享表上的“保存”按钮时应用程序崩溃。 “添加到照片”和“复制”等其他操作可以正常工作。发生崩溃并出现以下错误:
Thread 1: "-[NSItemProvider pathExtension]: unrecognized selector sent to instance 0x600001c1e290"
示例代码:
ShareLink(item: Image(systemName: "swift"), preview: SharePreview(Text("PNG"), image: Image(systemName: "swift")))
此问题可能是由于 macOS 处理文件操作的方式与 iOS/iPadOS 不同所致。在 macOS 上运行时,所使用的
NSItemProvider
似乎没有预期的属性或方法。
以下是解决此问题的几种方法:
在分享之前将 SwiftUI
Image
转换为 UIImage
:
import SwiftUI
struct ContentView: View {
var body: some View {
if let uiImage = UIImage(systemName: "swift") {
ShareLink(item: uiImage, preview: SharePreview("Swift Symbol", image: Image(uiImage: uiImage)))
}
}
}
创建一个可处理 iOS 和 macOS 的自定义
NSItemProvider
:
import SwiftUI
import UniformTypeIdentifiers
struct ContentView: View {
var body: some View {
ShareLink(item: CustomItemProvider(image: UIImage(systemName: "swift")!),
preview: SharePreview("Swift Symbol", image: Image(systemName: "swift")))
}
}
class CustomItemProvider: NSItemProvider {
init(image: UIImage) {
super.init()
self.registerDataRepresentation(forTypeIdentifier: UTType.png.identifier, visibility: .all) { completion in
guard let data = image.pngData() else {
completion(nil, NSError(domain: "ImageError", code: 0, userInfo: nil))
return nil
}
completion(data, nil)
return nil
}
}
}
将图像保存到临时文件并共享:
import SwiftUI
struct ContentView: View {
var body: some View {
if let url = saveImageToTemporaryFile() {
ShareLink(item: url, preview: SharePreview("Swift Symbol", image: Image(systemName: "swift")))
}
}
func saveImageToTemporaryFile() -> URL? {
guard let image = UIImage(systemName: "swift"),
let data = image.pngData() else { return nil }
let temporaryDirectoryURL = FileManager.default.temporaryDirectory
let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent("swiftSymbol.png")
do {
try data.write(to: temporaryFileURL)
return temporaryFileURL
} catch {
print("Error saving file: \(error)")
return nil
}
}
}
确保您的应用程序具有在 macOS 上访问文件所需的权限:
检测应用程序是否在 macOS 上运行并提供不同的共享机制:
import SwiftUI
struct ContentView: View {
var body: some View {
if #available(macOS 11.0, *) {
// macOS-specific sharing
Button("Share") {
let picker = NSSavePanel()
picker.allowedContentTypes = [.png]
picker.canCreateDirectories = true
picker.isExtensionHidden = false
picker.title = "Save Image"
picker.message = "Choose a location to save the image"
picker.nameFieldStringValue = "swiftSymbol.png"
picker.begin { result in
if result == .OK {
if let url = picker.url,
let image = NSImage(systemSymbolName: "swift", accessibilityDescription: nil),
let tiffData = image.tiffRepresentation,
let bitmapImage = NSBitmapImageRep(data: tiffData),
let pngData = bitmapImage.representation(using: .png, properties: [:]) {
do {
try pngData.write(to: url)
} catch {
print("Error saving file: \(error)")
}
}
}
}
}
} else {
// iOS/iPadOS sharing
ShareLink(item: Image(systemName: "swift"), preview: SharePreview("Swift Symbol", image: Image(systemName: "swift")))
}
}
}
该问题源于 macOS 和 iOS/iPadOS 处理文件操作和共享的方式不同。通过使用上述方法之一,您应该能够解决崩溃问题并在两个平台上成功共享图像。
请记住在 iOS/iPadOS 设备和 Mac 上进行彻底测试,以确保该解决方案适用于所有平台。