Importing pictures and sounds into Swift Package

Introduction

As a coursework, I needed to develop a library with “calming” elements in the Swift language. You know, these are those sticky things, like a spinner or bubble wrap that you pop.

The framework chosen was SwiftUI. It was possible to complete the task in a shorter time, but I did not at all think that I would encounter some problems.

We all know the function Image, which we can easily use in regular projects. So here she is doesn't work in Swift Package… well, or rather how it doesn’t work, you need to plunge into Limbo, save your comrade and return through four emissions, and it’s not a fact that you woke up or the pictures can be connected…

* If this thing falls, then you have successfully connected the pictures 🙂

** Good idea for another UI element :))

The problem is that the Swift Package is missing a resource folder (the Assets folder we are used to). Accordingly, when using the Image function or other functions that pull data from resources, we will not receive anything.

Solution

  1. Create a Resources folder in a subdirectory of the Sources directory. I placed it in a folder at Sources/FidgetUIElements.

  1. You have a Package file, there you need to write the path to this folder, indicating that it is a resource folder. This is done in the field targets in the following way:

    targets: [
        .target(
            name: "FidgetUIElements",
            dependencies: [],
            resources: [.process("Resources")]),
        // other tergets
    ]
  1. Next, you need to extend the Image function by redirecting the resource search path to your new folder. Here is the code for such an extension:

import SwiftUI

extension Image {
    // Наше расширение будет принимать имя файла и его тип
    init(packageResource name: String, ofType type: String) {
        guard let path = Bundle.module.path(forResource: name, ofType: type),
              let image = UIImage(contentsOfFile: path) else {
            self.init(name)
            return
        }
        self.init(uiImage: image)
    }
}
  1. Also, if you need to connect pictures, you can use the following function:

import Foundation

import AVFoundation

var player: AVAudioPlayer?

func playSound(_ soundName: String) {
    guard let url = Bundle.module.url(forResource: soundName, withExtension: "mp3") else {
        print("URL is wrong")
        return
    }
    do {
        player = try AVAudioPlayer(contentsOf: url)
        guard let player = player else { print("URL is wrong 2"); return }

        player.prepareToPlay()
        player.play()

    } catch {
        print(error.localizedDescription)
    }
}
  1. Now, when adding sounds or images to the Resources folder, you can safely pass the name of these components to your functions. In the Resources folder you can create subdirectories and put your files there, it doesn’t matter, the functions will still find your files if you specified the names correctly.

I still don’t see the pictures/hear the sounds.

We say hello to our beloved XCode and go clean out the cache folder. I don’t know how anyone did it, but I had to do this every time I added another item to the Resources folder, because… it didn't show up.

For this:

  1. We close the project.

  2. Opening Finder.

  3. Click on the top menu Go –> Go to folder…

  4. Next we drive in /Users/{your username}/Library/developer/xcode/derivedData.

  5. The folder with the cache will open, delete everything from there, open the project again and VOILA.


That's all for me, I hope it was useful and the top fell after all. Good luck and good mood!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *