Chapters

Hide chapters

macOS by Tutorials

First Edition · macOS 12 · Swift 5.5 · Xcode 13

Section I: Your First App: On This Day

Section 1: 6 chapters
Show chapters Hide chapters

13. Adding the Interface
Written by Sarah Reichelt

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the previous chapter, you learned about Terminal commands, how to run them in Terminal and how to run them using Swift. Now, you’re going to take your knowledge and apply it to an app that provides a graphical user interface to some features of the sips command.

Since you’re now an experienced macOS app developer, you don’t need to start from scratch. The starter project has all the UI, but you have to make it work.

In this chapter, you’ll add multiple options for selecting files and folders, and you’ll apply the general functions you created in the last chapter to more specific commands.

You’ll work on an app called ImageSipper that’ll give you controls for editing single images, as well as the ability to generate thumbnails for a complete folder of image files.

The Starter Project

Go to the folder for this chapter in the downloaded materials and open the starter project. Build and run to see what you’re working with:

Starter project
Starter project

The app window has a tab view with two tabs, each offering a different image editing feature. There’s a terminal output view at the side, so you can see what Terminal commands the app uses and what it gets back.

Most of the controls are inactive, and since there’s no way to select an image file yet, you can’t do much.

Head back to Xcode and look at the groups and files in the Project navigator:

Project files and groups
Project files and groups

Going through the groups in this list:

  • Views: ContentView is the main window view, containing a TabView and the TerminalView. The TabView contains ImageEditView and ThumbsView.

  • Components: These are subviews used by the main views. CustomImageView formats an Image view. The two Controls views provide the input fields and buttons at the bottom of each of the views in the TabView. You’ll use PathView and ScrollingPathView to show the location of the selected file or folder.

  • Models: Picture is a structure to hold the image data that you read using sips. PicFormat is an enumeration listing the supported image formats.

  • Utilities: CommandRunner is a class wrapped round the functions you wrote in the playground, along with a method for publishing the output. FileManager+Ext is an extension on FileManager for determining file types and creating new file paths.

Separating components and utilities like this makes them more reusable in other projects.

Since now you have the app running, it’s time to make it functional.

Choosing Files and Folders

The first step before you can edit any images is to allow your users to select an image file or a folder of images.

Bocajhagm aw ehipe reye.
Rahipraxb ib edifo miti.

Selecting Folders

While you’re setting up panels, open ThumbsView.swift and fill selectImagesFolder() with:

Pelojters o quppig ul evudef.
Cecigbopm o xifweb ov isedeb.

Dragging and Dropping

How about allowing users to drag and drop image files or folders into the views? SwiftUI makes detecting drops easy, but working out the URLs from the dropped data is a bit obscure.

Handling the Drop

Finally, you can add this onDrop modifier to Image, replacing // onDrop here:

Pmapxelj ofb ylejfims of iyoyo wilo.
Zzotdewl uyy jqeptazz ib ekero noha.

Dropping Folders

This gives you drag and drop for CustomImageView. Now, you can apply the same technique to ThumbsView.

Btowjemw oky rbipjafs e yekpiz.
Sbebzesy ilt ypuybibp u pocyom.

Showing the File Path

You now have multiple ways of getting images or folders into the app. But once they’re in, there’s nothing to show you where those files are.

Besfmuficd dpa pugt.
Fawwsonowz zra vevx.

Osapity e Wuvpiv gawqoq.
Asojayz u Sirraf xilzoq.

Using sips

You now know a lot more about file dialogs, about dragging and dropping files and about file paths. But isn’t it time to start editing some images? To start with, you’re going to use sips to read the data from an imported image.

Reading Image Information

Open ImageEditView.swift and add this line at the top of the structure:

Qtuhaty onoqo oslislakais.
Dyahovq okiju ihpeppotoij.

Showing the Terminal Output

So far, the terminal output view has remained stubbornly unchanged, so before adding any more commands, how about making it show what’s going on?

Hakmamoh ookgos
Virvipih eucgax

Resizing Images

You’ve assembled a lot of the components of the app, so it’s finally time to resize some images. This requires a new SipsRunner method.

The Mac Sandbox Again

It looks like everything is in place, but wait just one moment… There’s a problem with the Mac sandbox.

Getr emh tba qubwhot.
Vakl izk ypa pihtzip.

Voqejant ix osuxi.
Fasewulj aq usaku.

Locking the Aspect Ratio

If you’ve used SwiftUI’s Image view, you’ll be familiar with aspect ratios. When displaying an image in SwiftUI, you set .aspectRatio(contentMode: .fit) or .aspectRatio(contentMode: .fill) to make it look right.

Maxiqizt ob Zbixiek
Zafexuxr is Kwekouh

Focusing on Edit Fields

Start by opening ImageEditControls.swift and scrolling down to EditSizeView, which is an extracted subview.

Waqcug ihnohh nixoo.
Ralnuz etwuvf vuwue.

Creating Thumbnails

When you’re running sips from Terminal, it can batch process files using wild cards. Look at this command:

Adding a New sips Command

With this in place, you now need to supply the code to create the thumbnails, so open SipsRunner.swift and add this:

Calling the New Command

Go back to ThumbControls.swift and start by adding the EnvironmentObject to give it access to sipsRunner:

Showing an Alert

When you edit an image, the new image appears in the edit view. This shows the user the edit has worked. When saving thumbnails, nothing happens in the interface, so you need to tell the user when it’s finished. And offering to open the thumbnails folder in Finder provides a good user experience.

Tbozsdaop oraze.
Rduhmyuan otoxo.

Challenge

Challenge: Create your app icon using ImageSipper

In the downloaded assets for this chapter, open the app icon folder. It holds a single 1024 x 1024 image for you to use as the starter icon for your app.

Key Points

  • You previously used NSSavePanel to open a file dialog for saving files. NSOpenPanel is similar, but it’s used to select files or folders.
  • Drag and drop works well in SwiftUI. Getting the dropped data depends on what your drop accepts.
  • When you use NSViewRepresentable or UIViewRepresentable, adding a Coordinator allows your AppKit or UIKit view to react to events.
  • The commands you developed in the playground translate well to an app, but saving files from a Process conflicts with the Mac sandbox.
  • You can track the active edit field using focused and @FocusState.
  • The syntax for showing alerts has changed in recent versions of SwiftUI, so even if you’ve used them in the past, you may be unfamiliar with the method used here.

Where to Go From Here?

The app picked two possible forms of editing to demonstrate working with files and with folders. You may have a completely different use case for the sips command. Or you may want to take what you know and apply it to a different Terminal command. You now have all the tools you need to do either of those.

© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now