Author: Mark Szymczyk

Running a Command-Line Program from a Mac App

Apple provides the Process class that lets you run Terminal commands and command-line programs inside a Mac app. If you were creating a git GUI client, such as SourceTree or Tower, you would use the Process class to run git commands from your app.

To run a command-line program from your Mac app, you must do the following:

  • Create a Process instance
  • Configure the process
  • Run the process

Create the Process

Creating a process is the easiest step. Call the Process class’s initializer.

Configure the Process

What you must configure depends on the command or program you want to run. You must set the executable URL, the location of the command or program you want to run. Some other things you may need to configure include the following:

  • Arguments to pass to the process
  • The current directory
  • Environment variables
  • Standard error
  • Standard input
  • Standard output

In my help book building app Phel, I run the hiutil command to index the help book. I configure the following items to run the command:

  • The executable URL, which is usr/bin/hiutil.
  • The directory to run the command, which is the Resources folder inside the help book bundle.
  • The arguments, which are -I, -lsm, Caf, the name of the index file, -vv, and ..

I must run the hiutil command a second time to generate a spotlight index file. I replace the lsm argument with corespotlight and supply the name of the spotlight index file.

Run the Process

Call the run function inside a do-catch block to run a process.

The following code runs the hiutil to generate an index file for an Apple help book:

Creating a UIKit Xcode Project

A common problem people learning UIKit have when following a tutorial is that what they see in Xcode does not match what the tutorial shows. The tutorial shows a view controller file, but they see a content view file.

The most common cause of this problem is creating an Xcode project that uses SwiftUI instead of UIKit. When you create a new project in Xcode, the default is to create a SwiftUI project.

To create an Xcode project that uses UIKit, you must create an iOS app project and tell Xcode to use a storyboard for the user interface. UIKit uses storyboards, and SwiftUI doesn’t.

Create an iOS App Project

In Xcode choose File > New > Project to create a new project. The New Project Assistant opens.

XcodeCreateiOSAppProject

Click on iOS at the top of the assistant to see the iOS app project templates. Choose either App or Document App. If you’re not sure, choose App. Click the Next button.

Choose Storyboard for the User Interface

When you click the Next button, the New Project Assistant takes you to the next step in creating the project.

XcodeChooseStoryboard

Choose Storyboard from the Interface menu to create a UIKIt project.

If you don’t see an Interface menu (or a menu with a similar name), click the Previous button and make sure you choose an iOS app project. Xcode’s multi-platform project templates create SwiftUI projects.

How to Learn SwiftUI to Develop Mac Apps

A common complaint I hear online from Mac developers is that all the SwiftUI learning material focuses on iOS development, and there’s nothing on Mac development. This article provides advice on learning SwiftUI for Mac development.

A lot of iOS SwiftUI learning material also works on Mac

Mac developers have to accept the fact that iOS development is much more popular than Mac development. People creating SwiftUI tutorials, videos, and courses are going to focus on iOS developers.

The good news with SwiftUI is that most of the iOS learning material also applies to Mac development. Apple created SwiftUI so developers can create user interfaces for all of their platforms with one framework. If you find a SwiftUI tutorial or course that you like, such as Hacking with Swift’s 100 Days of SwiftUI course, you can use the tutorial or course to make Mac apps. You may have to make some changes to get things to work on Mac.

Lists are one area of SwiftUI where there are large differences between iOS and Mac. If you read an article about lists and try to use the code in a Mac app, you’ll run into problems. The following articles cover those differences:

You can use AppKit views in SwiftUI Mac apps

SwiftUI is not a finished framework, especially on Mac. Some views that Mac apps need do not have native SwiftUI equivalents, and some of SwiftUI’s views do not work well on Mac. A workaround for SwiftUI’s Mac limitations is to use AppKit views in your app.

To use an AppKit view in a SwiftUI Mac app, create a struct that conforms to the NSViewRepresentable protocol. My Using a UIKit or AppKIt View in SwiftUI article provides more details on using AppKit views in a SwiftUI app.

SwiftUI resources for Mac development

To address complaints about a lack of learning material on Mac development, I compiled a list of Mac development resources. Many of those resources cover using SwiftUI for Mac development.

This site has a number of SwiftUI articles, most of which apply to Mac development. You can see a complete list of articles on the Articles page.

Deleting an Xcode Project’s Git Repository

Deleting a git repository for an Xcode project is relatively easy: move the folder that holds the git repository out of the project folder. But the Finder makes locating the repository folder difficult. In this article you will learn how to find the repository folder so you can delete it.

Where is the git repository?

The git repository is in a .git folder inside the project folder. If you go to the project folder in the Finder, you won’t see the .git folder. Why can’t you see it?

You can’t see the .git folder in the Finder because the Finder hides files and folders that start with a dot. To see the .git folder in the Finder, press Cmd-Shift-Dot. Pressing Cmd-Shift-Dot shows hidden files and folders.

Press Cmd-Shift-Dot a second time to stop showing the hidden files and folders in the Finder.

Deleting the repository

Move the .git folder out of the project folder, and git will stop tracking changes in your project. You will normally move the .git folder to the Trash.

If you want to create a new git repository for your project after removing the previous one, choose Integrate > New Git Repository in Xcode. Older versions of Xcode have a Source Control menu instead of an Integrate menu.

Want to learn more about git?

Check out my version control book. It shows you how to do the most common git tasks without leaving Xcode. Some of the material covered in the book includes cloning projects from GitHub, branching, and going back to earlier versions of your project.

Where is the Info.plist file?

Recent versions of Xcode do not add an Info.plist file to new iOS app projects. How do you add settings to your app that you would normally place in Info.plist?

Xcode’s project editor has an Info section for the app target, where you can add the settings. Take the following steps to access the Info section:

  1. Select your project from the project navigator on the left side of the project window to open the project editor.
  2. Select your app from the target list on the left side of the project editor.
  3. Click the Info button at the top of the project editor.

InfoPlistTargetSettings

At the top of the Info section is a Custom Target Properties list. To add an item to the Info section, move the mouse arrow over one of the keys in the list. Tiny buttons to add and remove an item will appear on the right side of the key where the mouse arrow is. Click the Add (+) button to add a setting to the Info section.

Dealing with the init(destination:tag:selection ) was deprecated in iOS 16.0 message

People starting out with SwiftUI development may get a message like the following from Xcode when building their project:

`init(destination:isActive:label:)’ was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a NavigationStack or NavigationSplitView

‘init(destination:tag:selection????️ )’ was deprecated in iOS 16.0: use NavigationLink(value????️ ), or navigationDestination(isPresented:destination:), inside a NavigationStack or NavigationSplitView

Why are you getting this message?

You are getting this message because you are using NavigationView in your user interface.

The original version of SwiftUI used navigation views to navigate from one screen to another in an app and for master-detail interfaces with split views on iPad. In iOS 16 Apple replaced NavigationView with NavigationStack and NavigationSplitView for navigation.

The message is telling you to replace NavigationView in your app with either NavigationStack or NavigationSplitView.

NavigationStack and NavigationSplitView don’t run on earlier iOS versions. If you want your SwiftUI app to run on iOS 15, you must use NavigationView.

Is the message a problem?

Not currently. The message is a compiler warning, not an error. Your project will build and run, assuming there are no errors in the rest of your code.

Eventually Apple will stop supporting iOS 15. A future version of Xcode will drop support for building an app that runs on iOS 15. For reference Xcode 14 does not support iOS versions older than iOS 11. When Apple releases a version of Xcode that does not support building an app that runs on iOS 15, the message will be a problem.

How do you remove the message?

Use either NavigationStack or NavigationSplitView instead of NavigationView in your app. Apple provides the following guide to migrate code from NavigationView:

Migrating to new navigation types

If you are following a tutorial that uses NavigationView, find a more recent tutorial that uses the newer navigation APIs.

Dealing with Core Data Duplicate Class Errors

Many people learning Core Data take the following steps when creating their first Core Data app:

  1. Create a new Xcode project that uses Core Data.
  2. Create Code Data entities and relationships in Xcode’s data model editor.
  3. Create subclasses for their entities by choosing Editor > Create NSManagedObject Subclass in Xcode.

They build the project and get the following build error:

Invalid redeclaration of Entity

Where Entity is the name of a Core Data entity.

What Causes the Error?

When you create a new Xcode project that uses Core Data, Xcode is set to automatically create NSManagedObject subclasses for your Core Data entities. Xcode creates the subclasses when you build the project.

The source code files Xcode creates are in the project’s derived data location. You can’t see the files in the left side of the project window like the other source code files in your project. You’re not meant to access and edit the source code files Xcode creates for your Core Data entities. The point of Xcode creating the files is to automatically update the files when you make changes to the data model.

If you create NSManagedObject subclasses from Xcode’s Editor menu, you wind up with two files for each subclass: the one Xcode automatically generates and the one you create.

When you have two classes with the same name, Xcode gives you the “Invalid redeclaration” error, and your project won’t build.

How do You Fix the Error?

There are two ways to fix the error. The first way is to remove the class files you added and let Xcode generate the classes for you.

The second way is to tell Xcode not to generate class files for your Core Data entities by choosing Manual/None from the Codegen menu in Xcode’s data model inspector. Choose View > Inspectors > Data Model in Xcode to access the data model inspector. Read the following article for screenshots and more details on Core Data class generation options:

Core Data Code Generation

Highlighting the Selected Item Button in a SwiftUI List

If you use a button for list items in SwiftUI, the list item does not highlight when you select it. This is expected behavior for a bordered button. But some apps need to use buttons that look like text to perform actions when selecting the list item. If you have a button that looks like text, you want to highlight the selection so people can easily see the selected item.

How do you highlight the selected item? You must do two things to highlight the selected item. First, you must set the background color for the list row. Second, you must set the foreground color for the list item.

Setting the Background Color

Add a .listRowBackground modifier to the button to set the background color. Use the accent color for the selected item to highlight it and the clear color for the other items to match the standard selection highlighting.

Setting the Foreground Color

When you select an item from a SwiftUI list in an app running in light mode, the text color for the item changes from a dark color to a light color. You must set the color based on the current color scheme or else the text of the selected item will be tough to read.

Start by adding an @Environment property to your SwiftUI view that stores the current color scheme: light or dark.

Next, create computed properties for the item color based on whether or not it’s selected. Use white for the selected item. For unselected items make the text white in dark mode and black in light mode.

Finally add a .foregroundColor modifier to the button. Use the selected item color for the selected item and the unselected item color for the other items.

Creating a SwiftUI Toolbar Button with an Image and a Label

Many toolbar buttons in Mac and iOS apps include an image and a label. The Mac apps Finder, Mail, and Pages are examples of apps whose toolbar buttons have an image and a label.

If you try to create a button in a SwiftUI toolbar with an image and a label, you will notice the label does not appear. You must do the following to create a toolbar button with an image and a label:

  • Create a label style for the button.
  • Add a .labelStyle modifier to your button label and use the label style you created.

Creating a Label Style

To create a label style, you must create a struct that conforms to the LabelStyle protocol. Add a makeBody function to the struct that returns a SwiftUI view.

A label style for a toolbar button should create a VStack with the image first and the text label second. Supply a font to use for the image and the label in the VStack.

Add the .labelStyle Modifier

After creating the label style for your toolbar button, add a .labelStyle modifier to the button’s label and supply the name of the struct you created for the label style. The following code shows an example of a SwiftUI button that uses a custom label style:

Credits

The answer from Eduardo to the following Stack Overflow question helped me with the code for this article:

Add Button with Image and Text in ToolbarItem SwiftUI

Adding a Help Menu to a SwiftUI App

When you create and run a SwiftUI Mac app project, the Help menu has a menu item named AppName Help, where AppName is the name of your app. If you choose that menu item, an alert opens saying help isn’t available for the app.

Help Books

The included menu item works only if your app has a Help Book bundled in the app. Many of Apple’s apps have Help Books. Choose Help > Xcode Help in Xcode to see an example of a Help Book.

Creating Help Books is painful. Apple’s Help Book Programming Guide was last updated in 2013, and there aren’t many articles online on creating Help Books.

Take Users to Your Site

For most apps it’s easier to add a page to your app’s website with your app’s help and add a menu item to go that page. You can even include a link on the page for people to download a user guide for your app. Creating a menu item that takes someone to your site involves the following steps:

  • Create a view for the menu item.
  • Create a SwiftUI link for the menu item.
  • Add the menu item to the menu bar.

Creating the Link and Menu Item

A SwiftUI link takes two arguments. The first argument is the link name, which is the menu item text for menus. The second argument is the link destination. The following code shows an example of a menu item with a link:

Adding the Menu Item to the Menu Bar

Add a .commands modifier to the window group or document group in the App struct for your app. Add a command group for the menu, replacing the default Help menu item with your Help menu items.

Do you want to add a help book to your app?

Earlier in this article I mentioned that creating a help book for a Mac app is painful. To help developers deal with this pain, I’m developing Phel, an app that creates help books from Markdown files.

Write your help pages in Markdown, import the help pages and images, hit the Publish button, and get an indexed help book you can add to your Xcode project.

You can download and try Phel at the Phel page.