[Swift / SPM] パッケージを自作して、アプリに取り入れる方法を簡単にまとめてみた

2023.03.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

CX事業本部の中安です。まいどです。

いくつかアプリを作っていると「この処理、前も書いたなー」とか「同じようなクラス作ったなー」などということがよくあり、 どうせ同じものを作るなら共通化したいなーと思ようになります。

そこで、いつも作るような処理をパッケージとしてまとめて、各アプリでSwift Package Manager的にライブラリ化を目指すことにしました。

今記事では、パッケージの作成からリリース、使用するまでの流れをまとめてみたいと思います。

準備

GitHubにリポジトリを作る

あまり詳しく説明は書きません。シンプルにGitHubにリポジトリを作るだけです。

Swift用の.gitignoreREADME.mdは最初から用意しておきます。(GitHub側で追加した状態でInitial Commitできます)

パッケージを作る

リポジトリができたらパッケージを実際に作る手順に入ります。 ターミナルで以下のような流れになります。

# パッケージを作りたいディレクトリに移動します
% cd (ディレクトリパス)

# 作ったGitHubのリポジトリをクローンします
% git clone git@github.com:(ユーザ名)/(リポジトリ名).git

# クローンされたらその中に入ります
% cd (リポジトリ名)

# Swift Package の初期化をします
% swift package init --type library --name (パッケージ名)

# Package.swiftを開くことでXcodeを起動します。
% open Package.swift

iOS用に色々といじる

Xcodeが開かれると上部の実行する環境が「My Mac」になってると思います。 このままだとUIKitなどのiOS用フレームワークを使おうとするとエラーになってしまうので、iPhoneシミュレータに変えてしまいます(種類はおそらく問わない)。

初期化時にSources/(パッケージ名)/(パッケージ名).swiftが作られていて、Xcodeで開くと下記のようなサンプルコードが書かれていると思います。

public struct (パッケージ名) {
    public private(set) var text = "Hello, World!"

    public init() {
    }
}

ここの先頭行に

import UIKit

を追加して、ビルドをしてみてUIKitについてエラーにならなければOKと思います。

プラットフォームを限定する

iOS用のパッケージとして特化するのであれば、プラットフォームを限定しておいた方がいいかもしれません。 ここを指定しておけば下位のiOSバージョンとの互換も考えずに済むと思います。

Package.swiftにハイライトした部分を書き加えます。

Package.swift

// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "(パッケージ名)",
    platforms: [
        .iOS(.v16)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "(パッケージ名)",
            targets: ["(パッケージ名)"]),
    ],
    dependencies: [
    :
    (以下略)

パッケージの中身を作る

ここからは中身を作成していくわけですが、ソースコードはSources/(パッケージ名)/以下にファイルを置いていき、Tests/(パッケージ名)Tests/以下にテストコードを書いていきます。

アクセス修飾子

作成したパッケージは、最終的にアプリ開発のターゲット外のものになりますので、アクセス修飾子をアプリ開発よりも意識しなければいけません。 ここではあらためてSwiftのアクセス修飾子について整理していきます。

  • open: 外部から呼び出すことができる。継承・オーバライドができる。
  • public: 外部から呼び出すことができる。継承・オーバライドはできない。
  • internal: 外部から呼び出すことができない。同一パッケージ内であれば呼び出せる。
  • fileprivate: 外部から呼び出すことができない。同一ファイル内であれば呼び出せる。
  • private: 外部から呼び出すことができない。同一クラス内であれば呼び出せる。

このように、アプリのプロダクトコードから呼び出せるのは、publicopenだけになります。

ちなみに何もアクセス修飾子が付いていなければ internal扱いです。 つまり外部からの呼び出しを前提にしたメソッドやプロパティはアクセス修飾子をつけてやる必要があります。

パッケージをリリースする

ソースコードがある程度できたら、mainブランチにプッシュします。

GitHubのリポジトリページの tagsページを開き、Create a new releaseボタンを押してリリース作成ページへと進みましょう。

まずはバージョン番号 (例: 0.1.0)を付したタグを作成し、そのバージョン番号をリリースタイトルにも入力します。 あとは、リリースノートなどを添えてから、Publish Releaseを押してやります。

リリースのバージョン番号があることで、パッケージを使用する側でバージョン指定することができます。

パッケージを使用する

今度はアプリ開発プロジェクト側の話になります。

プロジェクトの PROJECT > Package Dependencies からパッケージ一覧を開いて、+ボタンを押下します。

表示されるダイアログの検索窓 Search or Enter Package URL に、先ほど作ったパッケージリポジトリのGitHubのURLをコピー&ペーストします。

すると、作ったパッケージが出てくると思いますので、選択して Add Packageを押下します。

Xcode左ペインの Package Dependencies に自分の作ったパッケージが表示されたらOKです。

使用するソースコード上では

import (パッケージ名)

というふうにインポートしてあげる必要があります。

最後に

ここまでが、自作でパッケージを作り、実際にそれを使用するところまでのザックリした流れになります。

テストの実行など他にもやるべきことがありそうですが、今回は割愛させていただきました。

1つのUIクラスとして作ってもいいと思いますし、いくつかのクラスの集合体としても作ってもいいかもしれません。 便利なものを作れば、使いまわしたくなるのが人情。こういった方法を使うのもいいかもしれませんね。

何かの参考になれば幸いです。ではまたー