Group Group Group Group Group Group Group Group Group

Confused about view controller best practices

Before I get too far into my project, I want to clear up what’s the best way to handle things for a sustainable app.

While working on the first part of my (MacOS) project, I noticed that my view controller file was getting hugely unwieldy because I had so many interface elements I needed to work into it. It’s a single-view app (for now) but there are at least four, possibly five “sections” of radio buttons and check-box options and all the methods and arrays and switch statements and whatnot behind them.

And that’s before I get to work on the windows that will open up when certain buttons are clicked.

I was using // MARK: comments to make navigating it all a little easier, but it was still a lot of code for a single file.

Then somewhere in my research into how to do something else, I stumbled upon a couple sites making arguments for using multiple view controllers to keep your code neater. But when I dug deeper, it seems like most of the tutorials are talking about multiple view controllers for multiple views, not for a single-view app that just happens to have a lot going on in that single view.

When I tried to experiment and follow some tutorials on how to add additional view controllers, I couldn’t link my interface elements to them as @IBOutlets or @IBAction methods. Which I take to mean they’re not actually meant to manage elements that are located on a single interface view.

So now I’m not sure what the best practice for handling this sort of situation is, and I really would like to know before I get much further into my project and it becomes impossible to fix a bad situation.

Firstly, I’d look at the options, particularly the radio buttons. Are they linked to the same method and distinguished by tags? Since they’re a logical group, you can use them to set an enum value… and your enum can have a computed property where you put the detailed logic. That way, you can keep the viewController much cleaner and keep your code branches in a single place that is not a massive viewController.

Secondly, you can use embed views if you want to move a whole section of your logic into a separate viewController. That way, you don’t have to manage adding of views and viewControllers in code - you lay them out in the storyboard as usual.

Thanks for replying.

Right now I have five distinct “areas” that should logically be grouped together in an app that deals with converting audiobook formats, and editing metadata/chapters using ffmpeg, which is located in the main resource bundle.

Area 1:
I have input and output NSTextFields that display the path to the input and output file chosen by the user, using corresponding Browse… NSButtons.

I also have an image well off there to the left that will display the cover art embedded in the input file chosen and it seems logical to me to have this encoded in the same place as the input/output text fields. That image well will hopefully also be encoded to allow the user to drag a different image to be the audiobook cover art instead, but that’s a ways off.

Area 2:
Ideally this SHOULD hold the all logic for the different conversion options managed by the NSPopupButton, which would be passed into the ffmpeg process as arguments, but right now all it does is provide the extension for the output file because I needed to move the argument logic into the process, as it wasn’t being read properly otherwise.

Area 3:
The “Edit Metadata” button should open a new window with metadata-related options. That will, in turn, be fed into the ffmpeg process as arguments.

Area 4:
Same as Area 3, only dealing with chaptering options.

Area 5:
Everything below that midline.
The textfield (which is in a scrollview) should display the FFMpeg output. The checkbox should add an argument for FFmpeg to return more verbose output. The Start Conversion button should launch the FFmpeg process.

I haven’t had the need to familiarize myself with enums yet and I’m not sure they’re necessary here? I have played around a little with embed views, mostly using containers in the interface builder, but I’ll have to experiment more with that.

The good news is that this does not look like an overly complex interface for a desktop app. I’d simplify it further by letting users open an input file, and then, when they’re done, save it. (Elsewhere, in preferences, you can set default directories for these). I think your main challenge is to find visual groupings, correct labels, and a better way to guide users through your workflow.

If this was me, I’d experiment with making the chapters and metadata visible (maybe in an inspector in a split view) so that users can see why they might want to adjust it. I’m assuming that your main operation is relatively costly and takes some time - can you provide a preview of what the different options mean?

Enums aren’t necessary, but they’re useful. How I would structure this is to have a ConversionOptions enum, linked to the popup button to let users choose, and a Converter class that does all of the work: the view controller collects the settings (output format, anything else), passes it to the Converter class, and gets an appropriate file back.

Thank you. That’s a good suggestion about the split view (though I admit, I’m terrified to touch the interface again because every time I do, autolayout decides to throw something else out of whack.)

The main operation can be fairly time-consuming, depending on whether the user wants to re-encode the file to a different format. But the metadata and chapters themselves take hardly any time at all, because that’s just a matter of rewriting the metadata without re-encoding.