使用 FileWrapper 创建自定义文档类型

app*_*sch 5 macos swiftui

我想创建一个 SwiftUI macOS 应用程序来创建自己的数据类型。它应该创建扩展名为 的文件.frogmd,该文件应该是包含以下内容的包

  • 代表文档的 json 文件
  • images包含图像的文件夹

现在,我可以将我的内容保存到磁盘中包含上述结构的文件夹中,但它不会创建具有我所需扩展名的文件,代表包含内容的包。

Exported Type Identifiers我有根据的猜测是我在我的部分中做错了一些事情Info.plist,所以这是我的 plist 的一部分:

<key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <array>
                <string>public.data</string>
            </array>
            <key>UTTypeDescription</key>
            <string>Frog's MD Document</string>
            <key>UTTypeIcons</key>
            <dict/>
            <key>UTTypeIdentifier</key>
            <string>ch.appfros.frogmd</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <array>
                    <string>frogmd</string>
                </array>
            </dict>
        </dict>
    </array>
Run Code Online (Sandbox Code Playgroud)

如果它有帮助,这里是到目前为止应用程序的代码:

@main
struct poc_Markdown2App: App {
    var body: some Scene {
        DocumentGroup(newDocument: FrogMdDocumentWrapper()) { file in
            ContentView(document: file.$document.document)
        }
    }
}

struct FrogMdDocument: Codable {
    var id: UUID
    var title: String
    var textContent: String
    var imageUrls: [URL]
    
    init(id: UUID = .init(), title: String = "New Document", textContent: String = .init(), imageUrls: [URL] = .init()) {
        self.id = id
        self.title = title
        self.textContent = textContent
        self.imageUrls = imageUrls
    }
}

struct FrogMdDocumentWrapper: FileDocument {
    var document: FrogMdDocument
    
    static var readableContentTypes = [UTType.data]
    
    init(document: FrogMdDocument = FrogMdDocument()) {
        self.document = document
    }
    
    init(configuration: ReadConfiguration) throws {
        self.init()
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        do {
            let data = try getDocumentData()
            let jsonFileWrapper = FileWrapper(regularFileWithContents: data)
            let filename = "document.json"
            jsonFileWrapper.filename = filename
            
            //TODO: store images to this imagesFileWrapper
            let imagesFileWrapper = FileWrapper(directoryWithFileWrappers: [String : FileWrapper]())
            
            let fileWrapper = FileWrapper(directoryWithFileWrappers: [
                filename: jsonFileWrapper,
                "images": imagesFileWrapper
            ])
            
            return fileWrapper
        } catch {
            throw error
        }
    }

    private func getDocumentData() throws -> Data {
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(document)
            return data
        } catch {
            throw error
        }
    }
    
}
Run Code Online (Sandbox Code Playgroud)

app*_*sch 2

我找到了它(并将发布在这里以供将来参考:-)):

我的文档类型条目中缺少 plist 条目。在下Additional document type properties,确保LSTypeIsPackage设置为YES

文档类型设置,包括 LSTypeIsPackage

由于我无法Info直接在界面中添加提到的密钥,因此我将其添加到其Info.plist本身中,从而导致了上述设置;请参阅下面的相应Info.plist部分:

<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>LSTypeIsPackage</key>
            <true/>
            <key>CFBundleTypeIconSystemGenerated</key>
            <integer>0</integer>
            <key>CFBundleTypeName</key>
            <string>Frog Markdown</string>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>LSHandlerRank</key>
            <string>Default</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>ch.appfros.frogmd</string>
            </array>
            <key>NSUbiquitousDocumentUserActivityType</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER).frogmd</string>
        </dict>
    </array>
Run Code Online (Sandbox Code Playgroud)