Swift Package Manager (SwiftPM) を使ってみよう　~作成編~

Xcode11からiOSアプリ開発にも使えるようになり、先日リリースされたXcode12ではかなり使いやすくなったSwiftPackageManager（以下、SwiftPM）について、プロジェクトへの導入方法とSwiftPMへ自作ライブリを作成方法のうち、この記事は自作ライブラリ作成方法になります。

↓導入方法はこちら
* [Swift Package Manager (SwiftPM) を使ってみよう　~導入編~](https://qiita.com/gurensouen/items/f24d868bc6f3be2a3134)

##ライブラリ作成方法　

###導入環境
- Xcode12

###SwiftPM起動

[ Xcode起動 ] → [ File ] → [ New ] → [ Swift Packages ]

![スクリーンショット 2020-10-12 9.35.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246668/cacc159a-c281-9eea-2672-e70eadcbc753.png)

[ プロジェクト名 ] → [ Cleate ] 

![スクリーンショット 2020-10-12 9.36.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246668/11afaf28-d761-e2d9-6a54-5bbefa6e07ba.png)

作成された画面
今回はあくまで自作ライブラリの登録までなので、

- Package.swift
- MyLibrary.swift

しか、触れません。（本当だったら、テストも書いた方がいいです。）

![スクリーンショット 2020-10-12 9.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246668/b87e8b7a-a191-ff50-9950-5c2da12ec3a7.png)

Package.swiftに、読み込みたい対象のファイルや外部ライブラリのURLを記載します。
今回は、外部ライブラリでNukeを読み込み、UIImageをExtensionして、UIImage側でNukeのLoadを行ったものを作ります。


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

import PackageDescription

let package = Package(
    name: "MyLibrary",
    platforms:[.iOS(.v11)],   // 使用するプラットフォーム（今回はiOS11以上）
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibrary"]),
    ],
    dependencies: [
        .package(url: "https://github.com/kean/Nuke.git", from: "9.1.2")    // 読み込みたい外部ライブラリ


    ],
    targets: [
depends on.
        .target(
            name: "MyLibrary",
            dependencies: [
                .product(name: "Nuke", package: "Nuke")    // 読み込んだライブラリを使用する
            ]),
        .testTarget(
            name: "MyLibraryTests",
            dependencies: ["MyLibrary"]),
    ]
)
```

これで、ライブラリの使用するまでは完了。

```swift:MyLibrary.swift
import UIKit
import Nuke

public enum ProcessorsOption {
    case resize
    case resizeRound(radius: CGFloat)
    case resizeCircle
}

public typealias AspectMode = ImageProcessors.Resize.ContentMode

public extension UIImageView {
    
    func loadUrl(imageUrl: String?,
                 processorOption: ProcessorsOption = ProcessorsOption.resize,
                 aspectMode: AspectMode = .aspectFill,
                 crop: Bool = false,
                 placeHolder: UIImage? = nil,
                 failureImage: UIImage? = nil,
                 contentMode: UIView.ContentMode? = nil) {
        guard let url: String = imageUrl,
            let loadUrl: URL = URL(string: url) else {
            self.image = failureImage
            return
        }
        
        let resizeProcessor = ImageProcessors.Resize(size: self.bounds.size,
                                                     contentMode: aspectMode, crop: crop)
        let processors: [ImageProcessing]
        
        switch processorOption {
        case .resize:
            processors = [resizeProcessor]
        case .resizeRound(let radius):
            processors = [resizeProcessor, ImageProcessors.RoundedCorners(radius: radius)]
        case .resizeCircle:
            processors = [resizeProcessor, ImageProcessors.Circle()]
        }
        
        let request = ImageRequest(
            url: loadUrl,
            processors: processors
        )
        var contentModes: ImageLoadingOptions.ContentModes?
        
        if let mode = contentMode {
            contentModes = ImageLoadingOptions.ContentModes.init(success: mode,
                                                                 failure: mode, placeholder: mode)
        }
        let loadingOptions = ImageLoadingOptions(placeholder: placeHolder,
                                                 failureImage: failureImage, contentModes: contentModes)
        
        Nuke.loadImage(with: request, options: loadingOptions, into: self)
    }
}
```
ライブラリに内容は割愛させてもらいます。
（Nukeの画像ロードとリサイズを行ってくれるものをExtensionにしてみました。）

このままでは、**No such module 'UIKit'**が出ており、ビルドできません。

[ Tests ]　→　[ MyLibraryTests ]　→　[ MyLibraryTests.swift ]の中身を変更
![スクリーンショット 2020-10-12 16.19.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246668/0941eb0e-ee60-8510-076a-33eadb9aeff5.png)

ビルドを「MyMac」から「Any Any iOS Device」へ変更

![スクリーンショット 2020-10-12 16.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246668/daa65854-1de1-8021-e461-b65820469c7e.png)

ビルドが成功すれば完成です。

最後に作成したものをGitコマンドやソースツリーを使い、CommitしてTagを付与し、githubにPushすれば完了です。
↑こちらについては、

- https://tyoshikawa1106.hatenablog.com/entry/2016/05/16/230237
- https://backlog.com/ja/git-tutorial/stepup/17/

を、参照してください。
＊Tagは[1.0.0]のようにしないとエラーになります。

全体配布を考えられるなら、ライセンスをつけることをお勧めします。
githubでライセンスをつける方法は

- https://qiita.com/shibukk/items/67ad0a5eda5a94e5c032

を参照ください。

ちなみに、今回作成したものをgithubに公開しています。
よかったらStarでもつけて使ってみてください。

####github
https://github.com/isamiodagiri/ExtendedImageViewWithNuke

↓導入方法はこちらになります。

* [Swift Package Manager (SwiftPM) を使ってみよう　~導入編~](https://qiita.com/gurensouen/items/f24d868bc6f3be2a3134)

###参考
- https://qiita.com/am10/items/72dbc511efc512fc065a

###協力
自作ライブラリをSwiftPMに登録する方法で、外部ライブラリを導入する方法だけが参考だけでは分からず、「**[アプリ道場サロン](https://community.camp-fire.jp/projects/view/281055)**」の方々にも協力していただきました。
ありがとうございました。