GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

SOLVED: Type '()' cannot conform to 'View' when trying to set a model parameter in a DocumentGroup

Forums > SwiftUI

My post from 2 days ago hasn't generated any conversation/answers so I decided to go back and take another look at using DocumentGroup to open and save my custom document type even though I don't think it will give me the control I need - i.e. my custom document type contains a stringified path URL to a media (audio) file that I also need to open.

Imagine an audio player that lets the user select a portion of the audio and loop it a specified number of times and a specified rate (slow down or speed up). I intend to save these parameters in a JSON file along with the URL to the associated media file. My post the other day describes the problem I have with using custom file Open and Save buttons on the File menu when using a regular WindowGroup and .fileImporter and .fileExporter on buttons in the ContentView hierarchy - but I can't figure out how to access the document from the file menu (either I crash or have compiler errors). So until I have have some feedback on that (or I find enlightenment in my searches) I am once again attempting to use a DocumentGroup.

Now I'm running into a different problem but if I can solve this problem, I might be able to use DocumentGroup to accomplish what I need. Here is a stripped down SwiftUI DocumentGroup app that shows the issue:

//
//  TestDocumentGroupApp.swift
import SwiftUI

@main
struct LoopTimeApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: TestDocumentGroupDocument()) { file in
        // The following line won't compile - it fail with a Type '()' cannot conform to 'View' error.
        // I undertand what this error means (I think) but believed that the return 
        // of the constructed ContentView satisfied the requirement
            file.document.mediaURL = file.fileURL?.lastPathComponent ?? "new file"  
            ContentView(document: file.$document)
        }
    }
}
//
//  TestDocumentGroupDocument.swift
import SwiftUI
import UniformTypeIdentifiers

extension UTType {
    static var exampleText: UTType {
        UTType(importedAs: "com.example.plain-text")
    }
}

struct TestDocumentGroupDocument: FileDocument {
    var text: String
    var mediaURL: String

    init(text: String = "Hello, world!") {
        self.text = text
        mediaURL = ""
    }

    static var readableContentTypes: [UTType] { [.exampleText] }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let string = String(data: data, encoding: .utf8)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        text = string
        mediaURL = ""
    }

    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        let data = text.data(using: .utf8)!
        return .init(regularFileWithContents: data)
    }
}
//
//  ContentView.swift
import SwiftUI

struct ContentView: View {
    @Binding var document: TestDocumentGroupDocument

    var body: some View {
        TextEditor(text: $document.text)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(document: .constant(TestDocumentGroupDocument()))
    }
}

2      

I found a post here referring to Day 26 from the course that discusses this in the context of Views. An explicit use of return to return the view but my issue is within a ViewBuilder so adding return generates this error:

DocumentGroup(newDocument: TestDocumentGroupDocument()) { file in
            file.document.mediaURL = file.fileURL?.lastPathComponent ?? "new file"
            return ContentView(document: file.$document)
        }

Cannot use explicit 'return' statement in the body of result builder 'ViewBuilder'

2      

2      

Thanks @NigelGee - that is actually one of the source I used when I started this. Unfortunately, it doesn't shed any light on this issue or what I would like to do. There is very little info / design patterns on how to do more complex file management in SwiftUI it seems. This stuff was all easy using the old NSOpenPanel stuff. But I really want this to be as native SwiftUI as possible. I'm very close with my other implementation - except that I can't figure out how to implement File menu Open and Save menu buttons. If I ignore the File menu (remove these option) I would be fine but that's not a friendly Mac app!

2      

A very simple conceptual exercise that would give me the tools and understanding I need is:

Imagine you have a text file that has a simple string in it that you want to display at the top of the ContenView and that you would like to allow the user to edit this string and have it persist back to the file.

I think the understanding needed to implment this with DocumentGroup would put me on the right track. Perhaps the answer is "it can't be done with the current version of SwiftUI"!

thanks, Michael

2      

Can you just add another property to your ContentView and then use that to set the property on the document in onAppear?

@main
struct LoopTimeApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: TestDocumentGroupDocument()) { file in
            ContentView(document: file.$document, fileURL: file.fileURL?.lastPathComponent ?? "new file")
        }
    }
}

struct ContentView: View {
    @Binding var document: TestDocumentGroupDocument
    let fileURL: String

    var body: some View {
        TextEditor(text: $document.text)
            .onAppear {
                document.mediaURL = fileURL
            }
    }
}

2      

@roosterboy Yes! that works for this simple case so that might give me the building blocks I need. Thank you.

So, is it a general design principle that any calculations, parameter settings, etc that a View needs can be performed in the onAppear action?

thanks, Michael

2      

Hacking with Swift is sponsored by Alex.

SPONSORED Alex is the iOS & Mac developer’s ultimate AI assistant. It integrates with Xcode, offering a best-in-class Swift coding agent. Generate modern SwiftUI from images. Fast-apply suggestions from Claude 3.5 Sonnet, o3-mini, and DeepSeek R1. Autofix Swift 6 errors and warnings. And so much more. Start your 7-day free trial today!

Try for free!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.