Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sfsafesymbols/sfsafesymbols

Safely access Apple's SF Symbols using static typing
https://github.com/sfsafesymbols/sfsafesymbols

icons ios sfsymbols swift symbols

Last synced: 29 days ago
JSON representation

Safely access Apple's SF Symbols using static typing

Awesome Lists containing this project

README

        





Build Status


Swift: 5


Version: 5.3


Platforms: iOS – tvOS – watchOS – macOS


License: MIT




SwiftPM: Compatible


Carthage: Compatible


CocoaPods: Compatible


Idea & Features
Supported Versions
Installation
Usage
Contributing
License
Issues
Pull Requests

## Idea & Features

At WWDC 2019, Apple announced a new library of icons that came included with that year's new operating system versions. To browse them, there's a [dedicated Mac app](https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/) called SF Symbols. However, developers still have to copy the name of a symbol and reference it unsafely, resulting in code like this:

```swift
UIImage(systemName: "circle.fill")
```

It didn't take long until [first ideas came up](https://twitter.com/simjp/status/1135642837322588161?s=12) to make these icons **accessible in a safe way** using a framework. And this is just the basic idea behind `SFSafeSymbols`!

Furthermore, with `SFSafeSymbols`...

- ... you can be sure your symbol code won't crash due to typos or symbol availability issues. This is because **all symbols are tested via a CI** (on the latest iOS & tvOS versions and also some earlier OS versions).
- ... lookups in the SF Symbols app (e. g. about available **layersets**, available **localizations** & the **look of the symbol**) are no longer needed because every symbol is **documented in code**.
- ... **multiple SF Symbols versions** are supported at the same time (via utilization of the `@availability` flag). Each symbol is only made available on those platform versions where Apple says it's available.
- ... **renamed symbols can be detected easily** (via a deprecation notice which suggests the use of the new name at the same time).

## Supported Versions

The following SF Symbols versions are currently supported:

| SF Symbols Version | iOS Version | macOS Version | tvOS Version | watchOS Version |
| ------------------ | ----------- | ------------- | ------------ | --------------- |
| 1.0 | 13.0 | 11.0 | 13.0 | 6.0 |
| 1.1 | 13.1 | 11.0 | 13.0 | 6.1 |
| 2.0 | 14.0 | 11.0 | 14.0 | 7.0 |
| 2.1 | 14.2 | 11.0 | 14.2 | 7.1 |
| 2.2 | 14.5 | 11.3 | 14.5 | 7.4 |
| 3.0 | 15.0 | 12.0 | 15.0 | 8.0 |
| 3.1 | 15.1 | 12.0 | 15.1 | 8.1 |
| 3.2 | 15.2 | 12.1 | 15.2 | 8.3 |
| 3.3 | 15.4 | 12.3 | 15.4 | 8.5 |
| 4.0 | 16.0 | 13.0 | 16.0 | 9.0 |
| 4.1 | 16.1 | 13.0 | 16.1 | 9.1 |
| 4.2 | 16.4 | 13.3 | 16.4 | 9.4 |
| 5.0 | 17.0 | 14.0 | 17.0 | 10.0 |
| 5.1 | 17.1 | 14.1 | 17.1 | 10.1 |
| 5.2 | 17.2 | 14.2 | 17.2 | 10.2 |
| 5.3 | 17.4 | 14.4 | 17.4 | 10.4 |

## Installation

`SFSafeSymbols` can be installed via the **Swift Package Manager (recommended)**, Carthage or CocoaPods.

Supported platforms are `iOS (11.0+)`, `macOS (10.13+)`, `tvOS (11.0+)` and `watchOS (4.0+)`, although the actual functionality is of course only accessible starting with `iOS 13.0`, `macOS 11.0`, `tvOS 13.0` and `watchOS 6.0`.

### Swift Package Manager (Xcode-integrated)

To integrate SFSafeSymbols using the Xcode-built-in SPM, choose `File` → `Swift Packages` → `Add Package Dependency`. Enter the following url: `https://github.com/SFSafeSymbols/SFSafeSymbols` and click `Next`. When asked about the version, leave the preselection and click `Next`. In the following step, select `SFSafeSymbols` as the package product and click `Finish`.

### Swift Package Manager (standalone)

To integrate using the standalone version of Apple's Swift Package Manager, add the following as a dependency to your `Package.swift`:

```swift
.package(url: "https://github.com/SFSafeSymbols/SFSafeSymbols.git", .upToNextMajor(from: "5.3"))
```

After specifying `"SFSafeSymbols"` as a dependency of the target in which you want to use it, run `swift package update`.

### Carthage

Add the following entry to your Cartfile:

```
github "SFSafeSymbols/SFSafeSymbols" ~> 5.3
```

Then run `carthage update`.

### CocoaPods

Add the following entry to your Podfile:

```rb
pod 'SFSafeSymbols', '~> 5.3'
```

Then run `pod install`.

## Usage

All the system symbols are accessible via the `SFSymbol` type. They are named similar to Apple's names, but use a lower camel case style and prefix names with leading numbers with a `_` character:

```
c.circle ~> SFSymbol.cCircle
e.circle.fill ~> SFSymbol.eCircleFill
11.circle.fill ~> SFSymbol._11CircleFill
```

A SF Symbol `UIImage` can now be initialized using the `SFSymbol` type. This image is already unwrapped, so you get a `UIImage` instead of a `UIImage?`:

```swift
UIImage(systemSymbol: .cCircle)
UIImage(systemSymbol: SFSymbol.eCircleFill)
UIImage(systemSymbol: ._11CircleFill, withConfiguration: /* Some UIImage.Configuration */)
```

A SF Symbol `SwiftUI.Image` can also be initialized using the `SFSymbol` type:

```swift
Image(systemSymbol: .cCircle)
Image(systemSymbol: SFSymbol.eCircleFill)
```

There are also `SwiftUI.Label` initializers:

```swift
Label("MyText", systemSymbol: .cCircle)
Label(LocalizedStringKey("my.text"), systemSymbol: SFSymbol.eCircleFill)
```

... and an initializer for `SwiftUI.Button`:

```swift
Button("MyText", systemSymbol: .cCircle){}
Button(LocalizedStringKey("my.text"), systemSymbol: SFSymbol.eCircleFill){}
Button("MyText", systemSymbol: .cCircle, role: .cancel){}
Button(LocalizedStringKey("my.text"), systemSymbol: SFSymbol.eCircleFill, role: .cancel){}
Button("MyText", systemSymbol: .cCircle, role: .cancel, intent: intent)
Button(LocalizedStringKey("my.text"), systemSymbol: SFSymbol.eCircleFill, intent: intent)
```

... and an initializer for `UIApplicationShortcutItem`:

```swift
UIApplicationShortcutIcon(systemSymbol: .cCircle)
UIApplicationShortcutIcon(systemSymbol: SFSymbol.eCircleFill)
```

... and finally also an initializer for AppKit's `NSImage`:

```swift
NSImage(systemSymbol: .cCircle)
NSImage(systemSymbol: SFSymbol.eCircleFill, accessibilityDescription: "some.description")
```

### Localization

SF Symbols can come with multiple different localizations. `SFSafeSymbols` exposes localization the following way:

- Implicit localization: When using an `SFSymbol`, it gets automatically localized to the user's current locale - nothing to do on your part. This behavior is managed by Apple's system implementation of SF Symbols.

- Explicit localization: `SFSafeSymbols` lets you access a symbol's localized versions as follows:

```swift
// 1. Static localization:
let a = SFSymbol.character.ar // corresponds to "character.ar"
let b = SFSymbol.character.zh // corresponds to "character.zh"
let c = SFSymbol.character.rtl // doesn't compile: "character.rtl" doesn't exist
// a, b have type SFSymbol

// 2. Dynamic localization:
SFSymbol.character.availableLocalizations // [.ar, .he, .hi, .ja, .ko, .th, .zh, .zhTraditional]
let a = SFSymbol.character.localized(to: .ar)
let b = SFSymbol.character.localized(to: .rtl)
// a, b have type SFSymbol?
```

Static localization only exposes the localizations which are actually available, so you cannot accidentally localize a non-localizable symbol.

Dynamic localization, in contrast, is useful when dealing with an array of `SFSymbol`s which all have different available localizations.

Attention: Serializing and deserializing `SFSymbol`s currently makes them lose their _explicit_ static localization information. Dynamic localization information will still be retained.

### Swiftlint

You may want to leverage [SwiftLint](https://github.com/realm/SwiftLint) to ensure that `SFSafeSymbols` is used when appropriate. In your `.swiftlint.yml` file, you can add a custom rule like this:
```yml
custom_rules:
sf_safe_symbol:
name: "Safe SFSymbol"
message: "Use `SFSafeSymbols` via `systemSymbol` parameters for type safety."
regex: "(Image\\(systemName:)|(NSImage\\(symbolName:)|(Label[^,]+?,\\s*systemImage:)|(UIApplicationShortcutIcon\\(systemImageName:)"
severity: warning
```

## Contributing

Contributions are very much welcome! See [CONTRIBUTING.md](https://github.com/SFSafeSymbols/SFSafeSymbols/blob/stable/CONTRIBUTING.md) for more information.

## License

This library is released under the [MIT License](http://opensource.org/licenses/MIT). See [LICENSE](https://github.com/SFSafeSymbols/SFSafeSymbols/blob/stable/LICENSE) for details.