Category: Tools

Genrerating Swift Code for REST APIs with CreateAPI

If you are starting to develop a Swift app that works with a REST API, you may be overwhelmed thinking about all the code you have to write. What if you forget a data structure? What if you forget to add a property to a data structure? Wouldn’t it be nice to have someone create the Swift code for you?

The command-line app CreateAPI makes this possible. Supply a JSON or YAML file that contains the REST API, and CreateAPI creates a Swift package with Swift code for the REST API. By using CreateAPI you can make faster progress on a Swift app that uses REST APIs.

Installing CreateAPI

The CreateAPI GitHub page has installation instructions. You can install it using Homebrew or Mint or by cloning the GitHub repository and installing it from source. Installing from source worked for me.

Generating a Swift Package with CreateAPI

Generating a Swift package with CreateAPI has the following steps:

  1. Download a JSON or YAML file that contains the REST API.
  2. Open the Terminal app.
  3. Navigate to the folder that contains the file.
  4. Run CreateAPI.

The most common way to run CreateAPI is to run the create-api generate command with the --output and --config-option options. The following example demonstrates running CreateAPI:

create-api generate "APIFile.json" 
    --output "./PackageName" 
    --config-option "module=PackageName"

The name of the JSON file must be in quotes. Replace APIFile.json with the name of the file containing the REST API. Replace PackageName with the name you want for your Swift package.

The CreateAPI GitHub page has a tutorial that contains more detailed instructions.

NOTE

CreateAPI is in its early stages of development. It may not work with every REST API. I was unable to generate a Swift package for GitHub’s REST API.

Add the Package to Your Xcode Project

After creating the Swift package you can add it to your project like any other Swift package. If you have never added a Swift package to a project in Xcode, take the following steps:

  1. Select the project file from the left side of the project window to open the project editor.
  2. Select the project from the left side of the project editor.
  3. Click the Package Dependencies button at the top of the project editor to show a list of Swift packages in the project.
  4. Click the Add button at the bottom of the package list.
  5. Click the Add Local button in the sheet to add your package.

Import the package module in your source code files, and you can start using the package in your app.

If you want to see an example of a Swift package that CreateAPI creates, I have a package for Jira’s REST API on GitHub.

Xcode Multiplatform App Targets

Starting in Xcode 14, when you create a multiplatform app project, Xcode creates a single app target with destinations for each platform you want to support: iPhone, iPad, Apple TV and Mac. This article provides an introduction to multiplatform app targets.

When to Use the Multiplatform App Target

Use the Multiplatform App Target if you want people to buy one version of your app on the App Store and run the app on all the platforms you support: iPhone, iPad, AppleTV, and/or Mac. Use separate targets if you plan to charge for each platform separately.

If you plan to sell a Mac version of your app outside the App Store, create a separate app target. Use the multiplatform app target to sell on the App Store and the Mac app target to sell outside the App Store.

Viewing, Adding, and Removing Platform Destinations

Select the target from the target list on the left side of the project editor and click the General button at the top of the project editor to see a list of the app’s platform destinations:

AppTargetSupportedDestinations

The supported destinations list has buttons to add and remove destinations. If you created a project in an older version of Xcode, you must add destinations to have a single app target that supports iPhone, iPad, AppleTV, and Mac. Older versions of Xcode have separate targets for each platform.

Mac Destination Choices

When adding the Mac destination to an app target, you have the following choices:

  • Mac
  • Mac Catalyst
  • Designed for iPad

Choosing Mac uses SwiftUI and/or AppKit for the Mac app. Mac is the best choice for a new app, especially one that uses SwiftUI.

Choosing Mac Catalyst uses UIKit for the Mac app. Mac Catalyst is the best choice if you want to make a Mac version of an existing iOS app.

Choosing Designed for iPad runs the iPad version of the app on Macs with Apple Silicon chips. Choose Designed for iPad if you want a Mac version of your iOS app and don’t want to do any work converting the app.

Choosing the Platform to Build and Run

Xcode can build and run for only platform at a time. How do you specify the platform to build and run?

There’s a jump bar in the project window toolbar.

ChoosePlatformToRun

Click the right part of the jump bar to choose the platform: Mac, a connected iOS device, or an iOS simulator.

Compiling Files for Specific Platforms

Previous versions of Xcode have separate targets for each platform. If you have separate targets with code that should be compiled for a specific platform, make the file a member of that target. But you can’t do that with the multiplatform app target because there’s only one target. What do you do if you have platform-specific source code files?

Tell Xcode what platforms a source code file should compile for. Click the Build Phases button at the top of the project editor and examine the Compile Sources build phase.

FilterDestinations

Xcode initially sets each source code file to build for each destination. Click on the Filter column for a source code file to open a popover.

PlatformFilterPopover

Deselect the Allow any platform checkbox and deselect the destinations you don’t want to use. Now that file compiles only for the platforms you specified.

Getting Started with the Get Networking Framework

The Get framework is a lightweight Swift framework for working with web APIs. Get is a nice framework, but the README file doesn’t provide much explanation on how to use the framework. This article shows how to start using the Get framework in your apps.

Basic Workflow

Using the Get framework involves the following basic steps:

  1. Create an API client instance
  2. Create a network request
  3. Send the request

Create an API Client Instance

Get provides an APIClient class for API clients. Create an instance, supplying the base URL to the network API you want to use. The following example creates an API client for the Jira REST API:

Create a Network Request

Get has a Request struct that represents a network request. Fill the Request struct to create a network request. The Request struct has the following fields:

  • The body, which you use to send data from your app to the API. POST and PUT methods require you to supply a body.
  • Headers for the request. The headers field is a Swift dictionary where each key and value are strings.
  • An ID for the request. You probably won’t need to set an ID.
  • The method, such as GET, POST, or PUT.
  • Query items. The query field is an array of Swift tuples, consisting of two strings.
  • The URL for the network call.

The Get framework defaults to using GET methods and leaving the other fields blank so the only fields you have to fill are the ones you need to make the network call.

To create a request for a GET method, start by creating a variable of type Request. Place the data type you want to return in angle brackets and supply the URL for the network call.

Replace T with the type you want to return from the network call. Replace urlPath with the URL string for the API call to make.

After creating the request, fill the fields your network call requires.

If you have a method that sends data to the server, such as a POST or PUT method, you must create the body data and supply it when creating the request. The body property is a let constant so you can’t set the body after creating the request.

The body must conform to the Encodable protocol.

Sending the Request

The API client has a send method to send the network request. Supply the request.

Usually a network call returns data. By attaching the value property when sending the request, you will get decoded data back in the type you specified when creating the request.

You’re going to use this code a lot when using Get. In one line of code you can send a network request and get data back in a form that your app can use.

Dealing with “Failed to prepare device for development” Error Message in Xcode

You update your iOS device to the latest version of iOS. Now you try to run your Xcode project on that device. An alert pops up in Xcode with the message Failed to prepare device for development.

Why Are You Getting This Message?

You are getting the Failed to prepare device for development message because the device is running a newer version of iOS than Xcode supports.

Each version of Xcode ships with a version of the iOS SDK. The Xcode Releases site has a list of each version of Xcode along with the iOS SDK. The version of the SDK is the latest version of iOS that version of Xcode supports. You won’t be able to run your Xcode project on a device running a newer version of iOS.

For example Xcode 13.2.1 ships with the iOS 15.2 SDK. If you are running Xcode 13.2.1, you won’t be able to run your project on a device running anything newer than iOS 15.2. If you have a device running iOS 15.4, you won’t be able to run the project on that device with Xcode 13.2.1.

How Do You Fix the Error?

The easiest solution is to install the latest version of Xcode. The latest version of Xcode has the latest version of the iOS SDK so you’ll be able to run and debug your project on a device running the latest version of iOS.

If your Mac is running an older version of macOS, you might not be able to update to the latest version of Xcode. Xcode 13.3 requires macOS 12. If your Mac is running macOS 11 and can’t run macOS 12, you won’t be able to update to Xcode 13.3. What do you do then?

There are two workarounds. The first is to download iOS support files for the newer iOS version and copy them to your Xcode app bundle.

The second workaround is to deselect the Debug executable checkbox in the Run step of the scheme. After the app launches, attach it to the debugger. The following article provides details and screenshots:

Debugging on iOS 15 with Xcode 12

Turn off Automatic Updates on Your Device

Keeping up with the latest version of iOS requires using the latest version of Xcode. Xcode takes a long time to install. If you don’t want to be constantly updating Xcode, turn off automatic updates on your iOS device.

Why Won’t My Xcode Project Build?

It’s frustrating to click the Run button in Xcode and find that your project won’t build and run. Xcode initially shows you a message like Command CompileSwiftSources failed with a nonzero exit code, which really doesn’t help much. How do you find where the error is so you can fix it and run your project?

Get a List of the Errors

The first step to figuring out why your project won’t build is to find the compiler errors in your project. Open Xcode’s issue navigator by pressing Cmd–5.

IssueNavigator

The issue navigator shows the compiler errors in your project. Select an error to show the line where the error is.

Seeing More Detailed Information about an Error

To see more detailed information about a compiler error, open the report navigator by pressing Cmd–9. Select a build from the report navigator to see the build steps and errors for that specific build.

ReportNavigatorHighlighted

Click the Log button (the small button with the horizontal lines) to see a detailed log of that particular build step.

Tips for Fixing Errors

You found the compiler errors in your project. How do you fix them?

I can’t tell you specifically how to fix the errors because I can’t see your code. But I have some general tips to help you fix the compiler errors in your Xcode projects.

Make Sure Argument Types Match

When calling functions, make sure the data types for the function arguments match. When the argument types don’t match, you get a compiler error message like the following:

Where X and Y data types.

If a function takes an integer as the first argument and you pass a string, you’re going to get the Can't convert value compiler error.

Check for Typos

If I make a typographical error in this article, you’ll still be able to read the article. But if you make one small typo in your code, the project won’t build.

Make sure you spell function names correctly when calling them. If you have a function called doSomething and you call it like the following:

You are going to get a compiler error because you made a typo when calling the function. There is no doSomethng function.

Make sure that you spell variable names correctly when accessing them. If you have a player variable in your app and misspell it,

You are going to get a compiler error because there is no playr variable.

Make sure each left brace, bracket, parenthesis, and quotation mark has a matching right one. An extra left or right brace can lead to compiler errors with bizarre messages.

Import Missing Modules

Make sure you import the modules for the frameworks your app uses. If you’re writing an app that works with PDF documents, you must import the PDFKit framework to call its functions in your app.

Edit Swift Files Outside Xcode

Does Xcode’s editor frustrate you? Do you have problems with Xcode’s code completion? Do you wish you could use a different text editor to edit the Swift files in your Xcode projects?

Xcode supports opening and editing Swift files in other text editors, such as BBEdit, Sublime Text, TextMate, and Visual Studio Code. Keep reading to learn how to use your favorite text editor to edit the Swift files in your Xcode projects.

Make Your Text Editor the Default Editor for Swift Files

Start by making your preferred text editor the default editor for Swift files on your Mac. Perform the following steps to change the default editor for Swift files:

  1. Go to the Finder.
  2. Select a Swift file.
  3. Press Cmd-I to open the file’s info panel.
  4. Choose your text editor from the Open with menu.
  5. Click the Change All button.

OpenWithTextEditorPanel

Now when you open a Swift file in the Finder, the file opens in your text editor.

Opening from Xcode

The final step is to open the Swift files in your text editor from Xcode. Select a Swift file in Xcode’s project navigator, right-click, and choose Open with External Editor. The file will open in your text editor.

The changes you make to the text in your text editor will also appear in Xcode. If your project is under version control, an M will appear next to the file in the project navigator, indicating you modified the file.

Xcode Installation Questions

People learning iOS development without prior programming experience have a lot of questions on installing Xcode, Apple’s tool for developing iOS and Mac apps. This post collects these questions and answers them.

Where do I get Xcode?

The easiest way to install Xcode is from the Mac App Store. The Mac App Store has the latest version, which usually requires the latest version of macOS.

If your Mac can’t run the latest version of Xcode, go to Apple’s Xcode Downloads page and install an older version. You can also use the Downloads page to install the latest version if you run into problems with the Mac App Store.

A faster way to find Xcode download links is to go to Xcode Releases, a site that has download links for every version of Xcode. Xcode Releases also lists the minimum version of macOS required for each Xcode version.

Another alternative to the App Store is to use the Xcodes app to install Xcode. I have not used Xcodes, but many people swear by it, saying it installs Xcode much faster than the App Store.

Why does Xcode take forever to install?

Xcode is a huge app. Verifying and expanding it takes a really long time. Even with a fast Internet connection, it will take 1–2 hours to install Xcode.

A Twitter thread explains why expanding takes so much time and provides a tip to speed up the expanding.

If you are installing Xcode from the Mac App Store, you can see the progress of the install from the LaunchPad app.

Why does Apple say I don’t have enough disk space to install Xcode?

Xcode requires a lot of disk space to install. You need 4–5 times the size of the Xcode download to install it. The file you are downloading is a compressed file. You need enough free space to temporarily store both the compressed and expanded files. If you have a Mac with a 128 GB drive, you will have a tough time installing Xcode.

If you get an error message saying there isn’t enough free space to install Xcode, free up more disk space until the error message goes away.

Some ways to free up disk space and work around space limitations include the following:

  • Download Xcode from the Xcode Releases site onto an external drive and expand it there. Copy the expanded file to your main drive.
  • Restarting your Mac can free up disk space if you haven’t restarted the Mac in several days.
  • The Dev Cleaner app can free up space used by Xcode caches and old iOS simulators.
  • Delete existing versions of Xcode before installing a new version.

Can I install Xcode on an external drive?

Xcode must be installed on your Mac’s startup disk. If you make an external drive the startup disk, you can install Xcode on an external drive. Use the System Preferences app (Choose Apple > System Preferences from the menu bar) to set the startup disk.

Can I run Xcode on an iPad?

Xcode currently runs only on Macs. Apple has a Swift Playgrounds app for iPad to learn Swift programming. Version 4, which requires iOS 15, lets you develop iOS apps on an iPad.

Can I run Xcode on a Windows PC?

Not without violating Apple’s license on macOS. Xcode currently runs only on macOS. Apple’s license forbids installing macOS on non-Apple hardware.

Can I have multiple versions of Xcode on my Mac?

Yes you can.

If you are installing Xcode from the Mac App Store, make sure you don’t overwrite your existing Xcode install. When installing from the Mac App Store, Apple adds a file named Xcode in your Applications folder. Change the name of the existing Xcode app on your Mac before installing the new version.

Where are the Single View and Master-Detail App Project Templates?

Prior to Xcode 12 Xcode had the following iOS application project templates:

  • Single View App
  • Master-Detail App
  • Page-Based App
  • Tabbed App

If you create an iOS application project in Xcode 12, you will notice these project templates are missing. In Xcode 12 Apple consolidated these project templates into one template: App. If you are following a tutorial that tells you to choose one of the older templates that no longer exist, choose the App template.

Getting Started with Swift Unit Testing in Xcode

In this article you’ll learn what you need to start unit testing your Swift code in Xcode.

Adding a Unit Test Target to Your Xcode Project

To unit test your app, your Xcode project must have a unit test target. The easiest way to add a unit test target to your project is to select the Include Tests checkbox when you create the project. Selecting the checkbox creates targets for unit tests and UI tests.

To add a unit test target to an existing Xcode project, choose File > New > Target.

AddUnitTestingTarget

Select your app platform (iOS, macOS, watchOS, tvOS) from the top of the New Target Assistant. Select the Unit Testing Bundle target from the list of targets. You will have to scroll through a long list of application extension targets to find the test targets.

Adding a Unit Test Class to Your Xcode Project

When you create the unit test target, Xcode includes a unit test class file. It has the name AppNameTests.swift, where AppName is the name of your project. Unless you have a really small project, you will have multiple unit test classes.

Choose File > New > File to add a new file to your project.

AddUnitTestClass

Select Unit Test Case Class from the list of file templates. Click the Next button.

Enter the name of the class in the Class text field. The subclass should be set to XCTestCase, and the language should be set to Swift. Click the Next button.

Save the file inside the Tests folder. Make sure to select the checkbox for the unit test target.

AddUnitTestClassToTarget

Click the Create button to finish creating the unit test class.

The Initial Unit Test Class

Select the unit test class’s Swift file to open it. It should look similar to the following code:

The first two lines of code import the XCTest framework, which is the framework Xcode uses for unit testing Swift code, and your app. You must use the @testable import statement to give the unit test class access to your app’s code. If your app name has spaces in it, use the underscore character instead of spaces in the @testable import call.

Next comes the declaration of the unit test class. It inherits from XCTestCase, the base class for Xcode’s unit test classes.

Finally comes the four empty test methods.

  • The setUpWithError method gets called before running each test in the class. Put any setup code you need to run before each test in this method.
  • The tearDownWithError method gets called after each test runs.
  • The testExample method provides a shell for a unit test. You can delete this method.
  • The textPerformanceExample method provides a shell for a performance unit test. You can delete this method.

The throws keyword means the test method throws an exception if the test fails.

Older versions of Xcode may not have the throws keyword in the test methods. The setup and teardown methods may not have the WithError part at the end.

XCTest Test Methods

Each unit test requires you to write a method for it. A unit test method has the following requirements:

  • It must start with the word test.
  • It takes no arguments.
  • It returns no value.

The following code shows the definition of a unit test method:

In the test start by calling the code in your app that you want to test. Then make an assertion, which I talk about next.

XCTest Assertions

Each test needs at least one assertion, which determines whether or not the test passes. XCTest assertions start with XCTAssert. If you start typing XCTAssert, Xcode’s code completion should show you a list of all the available assertions, but the following are the most widely-used assertions:

  • XCTAssertNotNil asserts a variable is not nil.
  • XCTAssertTrue asserts a condition is true.
  • XCTAssertFalse asserts a condition is false.
  • XCTAssertEqual asserts two values are equal.

The simplest way to write an assertion is to supply an expression.

But when you supply only the expression, all you get when a test fails is a message that the test failed. In this assertion example, when the assertion fails, you would like to know what the value of temperature is. Supply an error message to report as the final argument in the assertion. Wrap the variable whose value you want to report using the following syntax:

The following shows an improved assertion that the temperature is above 0.

Running Unit Tests

Xcode provides multiple ways to run your tests.

  • Press Cmd-U to run all your tests.
  • Run a unit test class’s tests from the Xcode editor by clicking the diamond-shaped button on the left side of the editor next to the test class name.
  • Run a single test from Xcode’s editor by clicking the diamond-shaped button next to the test method.
  • Press Cmd–6 to open the test navigator. Selecting the test target, a test class, or a test will make a small button appear on the right side of the navigator. Click the button to run the target’s tests, the class’s tests, or the single test, depending on what you selected.

Unit Testing Checklist

Use the following checklist to start unit testing your Swift code in Xcode:

  • Create a unit test target by selecting the Include Tests checkbox when creating your Xcode project.
  • Add unit test classes to the test target by choosing File > New > File.
  • Import the XCTest framework in your unit test classes.
  • Use the @testable import statement to give your unit test classes access to your app’s code.
  • Add test methods to your unit test classes.
  • Test methods start with test, take no arguments, and return no value.
  • Add at least one XCTest assertion in your test methods.
  • Press Cmd-U to run the tests.

Renaming Xcode Projects

Renaming Xcode projects is not intuitive or obvious. If you do it wrong, you can mess up your project. In this article you will learn how to safely rename your app and your project.

Rename the Target to Rename the App

Most of the time when people want to rename their project, what they really want to do is rename their app. By renaming the app target, you can rename the app without having to rename the project.

Select the project from the project navigator to open the project editor and see a list of the app’s targets.

TargetList

To rename a target, select it, press the Return key, and enter the new name. If all you want to do is rename the app, you’re finished.

Renaming the Project

Continue reading if you really want to rename the project. If you look at the screenshot from the previous section, you might think you could rename the project by selecting it and pressing the Return key. But you’ll discover that you can’t change the project name from the project editor.

Use the project navigator to change the project name.

ChangeXcodeProjectName

Select the project file and press Return to change the name. A sheet will open.

RenameProjectSheet

Xcode is initially set to rename all the project’s targets to reflect the new name of the project. Deselect a checkbox next to any item you don’t want to rename. Click the Rename button to rename the project.

Clicking the Don’t Rename button will rename the project file but won’t rename anything else.