SF Symbols for iOS: Getting Started
Learn to use SF Symbols, both existing and custom, to show data in an engaging way. By Tom Elliott.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
SF Symbols for iOS: Getting Started
30 mins
- Getting Started
- Getting Acquainted with the App
- Importing Models and Data
- Adding TransportAPI Functionality
- Setting up TransportAPI
- Connecting the API
- Understanding SF Symbols
- Viewing Available Symbols
- Using SF Symbols
- Testing with Mock Data
- Naïve Mock Data Approaches
- Using Mock Data with Environment Variables
- Switching Between Mock Data and Actual Data
- Using the DebugData Scheme
- Understanding Restrictions on Using SF Symbols
- Creating Custom SF Symbols
- Making an “Information” Symbol
- Importing the Exclamation Mark Symbol
- Customizing the Exclamation Mark Symbol
- Using Custom Symbols
- Supporting Older Operating Systems
- Where to Go From Here?
Switching Between Mock Data and Actual Data
Now, look at DebugDataService.swift. There are only a few lines of code here, but quite a lot going on! This is what the code in this file does:
- First, the file imports
Combine
to give it access to theFuture
class. - Next, it defines
DebugDataService
as conforming toTubeLinesStatusFetcher
. - Then, it implements
fetchStatus
— the only method required byTubeLinesStatusFetcher
. - Finally, it returns
debugData
wrapped in aFuture
. ThisdebugData
is the data you added in the previous section.
To use the debug line status fetcher, create a Swift file called TubeLinesStatusFetcherFactory.swift and add the following code:
// 1
enum TubeLinesStatusFetcherFactory {
// 2
static func new() -> TubeLinesStatusFetcher {
// 3
#if DEBUG
if ProcessInfo.processInfo.environment["USE_DEBUG_DATA"] == "true" {
return DebugDataService()
}
#endif
// 4
return TransportAPIService()
}
}
Here’s what’s happening:
- As you only want static methods on this entity, it’s implemented as a caseless enum. You could use a
struct
here instead, but it would be possible to needlessly instantiate astruct
, so anenum
is a better choice. - Define a single static method,
new()
, which returns an object conforming toTubeLineStatusFetcher
. - If running in debug mode and
USE_DEBUG_DATA
is set totrue
, return an instance ofDebugDataService
created previously. - Otherwise, return an instance of
TransportAPIService
, which fetches the real data from the Transport API.
Finally, open AppMain.swift and find this line:
model: TubeStatusViewModel(tubeLinesStatusFetcher: TransportAPIService())
Replace it with the following:
model: TubeStatusViewModel(
tubeLinesStatusFetcher: TubeLinesStatusFetcherFactory.new())
Here, you’re adding another layer of indirection and initializing TubeStatusViewModel
with whatever fetcher TubeLinesStatusFetcherFactory decides to provide for it rather than using TransportAPIService
directly.
Using the DebugData Scheme
Now, time to test it out! Make sure to select the Debug Data scheme.
Now, build and run the app.
This is a great example of the power and flexibility of both protocol-oriented programming and dependency injection.
By passing the data-fetching service as a dependency into TubeStatusViewModel
, it was simple to replace how the data was fetched with a different implementation.
By only providing TubeStatusViewModel
with the protocol that the data-fetching service uses to return the data — and not the implementation — the view model doesn’t deal with how the data is fetched. It could be hard-coded or downloaded via a JSON API.
Understanding Restrictions on Using SF Symbols
Before you go crazy and add SF Symbols everywhere, be aware that restrictions exist on where and how you can use them.
Quoted directly from Apple’s Human Interface Guidelines:
“You may not use SF Symbols — or glyphs that are substantially or confusingly similar — in your app icons, logos, or any other trademark-related use. Apple reserves the right to review and, in its sole discretion, require modification or discontinuance of use of any Symbol used in violation of the foregoing restrictions, and you agree to promptly comply with any such request.”
“You may not use SF Symbols — or glyphs that are substantially or confusingly similar — in your app icons, logos, or any other trademark-related use. Apple reserves the right to review and, in its sole discretion, require modification or discontinuance of use of any Symbol used in violation of the foregoing restrictions, and you agree to promptly comply with any such request.”
Additionally, SF Symbols are considered to be system-provided images and thus are covered by the Xcode and Apple SDK license agreements.
Furthermore, 124 SF Symbols aren’t allowed to be exported, modified or used for any purpose other than Apple-specific technologies.
Apple publishes a full list of these more restricted icons. The right-hand pane in the SF Symbols app also details any extra restrictions when you select a symbol.
Creating Custom SF Symbols
Even though Apple has provided thousands of different symbols in the SF Symbol library, it’s impossible to cover every conceivable image you may need in your app. What Apple has done instead is make it really easy for you to build your own custom symbols, when needed.
SF Symbols are built as vector graphics in an SVG file with a very specific formatting. At the top level, the file must contain three layers: Symbols, Guides and Notes. Each of these layers then contains sub-layers. For example, the Symbols layer contains 27 sub-layers — one for each of the variants available.
Furthermore, Apple makes it easy to create your own symbols by allowing you to export existing symbols from the SF Symbols app. That way, all the formatting is already present and you just need to change whatever you want to customize.
When building a custom symbol, it’s a good idea to find a built-in symbol that’s as close as possible to what you’re trying to draw and then adapt it to your needs.
You’re now going to see how to add a custom symbol into your app.
Making an “Information” Symbol
For this section, you need a vector art app that can edit SVG images.
Many different options are available, including paid products like Adobe Illustrator, Sketch, Figma and Affinity Designer. Most of these offer free trials. Open-source products are also available, like Inkscape and OpenOffice Draw.
This tutorial uses Affinity Designer, but the process should be similar in other vector art apps.
Importing the Exclamation Mark Symbol
Open the SF Symbols app on your Mac and search for the exclamationmark.circle symbol. Select it, and choose File ▸ Export Custom Symbol Template…. Save the symbol template on your machine and open it in your vector graphics app.
As you can see, the SVG file contains 27 separate images for each of the 9 font weights and 3 sizes.
Updating all 27 images would take a long time, but fortunately you don’t need to change any that you aren’t going to use. The only variant you need here is Regular-M, as that’s all this app uses. Apple recommends you create Regular S/M/L and Semi-bold S/M/L, as many of the common UIKit controls use these variants.
Customizing the Exclamation Mark Symbol
Find the Regular-M variant near the center of the canvas. Each symbol is built as a group in the SVG. Delete the exclamation mark in the center of the circle. You may need to ungroup the layer first, depending on which vector art app you’re using.
Next, add a text block to the layer and type a lowercase i. Size it to 64pt in SF Pro and weight Heavy. Then place it at the center of the circle.
Each variant in a custom SF Symbol can only contain shapes/curves. They must not contain text, bitmaps or any other type of object. Convert your i text layer into a curve. In Affinity Designer, do this by selecting Layer ▸ Convert to Curves.
Make sure your new layer is a sub-layer of the Regular-M group. Then, save or export your new symbol as an SVG called information.svg.
Switch to the SF Symbols app and select File ▸ Validate Custom Symbols…, then select the file you just saved. If you’ve done everything correctly, your new symbol will be validated — yay!