Manage resources easily using Swift Package Manager

Tan Terry
24stechblog
Published in
5 min readFeb 4, 2021

--

As iOS developers, we often need to manage many resources to develop new features or UI. Things may go quite smoothly for a one man team, but when a project becomes more and more complex, management of the project also becomes more and more complicated. If the communication amongst different teams is not fluid, the same work could be done repeatedly, or the user experience could become inconsistent.

The proper way is to modularize the project. There are many benefits of modularization, but here we will only talk about UI modules. This can ensure that any team can use uniform components, and it is easy for designers to follow the guidelines to design new components.

As a Swift developer, I choose Swift Package Manager to manage the resources. I will now introduce what Swift Package Manager is, and how to use the new feature to manage resources.

What is Swift Package Manager

If you have some experiences in managing dependencies, you have probably used CocoaPods or Carthage to manage your projects. Both tools are popular and great, but as a Swift developer, we are always looking for something native to use, that is why we have no reason to refuse Swift Package Manager.

Swift Package Manager, or SPM, is a tool for managing the distribution of Swift code, it allows people to integrate their tools easily into their projects.

You can use File > New > Swift Package in Xcode or use the command line swift package init to create a SPM project. Let’s say we want to create a music player app, and I want to create a module to manage basic assets (e.g. play button) and resources, so I create a new SPM project PlayerUI.

You can see the module underneath the Sources folder, in this case we only have one PlayerUI module. The other most important file Package.swift is the manifest file of the project.

The Package.swift consists of three major parts: Targets, Products and Dependencies.

  • Targets define the modules of the project
  • Products is the output of the project, it can be an executable file
  • Dependencies declare other packages that this package depends on

After a brief introduction of the structure, let’s start to understand how to add resources into your package. One thing you must be aware of though, is that in order for SPM to support resources, the Swift toolchain version must be 5.3 or higher in the first line of Package.swift, otherwise it will not be available.

Files types

In WWDC 2020, Apple announced that SPM will start to support resources in the framework bundle, which is a big feature that we have been waiting for since the first version of SPM was released.

Adding files is simple in the main project, drag the file directly into the project and select the targets you want to link with in the Xcode inspector, and that is it.

It is almost the same in SPM, but there are some different rules according to the purpose that you need to be aware of.

For clear purpose files, we can add them directly into the project without any extra declaration, because Xcode recognizes these files:

For ambiguous purpose files, we have to declare our intent in Package.swift, such as plain text file, shell, image, etc.

Swift 5.3 introduced new parameters resources and exclude for adding or excluding those ambiguous purpose files. It allows us to copy or declare an exclusive list of files that we do not desire to copy to the bundle.

As the dialog above, you might notice two special rules in resources, process() and copy(), they declare how you want to treat the resources.

Process

This is recommended by Apple. This rule will copy files into the bundle of the module and it will optimize images according to the building platform.

Xcode will recursively add files and retain the directory structure .

Copy

This is almost the same as process, but it only copies files into the top-level of the resource bundle without doing any optimizations. As shown in the example, we can copy the directory of data because there is no need to optimize it.

Let’s see how it works! Package uses the Bundle to access resources, so you can pass the bundle to any APIs that take bundle parameters, such as Image, Text in SwiftUI, or UIImage in UIKit.

I will add an image resource and create a button PlayButton that shows it.

Image view will search and show the image “play” in the module bundle

As shown in the dialog above, I pass the bundle of the module to access resources in order to show the “play” image.

Localize your package

In this new version of SPM, you can even add localized resources into the project. There is a parameter defaultLocalization in Package.swift, which allows us to set the default localized language if no localized file is found.

In this project, I have used English as the default language. To add your localizable string, first create a folder and name it as en.lproj for English, then create a file Localizable.strings and add your key and value. Here I will add "play" = “Play" for play button. Next, we follow the same process to create another folder fr.lproj and file for French, then add the new value "play" = “Jouer".

I will do the same with the Image view to localize the text, which is to pass a resource bundle of the module with Text view.

Let’s preview the result, instead of changing the system language, we can use .environment(\.locale, init(identifier: “fr”)) to see the result by different locales.

Conclusion

Adding resources to a Swift package is pretty easy and straightforward, this new feature makes it more powerful and complete. It also pushes me to start integrating some major dependencies into the existing project. However, it still lacks some features, such as updating a single dependency without updating the others.

If the project is not big enough, creating a resources management framework might take too long. But as the SPM is becoming more and more complete, it is the good time to start using it. It is not only good for building a proper development environment, but also for providing a better solution for designers.

References

https://developer.apple.com/videos/play/wwdc2020/10169/

https://www.sketchappsources.com/free-source/4543-essential-icons-sketch-freebie-resource.html

--

--