Safely access Apple's SF Symbols using static typing

Overview

Build Status Swift: 5 Version: 2.1.3 Platforms: iOS – tvOS – watchOS – macOS License: MIT
SwiftPM: Compatible Carthage: Compatible CocoaPods: Compatible

Supported VersionsMotivationInstallationUsageContributingLicenseIssuesPull Requests

Supported Versions

SFSafeSymbols supports multiple SF Symbols versions at the same time by utilizing the @availability flag. The following versions are currently supported:

  • SF Symbols 2.1 (@available(iOS 14.2, macOS 11.0, tvOS 14.2, watchOS 7.1, *))
  • SF Symbols 2.0 (@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *))
  • SF Symbols 1.0 (@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *))

Motivation

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 even a dedicated Mac app called SF Symbols. However, developers still have to copy the name of an icon and reference it unsafely, resulting in code like this:

UIImage(systemName: "circle.fill")

It didn't take long until first ideas came up to make these icons accessible in a safe way using a framework. And this is just what SFSafeSymbols does!

Installation

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

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

Swift Package Manager (Xcode-integrated)

To integrate SFSafeSymbols using the Xcode-built-in SPM, choose FileSwift PackagesAdd Package Dependency. Enter the following url: https://github.com/piknotech/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 unless you really want to use SFSafeSymbols-Dynamic and know what you are doing.

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:

.package(url: "https://github.com/piknotech/SFSafeSymbols.git", .upToNextMajor(from: "2.1.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 "piknotech/SFSafeSymbols" ~> 2.1.3

Then run carthage update.

CocoaPods

Add the following entry to your Podfile:

pod 'SFSafeSymbols', '~> 2.1.3'

Then run pod install.

Usage

All the system icons are accessible via the SFSymbol enum. 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 enum. This image is already unwrapped, so you get a UIImage instead of a UIImage?:

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 enum:

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

There are also SwiftUI.Label initializers:

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

... and interfaces for UIButton:

let button = UIButton.systemButton(with: .cCircle, target: self, selector: #selector(testMethod))
button.setImage(.eCircleFill, for: .normal)

... and an initializer for UIApplicationShortcutItem:

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

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

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

Testing

All symbols are tested via a CI (on the latest iOS & tvOS versions), so you can be sure your code won't crash because an image couldn't be found!

Contributing

Contributions are very much welcome! See CONTRIBUTING.md for more information.

License

This library is released under the MIT License. See LICENSE for details.

Comments
  • Supporting explicit symbol localization

    Supporting explicit symbol localization

    Apple mentioned in this WWDC Video (4:10) that explicit localization is supported, and we know what suffixes are supported based on name_availability.plist extracted from the app.

    This issue is for discussion to support this feature or not and to choose the implementation approach. Implementation details (e.g: Naming) will be discussed separately once the PR is made.

    These are the implementations that I have in mind, ordered based on type-safety:

    Implementation 1

    • Providing localized properties on SFSymbol for all the possible localizations, returns a new type LocalizedSFSymbol.
    • Initializing UIImage with LocalizedSFSymbol returns UIImage?.

    Example:

    extension SFSymbol {
    	var ar: LocalizedSFSymbol { LocalizedSFSymbol(rawValue: "\(rawValue).ar") }
    	// all other possible localizations, even ".rtl" which is not available for "character"
    }
    
    let arabicCharacterImage = UIImage(systemSymbol: .character.ar) // UIImage?
    

    Implementation 2

    • Having an internal Dictionary<SFSymbol, Set<Localization>>.
    • Providing localized properties on SFSymbol for all the possible localizations, returns a new type LocalizedSFSymbol? based on the Dictionary.
    • Initializing UIImage with LocalizedSFSymbol returns UIImage.

    Example:

    extension SFSymbol {
    	var ar: LocalizedSFSymbol? {
    		guard localizationDictionary[self]?.contains(.ar) == true else { return nil }
    		return LocalizedSFSymbol(rawValue: "\(rawValue).ar") 
    	}
    	// all other possible localizations, even ".rtl" which is not available for "character"
    }
    
    if let arabicCharacterSymbol = SFSymbol.character.ar {
    	let arabicCharacterImage = UIImage(systemSymbol: arabicCharacterSymbol) // UIImage
    }
    

    Implementation 3

    • Providing a new namespace for each symbol with localization.
    • For each symbol, The new namespace will have only the localization(s) available for this symbol
    • Keeping the default symbols as they are currently for source compatibility.

    Example:

    extension SFSymbol {
    	enum Character {
    		static var ar: SFSymbol { SFSymbol(rawValue: "character.ar") }
    		// all other localizations available for "character" only
    	}
    }
    
    let defaultCharacterImage = UIImage(systemSymbol: .character) // UIImage
    let arabicCharacterImage = UIImage(systemSymbol: .Character.ar) // UIImage
    // or
    let arabicCharacterImage = UIImage(systemSymbol: .Localizable.Character.ar) // UIImage
    

    Implementation 4

    • Same idea as Implementation 3.
    • Instead of keeping the default symbols static in SFSymbol, it would be moved to its dedicated namespace. Avoiding the confusion of .Character and .character.

    Example:

    extension SFSymbol {
    	enum Character {
    		static var default: SFSymbol { SFSymbol(rawValue: "character") }
    		static var ar: SFSymbol { SFSymbol(rawValue: "character.ar") }
    		// all other localizations available for "character" only
    	}
    }
    
    let defaultCharacterImage = UIImage(systemSymbol: .Character.default) // UIImage
    let arabicCharacterImage = UIImage(systemSymbol: .Character.ar) // UIImage
    

    @fredpi @knothed what do you think?

    opened by StevenSorial 33
  • Support explicit symbol localization

    Support explicit symbol localization

    Implements #87.

    Following this suggestion by @StevenMagdy, one protocol per localization per availability is created.

    The decision for the protocol names fell on hi and hi_v30 as these are shorter, easier to read and look better than HiLocalizable and HiLocalizableV30. What do you think?

    Additionally, allSymbols was made into an SFSymbolSet which allows to localize all symbols (via allSymbols.hi) and which exposes allSymbolVariants containing every localization variant of every symbol.

    The symbol documentations were adapted to match the actual exposed localizations: when deprecated symbols do not provide some localizations, but only their new versions do, these localizations are not in the documentation of the deprecated symbol to match its actual type. (example in the image) image

    opened by knothed 29
  • Support for SF Symbols 4

    Support for SF Symbols 4

    As can be seen here, there will be a new version of SF Symbols: SF Symbols 4. Currently, the SF Symbols 4 app isn't available to download, but it probably won't last long until we learn all about it.

    This issue can be used to collect ideas / track progress on the SF Symbols 4 support.

    enhancement 
    opened by fredpi 13
  • make `SFSymbol` struct

    make `SFSymbol` struct

    I believe SFSymbol is naturally a String backed struct, not enum.

    public struct SFSymbol: RawRepresentable {
        
        public let rawValue: String
        
        public init(rawValue: String) {
            self.rawValue = rawValue
        }
    }
    

    When new symbols were added (like #53), user can do it on their own:

    public extension SFSymbol {
        
        @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
        static let sealFill = SFSymbol(rawValue: "seal.fill")
    }
    

    We can also break the massive SFSymbol.swift file into smaller fils (v1, v2, v2.1, deprecated).

    I believe all existing functions won't be compromised. I can work on a pr with your permission.

    opened by ddddxxx 13
  • Support for SF Symbols v3

    Support for SF Symbols v3

    SF Symbols v3 are now officially a thing and the corresponding app to browse them can be downloaded at https://developer.apple.com/sf-symbols/.

    I quickly browsed the app and saw the following new features:

    • There are new types in addition to Monochrome and Multicolor: Hierarchical & Palette. Fortunately, there is a file embedded in the app that tells us everything about the types for each symbol: layerset_availability.plist. I suggest we add this information to each's symbol documentation (similar to the localized versions).
    • There's a new file symbol_categories.plist, but I suggest we just ignore it because there's no real value in adding the symbol category to each's symbol documentation IMO.
    • According to Apple, there are > 600 new symbols. As all files that were used to generate the SFSafeSymbols code are still present in the app, it's probably not much work to create an update for these new versions.
    opened by fredpi 12
  • Add support for next-generation SFSymbols

    Add support for next-generation SFSymbols

    SFSafeSymbols should include support for the new symbols introduced with iOS 14 and the other Apple operating systems.

    Regarding the structuring I suggest the following design:

    enum SFSymbol {
        @available(iOS 13...)
        enum v1 {
            case ...
        }
    
        @available(iOS 14...)
        enum v2 {
            case ...
        }
    }
    

    The SFSymbols 2 app required for parsing the symbol catalog isn't available yet, so I will look into this as soon as the app is available.

    enhancement 
    opened by fredpi 12
  • Add layerset documentation & improve documentation

    Add layerset documentation & improve documentation

    This PR adds support for layerset documentation which I stated as a goal for the v3 release (https://github.com/piknotech/SFSafeSymbols/issues/75).

    I also updated the whole documentation style to better align with the way documentation is rendered in Xcode 13.

    With the new documentation style, an exemplary symbol documentation now looks as follows:

    doc

    Notably, when the user types the symbol name, they will now only see the documentation summary in the editor, i. e. the symbol preview. It might be suitable to add a note whether localizations or layersets are available. What do you think? @StevenMagdy @knothed

    Simple summary:

    simple

    Extended summary:

    extended

    In this PR, I shortened the availability descriptions of localizations and layerset iOS 15.0, macOS ..., tvOS ..., watchOS ... to just iOS 15.0. With this, some information is removed, but I think that's okay for the sake of better readability.

    @StevenMagdy I noticed that there are still some TODOs in the Symbols Generator project. Are those still relevant? If true, it would be better to track them in a GitHub issue instead of the code. Would you mind removing the TODOs and creating GitHub issues if needed? You may use this branch and PR; I won't commit further until you reviewed and commented the PR.

    Also I think that the behavior introduced by the use of the localizationsOfAllVersions(of:) is incorrect: E. g., the legacy a is described as offering multiple localizations, but Apple only guarantees that those are available for the successor (character). Therefore, providing the same localization information for both the legacy and the current symbol name isn't correct, right? If you agree, would you mind changing this behavior?

    opened by fredpi 9
  • Supporting custom SFSymbols

    Supporting custom SFSymbols

    This looks like a great and useful project. I'm going to try to use it in a personal project.

    Looking ahead, though, I can see myself making my own custom additions to SF Symbols. I haven't tried this yet, but Apple documents how you would do this. Does SFSafeSymbols already give us a way to extend its support to our own custom additions?

    opened by ramink 8
  • Deprecated symbol names?

    Deprecated symbol names?

    Hi, I'm using SFSafeSymbols in my new project, but I get +100 Warnings in my log that several names were deprecated / changed in iOS 14.

    Is there a way to get a release that's for iOS 14+ ? I installed through CocoaPods btw.

    Thanks in advance

    opened by LilaQ 8
  • StringProtocol type inference issue in SwiftUI's Label initializers

    StringProtocol type inference issue in SwiftUI's Label initializers

    I just noticed a strange behavior. In SwiftUILabelExtension, the protocol StringProtocol is always matched to String instead of LocalizedStringKey if you write a string literal in your code. This is inconsistent with other SwiftUI native methods. For example:

    // Native SwiftUI:
    Text("some text")                      // inferred as LocalizedStringKey
    Label("some text", systemImage: "...") // inferred as LocalizedStringKey
        .navigationBarTitle("some text")   // inferred as LocalizedStringKey
    
    // SwiftUILabelExtension:
    Label("some text", systemSymbol: .xxx) // hmm... inferred as String... 🤔
    

    So I have to do the following to ensure the text is being localized correctly:

    Label("some text" as LocalizedStringKey, systemSymbol: .xxx) // 🤔
    

    I checked the implementation of SwiftUILabelExtension and it seems to be defined in the same way as in SwiftUI's native methods, but I don't know why the compiler doesn't give priority to matching LocalizedStringKey.

    public extension Label where Title == Text, Icon == Image {
        
        /// Creates a label with a system symbol image and a title generated from a
        /// localized string.
        ///
        /// - Parameter systemSymbol: The `SFSymbol` describing this image.
        init(_ titleKey: LocalizedStringKey, systemSymbol: SFSymbol) {
            self.init(titleKey, systemImage: systemSymbol.rawValue)
        }
        
        /// Creates a label with a system symbol image and a title generated from a
        /// string.
        ///
        /// - Parameter systemSymbol: The `SFSymbol` describing this image.
        init<S>(_ title: S, systemSymbol: SFSymbol) where S : StringProtocol {
            // 🤔 always goes here with S==String...
            self.init(title, systemImage: systemSymbol.rawValue)
        }
    }
    

    I suggest to check if we can find a better way to define the initializer signatures. Because this inconsistent behavior can easily lead to localization bugs, and it is less easy to be found if the app is not fully tested.

    opened by gongzhang 8
  • Improve package specs

    Improve package specs

    This PR improves the package specs (Package.swift and SFSafeSymbols.podspec):

    • General: Lower the library requirements to 2016 platforms (iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0).
    • Package.swift: Raise the minimum Swift version to 5.3 to match SFSafeSymbols.podspec.
    • Package.swift: Remove the library type (static/dynamic) which lets SPM picks it automatically (recommended by Apple). Tested successfully on the repo provided in #61.
    • SFSafeSymbols.podspec: Add support for swift 5.4 and 5.5.
    • SFSafeSymbols.podspec: Remove static_framework = true. Fixes #78.
    opened by StevenSorial 7
  • Document CI workarounds before release

    Document CI workarounds before release

    In the release documentation, a step should be added that describes the need for a locally run pod spec lint before the start of the release. While the lint is run on a CI, different issues may occur on a local machine – for example: the watchOS simulator issues that @StevenMagdy fixed for Bitrise with this code:

    xcrun simctl delete all;
    phoneID=$(xcrun simctl create "iPhone 14" com.apple.CoreSimulator.SimDeviceType.iPhone-14);
    watchID=$(xcrun simctl create "Apple Watch SE (40mm) (2nd generation)" com.apple.CoreSimulator.SimDeviceType.Apple-Watch-SE-44mm-2nd-generation);
    tvID=$(xcrun simctl create "Apple TV" com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p);
    xcrun simctl pair $watchID $phoneID;
    

    This workaround may also be added to the documentation.

    If we don't add this step to the release instructions, an issue may occur with a version having been released on Github, but the core contributor that released it being unable to push to CocoaPods.

    documentation 
    opened by fredpi 4
  • Add Symbol Categories

    Add Symbol Categories

    Hi,

    It would be helpful to add the symbol categories from the symbol.categories.plist file in SF Symbols.app to SFSymbol class to make sorting / filtering images in a view easier.

    enhancement 
    opened by narwahle 6
Releases(4.1.0)
Owner
Piknotech
Healthy Software
Piknotech
📷 A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 3, 2023
GPUImage 3 is a BSD-licensed Swift framework for GPU-accelerated video and image processing using Metal.

GPUImage 3 Janie Clayton http://redqueengraphics.com @RedQueenCoder Brad Larson http://www.sunsetlakesoftware.com @bradlarson contact@sunsetlakesoftwa

Brad Larson 2.4k Jan 3, 2023
SharkCardScan is a Credit/Debit Card scanner built using Apple's Vision Framework.

iOS Credit/Debit card scanner, built using Apple's Vision Framework.

Gymshark 23 Nov 16, 2022
📷 A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 2, 2023
Script to support easily using Xcode Asset Catalog in Swift.

Misen Misen is a script to support using Xcode Asset Catalog in Swift. Features Misen scans sub-directories in the specified Asset Catalog and creates

Kazunobu Tasaka 123 Jun 29, 2022
A simple macOS app to read code from images, written purely in Swift using Vision Framework.

CodeReader A simple macOS app to read code from images, written purely in Swift using Vision Framework. Usage Drag an image Click the convert button R

Md Ibrahim Hassan 44 Nov 20, 2022
In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3

In-App-ScreenRecording-iOS In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3 Features: Recording application screen onl

Ahmed Abdelkarim 4 Dec 23, 2022
iOS hashtag generator, using image analysis and discovery

Tagger Description Want to be popular on some social network easily? Use Tagger to make your account content more popular and to raise your popularity

Ivan Magda 44 Dec 17, 2022
A free, multiplatform SDK for real-time facial motion capture using blendshapes, and rigid head pose in 3D space from any RGB camera, photo, or video.

mocap4face by Facemoji mocap4face by Facemoji is a free, multiplatform SDK for real-time facial motion capture based on Facial Action Coding System or

Facemoji 592 Jan 1, 2023
IOS UIImage processing functions using the vDSP/Accellerate framework for speed.

UIImage Image Processing extensions using the vDSP/Accelerate framework.

null 372 Sep 1, 2022
GPU-based media processing library using Metal written in Swift

GPU-based media processing library using Metal written in Swift. Overview MetalAcc is a GPU-Based media processing library that lets you apply GPU-acc

Jiawei Wang 259 Dec 17, 2022
A view that takes a set of images, make transition from one to another by using flipping effects.

CDFlipView A view that takes a set of images, make transition from one to another by using flipping effects. Demo Live Demo: https://appetize.io/app/w

Jianbin LIN 99 Aug 27, 2021
An implementation of High Pass Skin Smoothing using Apple's Core Image Framework

YUCIHighPassSkinSmoothing An implementation of High Pass Skin Smoothing using CoreImage.framework Available on both OS X and iOS. Ports A MetalPetal b

Yu Ao 1.2k Dec 17, 2022
Using remote images in an application is more or less a requirement these days.

Imaginary Table of Contents Description Usage Basic Advanced Configuration ImageFetcher Installation Description Using remote images in an application

HyperRedink 597 Nov 8, 2022
A simple UIImageView extension for using initials as a profile image, written in swift

InitialsImageView An easy, helpful UIImageView extension that generates letter initials as a placeholder for user profile images, with a randomized ba

Tom Bachant 215 Dec 17, 2022
Style Art library process images using COREML with a set of pre trained machine learning models and convert them to Art style.

StyleArt Style Art is a library that process images using COREML with a set of pre trained machine learning models and convert them to Art style. Prev

iLeaf Solutions Pvt. Ltd. 222 Dec 17, 2022
High Quality Image ScrollView using cropped tiled images.

THTiledImageView Feature ?? THTiledImageView fully support UIScrollView. You can subclass it and use it. ?? Support Async Image Downloading & Caching.

null 28 Oct 28, 2022
Applies filter to a selected image from the Gallery using Combine

CombinePhotoFiltering App CombinePhotoFiltering is an app that applies sepia and bloom to a selected picture from the Photos app. Highlights The app i

Mauricio Esteves 0 Nov 14, 2021
Picture anonymiser using Vision face recognition

?? Anonymojizer [WIP] Anonymize people in photos by replacing their faces by emojis. How to use it ? Pick a photo from the gallery Choose an emoji The

Kaww 1 Dec 20, 2021