[Swift] Swift Package Manager

Written by じび on 8月 1st, 2018

Swift Package Manager とは、Apple純正のSwift用ライブラリ管理ツールです。
CocoaPodsやCarthageみたいなものですね。
Swift3から使用できるそうなので、試して見ました。

ライブラリの作り方

まずは取り込まれるライブラリ側の作り方です。
コマンドラインにて、フォルダを作り、ライブラリ用に初期化します。
$ mkdir Increment
$ cd Increment
$ swift package init
Creating library package: Increment
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/Increment/Increment.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/IncrementTests/
Creating Tests/IncrementTests/IncrementTests.swift
Creating Tests/IncrementTests/XCTestManifests.swift
$

このままコマンドラインで開発を続けることもできるのですが、Xcode Projectを作って、Xcode上で開発できるようにしてみましょう。

$ swift package generate-xcodeproj
generated: ./Increment.xcodeproj
$

以下のようにするとコマンドライからXcodeで開けます。
$ open Increment.xcodeproj
$

デフォルトで Sources/Increment/Increment.swift が作成されているので、書き換えます。
今回はInt型にincrementメソッドを追加してみました。

extension Int {
    public var increment: Int {
        return self + 1
    }
}

テストコード(Tests/IncrementTests/IncrementTests.swift)も書きましょう。

import XCTest
@testable import Increment

final class IncrementTests: XCTestCase {
    func testExample() {
        XCTAssertEqual(1.increment, 2)
    }

    static var allTests = [
        ("testExample", testExample),
    ]
}

書き換えた後はテストを実行して、ビルドおよびテストが通ることを確認してください。
コマンドライの場合は、以下の通りです。
$ swift test
Compile Swift Module 'Increment' (1 sources)
Compile Swift Module 'IncrementTests' (2 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/IncrementPackageTests.xctest/Contents/MacOS/IncrementPackageTests
Test Suite 'All tests' started at 2018-08-01 08:08:00.046
Test Suite 'IncrementPackageTests.xctest' started at 2018-08-01 08:08:00.047
Test Suite 'IncrementTests' started at 2018-08-01 08:08:00.047
Test Case '-[IncrementTests.IncrementTests testExample]' started.
Test Case '-[IncrementTests.IncrementTests testExample]' passed (0.206 seconds).
Test Suite 'IncrementTests' passed at 2018-08-01 08:08:00.253.
Executed 1 test, with 0 failures (0 unexpected) in 0.206 (0.207) seconds
Test Suite 'IncrementPackageTests.xctest' passed at 2018-08-01 08:08:00.254.
Executed 1 test, with 0 failures (0 unexpected) in 0.206 (0.207) seconds
Test Suite 'All tests' passed at 2018-08-01 08:08:00.254.
Executed 1 test, with 0 failures (0 unexpected) in 0.206 (0.207) seconds

最後にgitリポジトリを作って、’1.0.0’として登録しておきます。

$ git init
Initialized empty Git repository in /Users/hide/Documents/tmp/SoftwareDesign/sd201807/HelloWorldLibrary/.git/
$ git add .
$ git commit -am 'Version 1.0.0'
[master (root-commit) 7a9fdf6] Version 1.0.0
7 files changed, 70 insertions(+)
create mode 100644 .gitignore
create mode 100644 Package.swift
create mode 100644 README.md
create mode 100644 Sources/HelloWorldLibrary/HelloWorldLibrary.swift
create mode 100644 Tests/HelloWorldLibraryTests/HelloWorldLibraryTests.swift
create mode 100644 Tests/HelloWorldLibraryTests/XCTestManifests.swift
create mode 100644 Tests/LinuxMain.swift
$ git tag 1.0.0

アプリの作り方

続いて、ライブラリを使うアプリ側の作り方です。
初期化のオプションに –type=executable が付くのがライブラリとは異なります。

$ mkdir IncrementApp
$ cd IncrementApp
$ swift package init --type=executable
Creating executable package: HelloWorldApp
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/HelloWorldApp/main.swift
Creating Tests/
$

ここで Package.swift ファイルが作られているので、それを書き換えます。
デフォルトでは以下のようになっています。

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

import PackageDescription

let package = Package(
    name: "HelloWorldApp",
    dependencies: [
        // Dependencies declare other packages that this package depends on. 
        // .package(url: /* package url */, from: "1.0.0"),
    ],  
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "HelloWorldApp",
            dependencies: []),
    ]   
)

package.dependencies[]にIncrementへのパスとバージョンを記述します。
ここではローカルのパスを指定していますが、GitHubのリポジトリを指定することも可能です。

    dependencies: [
        // Dependencies declare other packages that this package depends on. 
        .package(url: "../Increment", from: "1.0.0"),
    ],  

package.targets[0].target.dependenciesにて、IncrementAppで使用するライブラリを記述します。

        .target(
            name: "IncrementApp",
            dependencies: ["Increment"]),

続いて、Sources/IncrementApp/main.swiftにアプリの実行コードを記述します。
1から10までの数値をインクリメントしたものを表示します。

import Increment

_ = (1...10).map { print($0.increment) }

これで完成です。
最後にアプリを実行して見ます。
$ swift run
Compile Swift Module 'IncrementApp' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/IncrementApp
2
3
4
5
6
7
8
9
10
11

参考

  • Software Designe 2018年7月号

 

[iOS] スワイプバックキャンセル時のライフサイクル

Written by じび on 6月 17th, 2018

iOSのUINavigationControllerにスワイプバックの機能がありますが、少しスワイプバックした時点で指を離してキャンセルした場合に、UIViewControllerのライフサイクルイベントがどのような順序で発生するか不明瞭だったので調べてみました。

使用したデバイスは iPhone 8 (iOS 11.3) です。

上から順番に時系列で並べてあります。
MasterViewControllerが親の画面、DetailViewControllerが子供の画面です。
DetailViewControllerが表示されている状態から始まり、スワイプバックでMasterViewControllerに戻ろうとしてキャンセルしています。

No. 操作 MasterViewController DetailViewController
1 少しスワイプ
2 viewWillDisappear
3 viewWillAppear
4 指を離す
5 viewWillDisappear
6 viewDidDisappear
7 viewWillAppear
8 viewDidAppear

画面表示時にデータを読み込んでいる場合は、

  • viewWillAppearで読み込み処理などを始めた場合は、viewWillDisappearまたはviewDidDisappearでキャンセルする。
  • viewWillAppearではなくviewDidAppearで開始する。

などの工夫が必要そうです。

 

HDDの破壊

Written by じび on 6月 10th, 2018

壊れたHDDが出て来たので、読み込み出来ないように破壊して捨てることにしました。

中のディスクの位置を確認し、電動ドリルで穴を開けます。
そのまま貫通させようとしたのですが、ガラス製のディクスに穴が開きません。
表面に傷はつくのですが、穴も開かなければ割れもしません。
結構、頑丈なのですね。

そこで空いた穴にセンターポンチを差し込んで、ハンマーで叩きました。
ディスクは中で粉々に割れ、破壊できました。

あとは中のガラス片がこぼれないように、ビニール袋で包んで燃えないゴミへ。

 

SUZUKI RGV250Γ

Written by じび on 6月 7th, 2018

 

持ち物

Written by じび on 6月 4th, 2018

普段、会社に行く時の持ち物を写してみました。
友達がやっていたので、面白そうだなと思ったので真似てみたのです。

こうして並べるためにカバンの中の物を全てだすと、無くても困らない物が結構入っていました。
たまにやるとカバンの中の整理になって良いですね。