OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift] 値付き enum は CaseIterable をつけても allCases を自身で定義しなければならない件


# この記事で分かること

- 値付き enum で `CaseIterable` のプロトコルを適応させる場合、`allCases` を自身で定義しなければならない

# 具体例

## 例その1: CaseIterableの通常の使い方

```swift
enum Color: CaseIterable {
    case red, green, blue
}

Color.allCases.forEach {
    print($0)
}

// 出力
//
// red
// green
// blue
```

## 例その2: 値付きenumでCaseIterableを使う場合

以下のような値付き `enum` では `CaseIterable` とつけても `Type 'Trade' does not conform to protocol 'CaseIterable'` と怒られてしまいます。

```swift
enum Trade: CaseIterable { // Type 'Trade' does not conform to protocol 'CaseIterable'
    case buy(stock: String, amount: Int)
    case sell(stock: String, amount: Int)
}
```

そのため、以下のように `allCases` を自分で定義して、具体値を定義しなければなりません。

```swift
enum Trade: CaseIterable {
    // allCases を自分で定義しなければなない
    static var allCases: [Trade] {
        return [
            .buy(stock: "", amount: 0),
            .sell(stock: "", amount: 0)
        ]
    }
    
    case buy(stock: String, amount: Int)
    case sell(stock: String, amount: Int)
}

Trade.allCases.forEach {
    print($0)
}

// 出力
//
// buy(stock: "", amount: 0)
// sell(stock: "", amount: 0)
```


# 例その3: 値付きenumの「値」にenumを用いた場合

では、値付き `enum` の「値」を `CaseIterable` に適応した `enum` を用いた場合、どうなるのでしょうか？
「いい感じに察してくれないかな〜」と期待したいところですよね。

実際に試したところ、これもコンパイラに怒られてしまい、`allCases` を自分で定義しなければいけませんでした（泣）

無理やり書いてみると以下のようになりました。残念！！

```swift
enum FinancialProduct: CaseIterable {
    case stock
    case gold
    case crypto
}

enum Trade: CaseIterable {
    static var allCases: [Trade] {
        return [
            FinancialProduct.allCases.map { .buy(financialProduct: $0) },
            FinancialProduct.allCases.map { .sell(financialProduct: $0) },
        ].flatMap { $0 }
    }
        
    case buy(financialProduct: FinancialProduct)
    case sell(financialProduct: FinancialProduct)
}

Trade.allCases.forEach { trade -> () in
    switch trade {
    case let .buy(financialProduct):
        print("buy: \(financialProduct)")
    case let .sell(financialProduct):
        print("sell: \(financialProduct)")
    }
}

// 出力
//
// buy: stock
// buy: gold
// buy: crypto
// sell: stock
// sell: gold
// sell: crypto
```

# 結論

- 値付き `enum` で `CaseIterable` を使うのは注意が必要
[Swift] 空配列の allSatisfy と contains の判定には注意せよ


# 伝えたいこと

- 空配列に対する `allSatisfy` と `contains` の判定の違い
  - `allSatisfy`: 配列にひとつでも `false` があれば `false`
    - -> 空配列には `false` はないので `true`
  - `contains`: 配列にひとつでも `true` があれば `true`
    - -> 空配列には `true` はないので `false`
- `allSatisfy` と `contains` の使い分け
  - 『すべての値が `true` or `false` であるのか』を判定するなら -> `allSatisfy`
  - 『ひとつでも `true` or `false` があるのか』を判定するなら -> `contains`
- 教訓
  - 空配列の可能性があるものを `allSatisfy` や `contains` の処理をかける際は注意が必要である
  - 空配列の処理の混乱を避けるため `if [判定対象の配列].empty { return true or false }` で、先に処理を抜けさせるのも手である
  - `allSatisfy` や `contains` を使う際に `!` による否定は混乱の元なので、でできることなら避けた方がいい

## 空配列に対する `allSatisfy` と `contains` の判定の違い

以下のように、空配列に対する `allSatisfy` と `contains` の判定の結果は異なるので注意が必要になります。

```swift
[].allSatisfy { $0 } // true
[].contains { $0 } // false
```

この違いは、以下のような理解になります。

- `allSatisfy`: 配列にひとつでも `false` があれば `false`
  - -> 空配列には `false` はないので `true`
- `contains`: 配列にひとつでも `true` があれば `true`
  - -> 空配列には `true` はないので `false`

## `allSatisfy` や `contains` を使うときのポイント

つまるところ、`[判定対象の配列].allSatisfy { $0 }` と `![判定対象の配列].contains { !$0 }` は同値となります。（たぶん）

なので、`allSatisfy` や `contains` のどちらか片方だけで記述することは可能なのですが、`!` による否定を使うと混乱するので、どちらを使うか迷ったときは、以下のようなイメージを持つと良いと思います。

- 『すべての値が `true` or `false` であるのか』を判定するなら -> `allSatisfy`
- 『ひとつでも `true` or `false` があるのか』を判定するなら -> `contains`

また、`!` による否定系を使えばワンライナーで書けるケースも、`if [判定対象の配列].empty { return true or false }` で判定を早期リターンさせて、複数行で書いてあげた方が読みやすいコードになると個人的には思っています。

## 挙動の確認

以下は、playground で実験した際のサンプルコードです。
挙動を確認したいときにお試しください。

```swift
[true, false].allSatisfy { $0 } // false
[true, true].allSatisfy { $0 } // true
[false, false].allSatisfy { $0 } // false
[].allSatisfy { $0 } // true
```

```swift
[true, false].allSatisfy { !$0 } // false
[true, true].allSatisfy { !$0 } // false
[false, false].allSatisfy { !$0 } // true
[].allSatisfy { !$0 } // true
```

```swift
[true, false].contains { $0 } // true
[true, true].contains { $0 } // true
[false, false].contains { $0 } // false
[].contains { $0 } // false
```

```swift
[true, false].contains { !$0 } // true
[true, true].contains { !$0 } // false
[false, false].contains { !$0 } // true
[].contains { !$0 } // false
```

以上になります。
[git] gitignore.io から .gitignore ファイルを npx コマンドで生成する方法


# 動機

環境構築する際に [gitignore.io](https://www.toptal.com/developers/gitignore/) からコマンドラインからファイルが取得できれば楽だと思い、やり方を探したところ[公式ドキュメント](https://docs.gitignore.io/install/client-applications#node-tejas-kumar)にやり方が書いてありました。

そのまま紹介したいと思います。

# 環境

- Node.js 環境導入済

```shell
$ node -v
v19.7.0
```

```shell
$ npm -v
9.6.1
```

# コマンド実行

`npx add-gitignore` を実行するだけです。

```shell
$ npx add-gitignore
? What environments would your .gitignore to ignore?
❯◯ 1c
 ◯ 1c-bitrix
 ◯ a-frame
 ◯ actionscript
 ◯ ada
 ◯ adobe
 ◯ advancedinstaller
 ◯ adventuregamestudio
 ◯ agda
 ◯ al
```

コマンド実行後に、文字を入力すると検索ができるので、指定したい言語やフレームワークを十字キーでカーソルを合わせてスペースキーで選択ができます。

選択した状態で Enter キーを入力するとコマンドを実行した階層に `.gitignore` ファイルが生成されます。

# 余談

これをうまく組み込んで CI で自動更新できないかとも思ったのですが、`.gitignore` ファイルは自動更新するようなものではない気がするので、検討するのを辞めました。

以上です。
[Swift] 既に存在するファイルに対して上書きコピーできない件


# この記事で分かること

- 書き込む (`write` する) 際は既に存在するファイルに対して、上書きして書き込むことができる
- 既に存在するファイルに対して上書きコピーしようとすると失敗する
  - そのため、コピーの前には、ファイルが存在するかチェックしてから、コピー先のファイルを削除してあげるとよさそう


# 書き込み ( `write` ) の場合

## ファイルに書き込む方法

まず、基本的な挙動として、ファイルを書き込む方法は以下の通りです。

```swift
import Foundation

// 適当な文字列を用意
let text = "\(Date())"
print("text: \(text)") // text: 2021-12-26 00:48:11 +0000

// 保存先のディレクトリを用意
let dir = FileManager.default.urls(for: .documentDirectory,in: .userDomainMask).first!
print("dir: \(dir)") // dir: file:///Users/xxxxxxx/Documents/

// 適当なファイルを用意
let fileUrl1: URL = dir.appendingPathComponent("test_1.txt")
print("fileUrl1: \(fileUrl1)") // fileUrl1: file:///Users/xxxxxxx/Documents/test_1.txt

do {
    // ファイルにテキストに書き込む
    try text.write(to: fileUrl1, atomically: false, encoding: .utf8)
} catch {
    print("Error: \(error)")
}
```

これで、`fileUrl1` に `text` を書き込むことができます。

## 同じファイルに2回書き込んでも失敗しない

`write` については同じファイルに2回書き込んでも失敗することはありません。

```swift
do {
    // ファイルにテキストに書き込む
    try text.write(to: fileUrl1, atomically: false, encoding: .utf8)
    
    // 2回同じファイルに対してに書き込んでもエラーにならない
    try text.write(to: fileUrl1, atomically: false, encoding: .utf8)
} catch {
    print("Error: \(error)")
}
```

そして、後半に `write` した `text` の内容がファイルに上書きされます。

# コピー ( `copyItem` ) の場合

## コピーする方法

まず、基本的な挙動として、ファイルをコピーする方法は以下の通りです。

```swift
// 適当なファイルをもうひとつ用意
let fileUrl2: URL = dir.appendingPathComponent("test_2.txt")
print("fileUrl2: \(fileUrl2)") // fileUrl2: file:///Users/xxxxxxx/Documents/test_2.txt

do {
    try FileManager.default.copyItem(at: fileUrl1, to: fileUrl2) 
} catch {
    print("Error: \(error)")
}
```

これで、`fileUrl1` の内容が `fileUrl2` に内容がコピーされて、`fileUrl2` にファイルが新たに作成されます。

## 既にファイルが存在するとコピーに失敗する

`copyItem` については、既にファイルが存在場合はコピーに失敗します。

```swift
do {
    // 既にファイルが存在するとコピーに失敗する
    try FileManager.default.copyItem(at: fileUrl1, to: fileUrl2)
    try FileManager.default.copyItem(at: fileUrl1, to: fileUrl2)
} catch {
    print("Error: \(error)") // Error: Error Domain=NSCocoaErrorDomain Code=516 "“test_1.txt” couldn’t be copied to “Documents” because an item with the same name already exists."
}
```

# コピーの前にはチェック&削除が必要

そのため、コピーの前にはチェック&削除が必要になります。

```swift
do {
    // コピーの前にはチェック&削除が必要
    if FileManager.default.fileExists(atPath: fileUrl2.path) {
        // すでに fileUrl2 が存在する場合はファイルを削除する
        try FileManager.default.removeItem(at: fileUrl2)
    }
    try FileManager.default.copyItem(at: fileUrl1, to: fileUrl2) // fileUrl2 が存在しないこと保証されているのでエラーは発生しない
} catch {
    print("Error: \(error)")
}
```

これで安全にコピーできます。

# 結論

- 書き込む (`write` する) 際は既に存在するファイルに対して、上書きして書き込むことができる
- 既に存在するファイルに対して上書きコピーしようとすると失敗する
  - そのため、コピーの前には、ファイルが存在するかチェックしてから、コピー先のファイルを削除してあげるとよさそう
[Swift] struct は weak self は必要ない（できない）件


# 伝えたいこと

- struct は `weak self` は必要ない（できない）

# 実験

以下のような適当な closure をもつ class を定義します。

```swift
struct Calculator {
    let numA: Double
    let numB: Double
    let closure: (Double, Double) -> Void
    
    init(numA: Double, numB: Double, closure: @escaping (Double, Double) -> Void) {
        self.numA = numA
        self.numB = numB
        self.closure = closure
    }
    
    func calc() {
        closure(numA, numB)
    }
}
```

上記の closure の処理内で struct に内包される自信の `taxRate` を使うような処理を記述させてみます。

```swift
struct SampleStruct {
    private let taxRate = 1.1
    let numA: Double
    let numB: Double
    
    init(numA: Double, numB: Double) {
        self.numA = numA
        self.numB = numB
    }
    
    // ⭕️ これはできる
    func getCalculator() -> Calculator {
        Calculator(numA: numA, numB: numB) { numA, numB in
            print("\((numA + numB) * self.taxRate)")
        }
    }
}
```

closure の処理で `self` が用いられているので、いつもの癖で `[weak self]` を記述すると怒られてしまいます。

```swift
struct SampleStruct {
    private let taxRate = 1.1
    let numA: Double
    let numB: Double
    
    init(numA: Double, numB: Double) {
        self.numA = numA
        self.numB = numB
    }
    
    // ❌ これはできない
    func getCalculator() -> Calculator {
        Calculator(numA: numA, numB: numB) { [weak self] numA, numB in // 'weak' may only be applied to class and class-bound protocol types, not 'SampleStruct'
            guard let self = self else {
                print("self is nil")
                return
            }
            print("\((numA + numB) * self.taxRate)")
        }
    }
}
```

エラーメッセージを見てみます。

エラーメッセージ↓

> 'weak' may only be applied to class and class-bound protocol types

Deepl翻訳↓ 

> 'weak' は、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できる

どうやら、 'weak' は struct では使えないみたいです。

strcut は値型であり、class のように参照型ではないため、当たり前と言ったら当たり前になります。

以上になります。
[Swift] タプルのアクセス方法あれこれ


# タプルのアクセス方法あれこれ

以下はすべて同じ挙動になります。

```swift
let nums: [Int] = [1,2,3]

zip(nums, nums.dropFirst()).map {
    print("パターンA: \($0),\($1)")
}
// パターンA: 1,2
// パターンA: 2,3

zip(nums, nums.dropFirst()).map {
    print("パターンB: \($0.0),\($0.1)")
}
// パターンB: 1,2
// パターンB: 2,3

zip(nums, nums.dropFirst()).map { hoge in
    print("パターンC: \(hoge.0),\(hoge.1)")
}
// パターンC: 1,2
// パターンC: 2,3

zip(nums, nums.dropFirst()).map { hoge, moge in
    print("パターンD: \(hoge),\(moge)")
}
// パターンD: 1,2
// パターンD: 2,3

zip(nums, nums.dropFirst()).map { (hoge, moge) in
    print("パターンE: \(hoge),\(moge)")
}
// パターンE: 1,2
// パターンE: 2,3
```

個人的には `パターン A` か`パターン D` がおすすめです。

以上になります。
[Swift] Double の min(), max() で Double.nan を扱うときは順番に注意せよ


# 結論

以下のように、`min()` や `max()` で評価するときに先頭に `Double.nan` があると、必ず `Double.nan` が抽出されてしまいます。

```swift
let hoge: Double = min(Double.nan, 0.0, -1.0)
print("hoge: \(hoge)") // hoge: nan

let moge: Double = min(0.0, Double.nan, -1.0)
print("moge: \(moge)") // moge: -1.0

let huga: Double = max(Double.nan, 0.0, 1.0)
print("huga: \(huga)") // huga: nan

let piyo: Double = max(0.0, Double.nan, 1.0)
print("piyo: \(piyo)") // piyo: 1.0
```

なので、先頭に `Double.nan` をとりうる計算結果などは、入れないように注意しましょう。
[Swift] 『private extension 内の func』と『extension 内の private func』の差の確認


# はじめに

『private extension 内の func』と『extension 内の private func』の挙動の差を確認するための記事になります。

# 問題

問題です。

以下のような class が定義されているとします。

```swift
class Hoge {
    func hogehoge() {
        print("hogehoge")
    }
    
    private func mogemoge() {
        print("mogemoge")
    }
}

private extension Hoge {
    func hugahuga() {
        print("hugahuga")
    }
}

extension Hoge {
    private func piyopiyo() {
        print("piyopiyo")
    }
}
```

## 問題(1): 「class Hoge」の定義と同じファイル内の場合

「class Hoge」の定義と同じファイル内で Hoge クラスの各関数を実行しようとした場合、コンパイルエラーとなるのは、以下の内どれでしょうか？

```swift
// 「class Hoge」の定義と同じファイル内
class Moge {
    init() {
        let hoge = Hoge()
        hoge.hogehoge()
        hoge.mogemoge()
        hoge.hugahuga()
        hoge.piyopiyo()
    }
}
```

## 問題(2): 「class Hoge」の定義と別ファイルの場合

「class Hoge」の定義と別のファイルで Hoge クラスの各関数を実行しようとした場合、コンパイルエラーとなるのは、以下の内どれでしょうか？

```swift
// 「class Hoge」の定義と別ファイル
class Fuga {
    init() {
        let hoge = Hoge()
        hoge.hogehoge()
        hoge.mogemoge()
        hoge.hugahuga()
        hoge.piyopiyo()
    }
}
```

# 答え

## 問題(1): 「class Hoge」の定義と同じファイル内の場合

```swift
// 「class Hoge」の定義と同じファイル内
class Moge {
    init() {
        let hoge = Hoge()
        hoge.hogehoge() // ← OK 🌟
        hoge.mogemoge() // ← コンパイルエラー 🌀
        hoge.hugahuga() // ← OK 🌟
        hoge.piyopiyo() // ← コンパイルエラー 🌀
    }
}
```

`private extension` は同じファイル内にいる場合はアクセス可能なので、`hugahuga()` は実行できます。

## 問題(2): 「class Hoge」の定義と別ファイルの場合

```swift
// 「class Hoge」の定義と別ファイル
class Fuga {
    init() {
        let hoge = Hoge()
        hoge.hogehoge() // ← OK 🌟
        hoge.mogemoge() // ← コンパイルエラー 🌀
        hoge.hugahuga() // ← コンパイルエラー 🌀
        hoge.piyopiyo() // ← コンパイルエラー 🌀
    }
}
```

先ほどと違い、別ファイルにいるため、`hugahuga()` を実行しようとするとコンパイルエラーとなります。

以上になります。
[Swift] Swift でも clamp() したい！


# Swift で clamp() 

`c++` には `min <= x <= max` の範囲で `x` の値を返却してくる [`clamp()`](https://cpprefjp.github.io/reference/algorithm/clamp.html) という関数があるので、それの Swift 版の紹介です。

```swift
extension Comparable {
    func clamp(minValue: Self, maxValue: Self) -> Self {
        min(max(minValue, self), maxValue)
    }
    
    func clamp(to range: ClosedRange<Self>) -> Self {
        self.clamp(minValue: range.lowerBound, maxValue: range.upperBound)
    }
}
```

正直、似たような記事はいくつもあったのですが、`Comparable` の拡張なら `ClosedRange` を用いて、表現できるとより綺麗かなと思い、投稿しました。

# 実際に使ってみた

使い方は以下のようになります。

```swift
let minValue: Int = 0
let maxValue: Int = 2
let range: ClosedRange<Int> = minValue...maxValue

print((-1).clamp(minValue: minValue, maxValue: maxValue)) // 0
print(0.clamp(minValue: minValue, maxValue: maxValue)) // 0
print(1.clamp(minValue: minValue, maxValue: maxValue)) // 1
print(2.clamp(minValue: minValue, maxValue: maxValue)) // 2
print(3.clamp(minValue: minValue, maxValue: maxValue)) // 2

print((-1).clamp(to: range)) // 0
print(0.clamp(to: range)) // 0
print(1.clamp(to: range)) // 1
print(2.clamp(to: range)) // 2
print(3.clamp(to: range)) // 2
```

以上になります。
[Swift] [Combine] 配列を引数にとる関数の戻り値が AnyPublisher であるときのインターフェースの検討


# 伝えたいこと

- 配列を引数にとる関数の戻り値が AnyPublisher の場合のインターフェースの場合は以下のことに注意する
  - **Input と Output の紐付けが必要な場合は、順序による暗黙的な紐付けを行わないようにすること**
  - Input と Output の型は統一性があったほうが自然だということ
  - Output を **単体** or **配列** で迷った場合は、**より汎用的な 単体 を用いて**、 Output をまとめて処理したい場合は、**subscribe 側で `collect()` すること**

# はじめに

Combine の特性上、配列処理との相性がとても良いです。

今回は、配列を引数にとる関数の戻り値が AnyPublisher の場合のインターフェースの検討をおこなっていきます。

# やりたいこと

具体例があると想像しやすいので、以下の定義されているときに、『複数の写真のサムネイルに取得して、それを Realm などのデータストアに永続化する処理』をやりたいとして、それを例に検討します。


```swift
import Combine
import Foundation

private var cancellables: Set<AnyCancellable> = []

// PhotoEntity
struct PhotoEntity: Identifiable {
    /// id
    let id: String
    /// サムネイルのURL(サムネイルの未取得の場合は nil)
    var thumbnail: URL?
}

// サムネイルの未取得の PhotoEntity の配列
let photos: [PhotoEntity] = [.init(id: UUID().uuidString), .init(id: UUID().uuidString)]

// サムネイルのfetch処理
func fetchThumbnail(photoId: String) -> URL {
    URL(string: photoId)!
}

// 保存処理（単体版）
func store(photo: PhotoEntity) {
    // Realm などへのデータストアへの保存処理...
    print("PhotoEntityの保存に成功しました！ id: \(photo.id), thumbnail: \(String(describing: photo.thumbnail))")
}

// 保存処理（複数版）
func store(photos: [PhotoEntity]) {
    photos.forEach { store(photo: $0) }
}
```

前提条件は以下になります。

- サムネイルの未取得の `PhotoEntity` の配列がある
- サムネイルの URL の fetch 処理には `PhotoEntity` の `id` が必要
- Realm などへのデータストアへの保存処理の `store()` は単体でも複数でも保存が可能である
- サムネイル取得処理は AnyPublisher 型で返却され、それを subscribe した Output を `store()` していくという実装方針

# インターフェースの案

AnyPublisher を返却する関数の案として、以下の A 〜 F までの 6 つの案を考えたとき、どれが良いかを検討します。

```swift
protocol PhotoDownloadDriverProtocol {
    // 案 A
    func fetchThumbnailA(photoIds: [String]) -> AnyPublisher<[URL], Never>
    
    // 案 B
    func fetchThumbnailB(photoIds: [String]) -> AnyPublisher<URL, Never>
    
    // 案 C
    func fetchThumbnailC(photoIds: [String]) -> AnyPublisher<(photoId: String, thumbnailURL: URL), Never>
    
    // 案 D
    func fetchThumbnailD(photoIds: [String]) -> AnyPublisher<PhotoEntity, Never>
    
    // 案 E
    func fetchThumbnailE(photos: [PhotoEntity]) -> AnyPublisher<PhotoEntity, Never>
    
    // 案 F
    func fetchThumbnailF(photos: [PhotoEntity]) -> AnyPublisher<[PhotoEntity], Never>
}
```

A 〜 F までの 6 つの案の違いを表でまとめると以下になります。

| 案 | Input                    | Output                                 |
[Swift] [Combine] measureInterval(using:)を使って出力の間隔を取得する


# `measureInterval(using:) `

Combine には [`measureInterval(using:)`](https://developer.apple.com/documentation/combine/fail/measureinterval(using:options:)) という Publisher の出力の間隔を取得することができる関数が用意されているのでそれを紹介してみたいと思います。

## サンプルコード

挙動はサンプルコードを見ていただくのが早いと思います。

まずは以下のような一定間隔で出力してくれる Publisher を用意します。

```swift
import Combine
import Foundation

var cancellables = Set<AnyCancellable>()
let timerPublisher = Timer.publish(every: 2, on: .main, in: .default)
    .autoconnect()
    .share()
```

適当に subscribe すると以下のような出力になります。

```swift
timerPublisher
    .sink { output in
        print("timerPublisher: \(output)")
    }
    .store(in: &cancellables)

// timerPublisher: 2022-02-05 11:14:17 +0000
// timerPublisher: 2022-02-05 11:14:19 +0000
// timerPublisher: 2022-02-05 11:14:21 +0000
```

ここで、[`measureInterval(using:)`](https://developer.apple.com/documentation/combine/fail/measureinterval(using:options:)) を間に噛ませると以下のようになります。

```swift
timerPublisher
    .measureInterval(using: RunLoop.main)
    .sink { output in
        print("measureInterval: \(output)")
    }
    .store(in: &cancellables)

// measureInterval: Stride(magnitude: 2.0009289979934692)
// measureInterval: Stride(magnitude: 1.9993009567260742)
// measureInterval: Stride(magnitude: 1.9998070001602173)
```

[`measureInterval(using:)`](https://developer.apple.com/documentation/combine/fail/measureinterval(using:options:)) を間に噛ませることで、`時刻` から `時間間隔` に変更されていることがわかります。


```swift
timerPublisher
    .measureInterval(using: RunLoop.main)
    .sink { output in
        print("measureInterval: \(output)")
    }
    .store(in: &cancellables)

// measureInterval: Stride(magnitude: 0.20106804370880127)
// measureInterval: Stride(magnitude: 0.1994309425354004)
// measureInterval: Stride(magnitude: 0.19979500770568848)

```

さらに [`collect()`](https://developer.apple.com/documentation/combine/fail/collect(_:)) を間に噛ませて、ちょっとした関数を当ててあげるだけで、出力の間隔の平均を表すこともできます。

```swift
func averageInterval(strides: [RunLoop.SchedulerTimeType.Stride]) -> Double {
    let sum = strides.map { $0.timeInterval }.reduce(0, +)
    return Double(sum) / Double(intervalValues.count)
}

timerPublisher
    .measureInterval(using: RunLoop.main)
    .collect(10)
    .map { averageInterval(strides: $0) }
    .sink { output in
        print("output average interval(s): \(output)")
    }
    .store(in: &cancellables)

// output average interval(s): 2.0000609040260313
```

以上になります。
[Swift] 辞書型あれこれ


# はじめに

基本的には辞書型は、クライアント側のコードでは `key` でのアクセスが `nil` の可能性を孕んだり、`value` や `key` に対して変数名を設定できないので、辞書型で宣言するよりも struct 型で宣言することがほとんどだと思います。

また、API レスポンスの型の都合上などで、辞書型を扱うことも `Codable` で定義することで、ほとんど必要なくなりました。

それでもたまに辞書型を使うとことがあるので、辞書型でよく使える技を書き残そうと思います。

# 伝えたいこと

- `key` も `value` も両方の値を使っていきたい -> 早めに Struct に変換する
- 辞書型を維持しなくても良いなら -> その段階で辞書型を変更 -> `.values` or `.keys`
- 辞書型を維持したまま処理するなら -> 辞書型を維持する処理 -> `.mapValues()`
- `.first(where: 条件)` は辞書型のまま使える

# `key` も `value` も両方の値を使っていきたい -> 早めに Struct に変換する

辞書型のままで良いですが、struct にして変数名を持たせることで、`key` と `value` に意味を持たせることができます。

```swift
let dict: [Int: String] = [1: "one", 2: "two" , 3: "three"]

struct Hoge {
    let id: Int
    let name: String
}

let hoges: [Hoge] = dict.map { key, value in Hoge(id: key, name: value) }
print(hoges) // [Hoge(id: 1, name: "one"), Hoge(id: 3, name: "three"), Hoge(id: 2, name: "two")]
```

※ ただし、順番は担保されないので注意が必要

# `key` だけや `value` だけの配列を生成する -> `.values` or `.keys`

```swift
let dict: [Int: String] = [1: "one", 2: "two" , 3: "three"]

print(dict.keys) // [1, 3, 2]
print(dict.values) // ["one", "three", "two"]

// 以下も同じ結果である
print(dict.map(\.key)) // [1, 3, 2]
print(dict.map(\.value)) // ["one", "three", "two"]
```

※ ただし、順番は担保されないので注意が必要

# `.mapValues()` で辞書型を維持したまま `value` だけ変換処理をする

```swift
let dict: [Int: String] = [1: "one", 2: "two" , 3: "three"]

print(dict.mapValues { $0.count }) // [1: 3, 2: 3, 3: 5]
```

`.values` or `.keys` や `.mapValues()` を使うことで通常の配列っぽく扱うことが可能ですが、以下のことを念頭に置くとよさそうです。

- 辞書型を維持したまま処理するなら -> 辞書型を維持する処理 -> `.mapValues()`
- 辞書型を維持しなくても良いなら -> その段階で辞書型を変更するとよさそう -> `.values` or `.keys`

# `.first(where: 条件)` は辞書型のまま使える

```swift
let dict: [Int: String] = [1: "one", 2: "two" , 3: "three"]

// 以下はすべて同じ結果である
print(dict[2]!) // two
print(dict.first(where: { $0.key == 2 })!.value) // two
print(dict.first(where: { $0.value == "two" })!.value) // two

// もちろん先にvalueに変換してもよし
print(dict.map(\.value).first(where: { $0 == "two" })!) // two
```

大体、配列と同じような処理をすることが辞書型でも可能みたいです。

以上です。
[Swift] [Combine] measureInterval(using:) の出力を Stride 型から秒単位に変換する


# `measureInterval(using:)` の出力は `Stride` 型

出力してみるとわかるのですが、 [`measureInterval(using:)`](https://developer.apple.com/documentation/combine/fail/measureinterval(using:options:)) の出力は `Stride` 型になります。

しかも、なぜか、`Scheduler` によって、若干単位が異なります。

```swift
import Combine
import Foundation

var cancellables = Set<AnyCancellable>()
let timerPublisher = Timer.publish(every: 2, on: .main, in: .default)
    .autoconnect()
    .share()

timerPublisher
    .measureInterval(using: DispatchQueue.global(qos: .default))
    .sink { print("DispatchQueue.global: \($0)") }
    .store(in: &cancellables)

timerPublisher
    .measureInterval(using: DispatchQueue.main)
    .sink { print("DispatchQueue.main: \($0)") }
    .store(in: &cancellables)

timerPublisher
    .measureInterval(using: RunLoop.main)
    .sink { print("RunLoop.main: \($0)") }
    .store(in: &cancellables)

// （出力）
// DispatchQueue.main: Stride(_nanoseconds: 2000724683)
// RunLoop.main: Stride(magnitude: 2.0008790493011475)
// DispatchQueue.global: Stride(_nanoseconds: 2001722113)
// DispatchQueue.main: Stride(_nanoseconds: 1999310387)
// RunLoop.main: Stride(magnitude: 1.9990659952163696)
// DispatchQueue.global: Stride(_nanoseconds: 1999024983)
```

`DispatchQueue` は「ナノ秒」で、`RunLoop` は「秒」単位ですね。


# `Stride` → `Double`(秒) に変換する

以下のような、extension を生やしました。

```swift
extension DispatchQueue.SchedulerTimeType.Stride {
    var seconds: Double {
        Double(self.magnitude) / 1_000_000_000
    }
}

extension RunLoop.SchedulerTimeType.Stride {
    var seconds: Double {
        Double(self.magnitude)
    }
}
```

`map()` を使って変換してみました。

```swift
timerPublisher
    .measureInterval(using: DispatchQueue.global(qos: .default))
    .map { $0.seconds }
    .sink { print("DispatchQueue.global: \($0)") }
    .store(in: &cancellables)

timerPublisher
    .measureInterval(using: DispatchQueue.main)
    .map { $0.seconds }
    .sink { print("DispatchQueue.main: \($0)") }
    .store(in: &cancellables)

timerPublisher
    .measureInterval(using: RunLoop.main)
    .map { $0.seconds }
    .sink { print("RunLoop.main: \($0)") }
    .store(in: &cancellables)

// （出力）
// DispatchQueue.global: 2.000364776
// DispatchQueue.main: 2.000371132
// RunLoop.main: 2.000351905822754
// DispatchQueue.global: 1.999870186
// DispatchQueue.main: 1.999699733
// RunLoop.main: 1.9996449947357178
```

全部、秒単位の `Double` で揃いました。

（もっと簡単な方法があれば教えていただきです🙇‍♂️）

以上になります。
[Swift] [Combine] ObservableObject でなくても @Published は使用できる件


# サンプルコード

**`@Published` と `ObservableObject` はセットで使うものだと誤解されがちですが、そうではありません。**

## ObservableObject をつけた場合

`ObservableObject` をつけると `@StateObject`、`@ObservedObject`、`@EnvironmentObject` のアノテーションをつけた変数で使用可能になります。

```swift
import SwiftUI

// ObservableObject をつける
class Hoge: ObservableObject {
    @Published private(set) var mogmoge: Int = 0
}

// コンパイルエラーにはならない🌟
class Piyo {
    @StateObject var hogeStateObject = Hoge()
    @ObservedObject var hogeObservedObject = Hoge()
    @EnvironmentObject var hogeEnvironmentObject: Hoge
}
```

また`@StateObject`、`@ObservedObject`、`@EnvironmentObject` を使用には `import SwiftUI` が必要となります。

**つまり、`ObservableObject` は `SwiftUI` での View の実装で使うものになります。**
（間違っておりましたらご指摘のほどお願いいたします🙇‍♂️）


## ObservableObject を外した場合

`ObservableObject` を外すと `@StateObject`、`@ObservedObject`、`@EnvironmentObject` のアノテーションをつけた変数で使用できなくなります。

```swift
import SwiftUI

// ObservableObject を外す
class Hoge {
    @Published private(set) var mogmoge: Int = 0
}

// コンパイルエラーとなる😭
class Piyo {
    @StateObject var hogeStateObject = Hoge() // Generic struct 'StateObject' requires that 'Hoge' conform to 'ObservableObject'
    @ObservedObject var hogeObservedObject = Hoge() // Generic struct 'ObservedObject' requires that 'Hoge' conform to 'ObservableObject'
    @EnvironmentObject var hogeEnvironmentObject: Hoge // Generic struct 'EnvironmentObject' requires that 'Hoge' conform to 'ObservableObject'
}
```

『`Generic struct 'StateObject' requires that 'Hoge' conform to 'ObservableObject'`』とこんな感じで怒られてしまいます。

# 結論

- **`ObservableObject` を適応した class でなくても `@Published` は使用できる**
- `ObservableObject` は `@StateObject`、`@ObservedObject`、`@EnvironmentObject` のアノテーションをつけた変数を使いたいときに使用する **= `SwiftUI` での View の実装で使用する**


以上になります。


# 続編

以下の記事でそんな `ObservableObject` ではない `@Published` の使い所について紹介しております。

- [[Swift] [Combine] ObservableObject ではない @Published の使い所](https://zenn.dev/ikuraikura/articles/2022-02-24-pub2)
[Swift] 割り算の商と余りの両方がほしい場合は quotientAndRemainder を使おう


# 伝えたいこと

- 割り算の商と余りの両方がほしい場合は `quotientAndRemainder` を使うと一発で両方が求められる

https://developer.apple.com/documentation/swift/int/quotientandremainder(dividingby:)

# `/` と `％` による商と余りの計算

`/` と `％` によって、以下のように割り算の商と余りの計算ができます。

```swift
let appleCount = 13
let friendCount = 4

// `/` と `％` による商と余りの計算
let quotient = appleCount / friendCount // 商: 3
let remainder = appleCount % friendCount // 余り: 1

print(quotient) // 3
print(remainder) // 1
```

# `quotientAndRemainder` による商と余りの計算

割り算の商と余りの両方がほしい場合は `quotientAndRemainder` を使うと一発で両方が求められます。

https://developer.apple.com/documentation/swift/int/quotientandremainder(dividingby:)

以下、サンプルコードです。

```swift
let appleCount = 13
let friendCount = 4

// `quotientAndRemainder` による商と余りの計算
let divisionResult = appleCount.quotientAndRemainder(dividingBy: friendCount)

// (quotient: 商, remainder: 余り) のタプルが返ってくる
print(divisionResult) // (quotient: 3, remainder: 1)

// もちろんこのようなアクセスも可能
print(divisionResult.quotient) // 3
print(divisionResult.remainder) // 1

// タプルのインデックスへのアクセスも可能
print(divisionResult.0) // 3
print(divisionResult.1) // 1
```

割り算の商と余りの両方使う場合はこちらを使うとよさそうですね。

以上になります。
[Swift] nil の意味を明確にする方法



# モチベーション

`nil` を乱暴に多用していると `nil` が表す意味が複数に膨れ上がってしまうため、何のために `nil` にしているかを変数から察することができないかと考えました。

# `nil` の意味を明確にする方法

以下のように `Optional` を拡張すると、変数名から `nil` の意味を明確にすることができます。

```swift
extension Optional {
    static var nilForDefault: Wrapped? {
        nil
    }

    static var nilForError: Wrapped? {
        nil
    }
}

// 使い方
var num: Int? = .nilForDefault
var str: String? = .nilForError
```

# 使い方（応用）

`where Wrapped == 型名` で型を絞り込んで、`nil` を定義することもできます。

```swift
extension Optional where Wrapped == Int {
    static var nilForXXXXX: Wrapped? {
        nil
    }
}

var num: Int? = .nilForDefault // nil
var str: String? = .nilForXXXXX // Type 'String' has no member 'nilForXXXXX'
```

# そもそも

`nilForError` などを使うことは間違っていて、Error を throw するように実装していない証拠かもしれません。

以上です。

## 補足（ダメな例）

### ダメな例 その1

以下ではうまくいきません。

```swift
enum Nil {
    static let forDefault: Optional<Any> = nil
}

var num: Int? = Nil.forDefault as! Int // expression failed to parse: error: op.playground:3:5: error: consecutive statements on a line must be separated by ';'
```

そもそも `Nil.forDefault` は `Optional<Any>` 型であり、`Optional<Int>` ではないので、`as!` or `as?` で型を判定しなければならなく、うまくいきません。

### ダメな例 その2

`Optional<Any>` でダメなら、型を指定すればよいという考え方です。

```swift
struct Nil {
    static let forDefault: Optional<Int> = nil
}

var num: Int? = Nil.forDefault // OK
var str: String? = Nil.forDefault // NG: Cannot convert value of type 'Optional<Int>' to specified type 'String?'
```

`as!` or `as?` でキャストする必要はなくなりましたが、すべての型において、いちいち定義しなければならないので、使い勝手が悪いです。

### ダメな例 その3

`static` で生やさない場合の例になります。

```swift
extension Optional {
    var nilForDefault: Wrapped? {
        nil
    }
}

var num: Int? = .nilForDefault // ← これはできない

// これならできるが、やりたいことではない
num = 0
num.nilForDefault // nil
```

一度インスタンスを生成しないと、使えません。
用途が異なります。

以上、補足でした。
[Swift] [Combine] throttle() で一定期間出力を無視する


# `throttle(for:scheduler:latest:)`

Combine には [`throttle(for:scheduler:latest:)`](https://developer.apple.com/documentation/combine/fail/throttle(for:scheduler:latest:)) という一定期間の出力を無視してくれる関数が用意されていたので、それを紹介したいと思います。

スロットルはもともと以下のようなものらしいので、イメージにぴったりですね。

> スロットルは、ガソリンエンジンなどの予混合燃焼機関では、エンジンへの吸気（空気あるいは混合気）の流入量を調整し、エンジンの出力を調節する弁である。

[出典: フリー百科事典『ウィキペディア（Wikipedia）』スロットル](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AD%E3%83%83%E3%83%88%E3%83%AB)


## サンプルコード

挙動は以下のサンプルコードを見ていただくのが早いと思います。

まずは以下のような一定間隔で出力してくれる Publisher を用意します。

```swift
import Combine
import Foundation

var cancellables = Set<AnyCancellable>()
let timerPublisher = Timer.publish(every: 2, on: .main, in: .default)
    .autoconnect()
    .share()
```

適当に subscribe すると以下のような出力になります。

```swift
timerPublisher
    .sink {
        print("output: \($0)")
    }
    .store(in: &cancellables)

//output: 2022-02-05 11:44:08 +0000
//output: 2022-02-05 11:44:10 +0000
//output: 2022-02-05 11:44:12 +0000
```

ここに [`throttle(for:scheduler:latest:)`](https://developer.apple.com/documentation/combine/fail/throttle(for:scheduler:latest:)) を間に噛ませていきます。

```swift
timerPublisher
    .throttle(for: .seconds(5), scheduler: DispatchQueue.main, latest: true)
    .sink {
        print("output: \($0)")
    }
    .store(in: &cancellables)

// output: 2022-02-05 12:15:18 +0000
// output: 2022-02-05 12:15:22 +0000
// output: 2022-02-05 12:15:28 +0000
```

出力からは分かりにくいのですが、出力が 5 秒間隔になって、流量がコントロールされていることがわかります。

使い所としては、ボタンの連打など、あまり連続で処理させたくないところで使ってあげるとよさそうです。

以上になります。
[Swift] 配列をペアに変換して処理する方法（zip, dropFirst 活用）


# 結論

[`zip()`](https://developer.apple.com/documentation/swift/1541125-zip) と[`dropFirst()`](https://developer.apple.com/documentation/swift/array/1688675-dropfirst) を使うとスマートにかけます。

```swift
let nums: [Int] = [1, 2, 3, 4]

zip(nums, nums.dropFirst()).forEach {
    print("$0: \($0), $1: \($1)")
}

// $0: 1, $1: 2
// $0: 2, $1: 3
// $0: 3, $1: 4
```

# 補足

[`zip()`](https://developer.apple.com/documentation/swift/1541125-zip) と[`dropFirst()`](https://developer.apple.com/documentation/swift/array/1688675-dropfirst) を使わずに書くと以下のようになります。

```swift
// 上記と同じ処理
zip([1, 2, 3, 4], [2, 3, 4]).forEach {
    print("$0: \($0), $1: \($1)")
}

// $0: 1, $1: 2
// $0: 2, $1: 3
// $0: 3, $1: 4
```

上記からわかるように、`zip()` を使うと値がセットで揃わない限り、組み合わせが生成されません。

つまり、配列の要素数からひとつ減った要素数を返します。

要素数を減らしたくなく、ペアの組み合わせに自由度をもたしたい場合は以下の記事が参考になると思います。

- [[Swift] 配列をペアに変換して処理する方法](https://zenn.dev/ikuraikura/articles/26567893ddbd3e14ee0b) 

以上です。
[Swift] [Combine] Publisher を flatMap() 内に隠蔽して直接 subscribe するのを避ける方法


# はじめに

以下の記事にもあるように、『Failure となる可能性がある Publisher を直接 subscribe している場合、一度でも Failure が発生すると、その時点で Completion となり、Output を受け付けなくなる』という挙動を示します。

- [[Swift] [Combine] エラーがあっても止まらないストリームを作りたい！](https://zenn.dev/ikuraikura/articles/2022-02-17-result)

その回避方法として、記事内では `flatMap() 内での tryMap() -> catch -> Empty の合わせ技` を紹介しているのですが、**そもそも外側にある Publisher を `flatMap()` 内に隠蔽する方法について、いくつかパターンがあるので、それを紹介する記事になります。**
[Swift] zip() を用いて配列操作した場合、ペアが揃っていないと処理が走らない件


# タイトル回収

以下のように、`words` と `numbers` の要素数が異なる場合など、ペアが揃っていない状態では、処理が走らないので注意が必要です。

```swift
let words = ["one", "two", "three"]
let numbers = [1, 2, 3, 4]

for (word, number) in zip(words, numbers) {
    print("\(word): \(number)")
}

// (出力)
// one: 1
// two: 2
// three: 3
↑
`4` は処理されない！！
```

以上です。
[Swift] [Combine] removeDuplicates で nil を含む場合の compactMap の位置について


# はじめに

`removeDuplicates` で `nil` を含む配列を扱うときの `compactMap` の位置による挙動の違いというかなりマニアックな記事になります。

# removeDuplicates の基本的な挙動

`removeDuplicates` の基本的な挙動は以下の通りです。

```swift
import Combine

let nums: [Int] = [0, 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 0]

let cancellable = nums.publisher
    .removeDuplicates()
    .sink {
        print("\($0)") // 0 1 2 3 4 0
    }
```

一つ前と連続してきた出力がきた場合に、その出力をなかったことにします。

# compactMap の位置による挙動の違い

`compactMap` の位置による挙動の違いは以下の通り。

```swift
import Combine

let nums: [Int?] = [0, nil, 0, nil, nil, 1, 2]

// removeDuplicates より先に compactMap する
let cancellableA = nums.publisher
    .compactMap { $0 } // [0, 0, 1, 2]
    .removeDuplicates() // [0, 1, 2]
    .sink {
        print("\($0)") // 0 1 2
    }

// removeDuplicates の後に compactMap する
let cancellableB = nums.publisher
    .removeDuplicates() // [0, nil, 0, nil, 1, 2]
    .compactMap { $0 } // [0, 0, 1, 2] 
    .sink {
        print("\($0)") // 0 0 1 2
    }
```

どちらが良いということではないですが、知っておかないと意図しない挙動が起こりかねないので、`compactMap` の位置には気をつけてましょう（戒め）
[Swift] rawValue を持つ enum には自動的にイニシャライザが定義される


# rawValue を持つ enum には自動的にイニシャライザが定義される

最近まで知りませんでした。
swift.org に普通に書いてありました。

> # Initializing from a Raw Value
> If you define an enumeration with a raw-value type, the enumeration automatically receives an initializer that takes a value of the raw value’s type (as a parameter called rawValue) and returns either an enumeration case or nil. You can use this initializer to try to create a new instance of the enumeration.

https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html


DeepL翻訳↓

> 生の値からの初期化
> 生の値の型を持つ列挙型を定義すると、列挙型は自動的に初期化子を受け取り、生の値の型の値（rawValueというパラメータ）を取り、列挙型のケースまたはnilを返します。このイニシャライザーを使って、列挙型の新しいインスタンスの作成を試みることができる。

# 実際に挙動を確認してみる

```swift
enum Drink: String {
    case coffee
    case tea
}

print(Drink(rawValue: "coffee") ?? "Undefined") // coffee
print(Drink(rawValue: "tea") ?? "Undefined") // tea
print(Drink(rawValue: "hoge") ?? "Undefined") // Undefined
```

自動的に以下のようなイニシャライザが定義されているみたいです。

```swift
enum Drink: String {
    case coffee
    case tea
    
    // これが自動的に記述される
    init?(rawValue: String) {
        switch rawValue {
        case Drink.coffee.rawValue:
            self = .coffee
        case Drink.tea.rawValue:
            self = .tea
        default:
            return nil
        }
    }
}
```


正直、大抵の場合は enum の定義を extension すれば済むことがほとんどだと思うので、使い所は限られてくると思います。

一致する rawValue がなければイニシャライザで `nil` が返却されることを考慮しなければならないので、その辺もすこし使いづらい印象です。

- 参考
  - [Enumerations - docs.swift.org](https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html)
  - [Initializer init(rawValue:)- Apple Developer Documentation](https://developer.apple.com/documentation/swift/rawrepresentable/init(rawvalue:))

以上です。
[Swift] [Combine] ストリームに reduce() 処理の途中経過を流したい場合 -> scan() を使おう！


# reduce() の復習

[`reduce()`](https://developer.apple.com/documentation/swift/array/2298686-reduce) は以下のように、配列の数値を合計するときなどで使用されます。

```swift
let sum = [1, 2, 3, 4].reduce(0) { $0 + $1 }
print("sum: \(sum)") // sum: 10

```

この計算の過程を Combine のストリームで出力として流したい時に [`scan()`](https://developer.apple.com/documentation/combine/fail/scan(_:_:)) を使うと簡単に書くことができます。

# scan() を使ってみる

[`scan()`](https://developer.apple.com/documentation/combine/fail/scan(_:_:)) の使い方は [`reduce()`](https://developer.apple.com/documentation/swift/array/2298686-reduce) の使い方とかなり似ています。

以下が例になります。

```swift
var cancellables = Set<AnyCancellable>()

[1, 2, 3, 4].publisher
    .scan(0) { $0 + $1 }
    .sink {
        print("result: \($0)")
    } receiveValue: {
        print("output: \($0)")
    }
    .store(in: &cancellables)

// 出力
// output: 1 ← 0 + 1
// output: 3 ← 1 + 2
// output: 6 ← 3 + 3
// output: 10 ← 6 + 4
// result: finished
```

他に例を挙げると以下のようなこともできます。

```swift
[1, 2, 3, 4].publisher
    .scan([]) { $0 + [$1] }
    .sink {
        print("result: \($0)")
    } receiveValue: {
        print("output: \($0)")
    }
    .store(in: &cancellables)

// 出力
// output: [1]
// output: [1, 2]
// output: [1, 2, 3]
// output: [1, 2, 3, 4]
// result: finished
```

以上になります。
[Swift] Computed Property でも例外を throw できる件


# サンプルコード

- Swift: 5.5.2

適当にサンプルコードを書いてみました。

```swift
enum HogeError: Error {
    case zeroError
}

var moge: Int = 0

var hoge: Int {
    get throws {
        guard moge != 0 else {
            throw HogeError.zeroError
        }
        return moge
    }
}
```

アクセスする際は `try` をつける以外は、いつも通りの要領です。

```swift
moge = 1
do {
    print("hoge: \(try hoge)") // hoge: 1
} catch {
    print("error: \(error)")
}

moge = 0
do {
    print("hoge: \(try hoge)")
} catch {
    print("error: \(error)") // error: zeroError
}
```

以上になります。
[Swift] struct は deinit を記述できない件


# 伝えたいこと

- struct は deinit を記述できない

# 実験

```swift
struct Hoge {
    let moge: Int
    
    deinit { // ❌ Deinitializers may only be declared within a class or actor
        print("deinit: \(type(of: self))")
    }
}
```

エラーメッセージ↓

> Deinitializers may only be declared within a class or actor

だそうです。知らなかった。。。

以上です。
[Swift] CustomStringConvertible の実装例


# CustomStringConvertible の実装例

`CustomStringConvertible` を適応させることで、出力するときに任意の文字列表現に変換できます。

```swift
import Foundation

struct CustomStringConvertibleHoge: CustomStringConvertible {
    let value: Int
    
    var description: String {
        "CustomStringConvertible を適応している場合: \(value)"
    }
}

struct NotCustomStringConvertibleHoge {
    let value: Int
    
    var description: String {
        "CustomStringConvertible を適応していない場合: \(value)"
    }
}

let customStringConvertibleHoge = CustomStringConvertibleHoge(value: 0)
let notCustomStringConvertibleHoge = NotCustomStringConvertibleHoge(value: 1)

print(customStringConvertibleHoge) // CustomStringConvertible を適応している場合: 0
print(notCustomStringConvertibleHoge) // NotCustomStringConvertibleHoge(value: 1)
```

以上です。
[Swift] Class と Struct の変数の didSet 挙動の違いについて


# 結論

- `Class` や `Struct` を持つ変数について、`didSet` を実装する時は、挙動が異なるので注意が必要

## 共通コード


以下のような、適当な `Class` と `Struct` を要します。

```swift
// 🏫 Class
class Moge {
    var mogemoge: Int = 0 {
        didSet {
            print("mogemoge: \(mogemoge)")
        }
    }
    
    init() {}
    
    func update(mogemoge: Int) {
        self.mogemoge = mogemoge
    }
}

// 🏗 Struct
struct Fuga {
    var fugafuga: Int = 0 {
        didSet {
            print("fugafuga: \(fugafuga)")
        }
    }
    
    // struct の場合 `mutating` をつけないとコンパイルエラー⚠️
    mutating func update(fugafuga: Int) {
        self.fugafuga = fugafuga
    }
}
```

上記の `Class` または `Struct` を変数にもつ `Class` をさらに用意します。

```Swift
class Hoge {
    // 🔢 Int の場合
    var hogehoge: Int = 0 {
        didSet {
            print("hogehoge: \(hogehoge)")
        }
    }
    
    // 🏫 Class の場合
    var moge: Moge = .init() {
        didSet {
            print("moge: \(moge), mogemoge: \(moge.mogemoge)")
        }
    }
    
    // 🏗 Struct の場合
    var fuga: Fuga = .init() {
        didSet {
            print("fuga: \(fuga), fugafuga: \(fuga.fugafuga)")
        }
    }
    
    init() {}
}

let hoge: Hoge = .init()
```

ここで、この `hoge` に対して、値の更新を走らせるとどうなるか実験してみます。

## 🔢 Int の場合

```swift:🔢 Int の場合
hoge.hogehoge = 1
// hogehoge: 1
```

当たり前の挙動になりました。

## 🏫 Class の場合

```swift:🏫 Class の場合
hoge.moge = Moge()
// moge: __lldb_expr_49.Moge, mogemoge: 0

hoge.moge.mogemoge = 2
// mogemoge: 2

hoge.moge.update(mogemoge: 3)
// mogemoge: 3
```

これもなんとなく想像の通りの結果だと思います。

## 🏗 Struct の場合

```swift:🏗 Struct の場合
hoge.fuga = Fuga()
// fuga: Fuga(fugafuga: 0), fugafuga: 0

hoge.fuga.fugafuga = 4
// fugafuga: 4
// fuga: Fuga(fugafuga: 4), fugafuga: 4 ← ❗️❗️

hoge.fuga.update(fugafuga: 5)
// fugafuga: 5
// fuga: Fuga(fugafuga: 5), fugafuga: 5 ← ❗️❗️
```

**`Struct` の持っている変数の変更を実施した場合、`Struct` の場合は、`Class` と違って、変更された変数の `didSet` に加えて、さらに、`hoge` が持っている `fuga` の `Struct` 自身の `didSet` も走っています。**

このように `Class` や `Struct` を持つ変数について、`didSet` を実装する時は、挙動が異なるので注意が必要です。

## 考察

このような挙動の差は、`Class` が参照型であり、`Struct` が値型であること原因であると考えられます。

また、似たような話として、`@Published` や `CurrentValueSubject` の挙動も `Class` と `Struct` で差があります。

- 参考
  - [値型と参照型 - Swiftの始め方](https://swift.codelly.dev/guide/%E6%A7%8B%E9%80%A0%E4%BD%93%E3%81%A8%E3%82%AF%E3%83%A9%E3%82%B9/%E5%80%A4%E5%9E%8B%E3%81%A8%E5%8F%82%E7%85%A7%E5%9E%8B.html)
  - [[Swift] [Combine] @Published な変数が Class と Struct では挙動が異なる件](https://zenn.dev/ikuraikura/articles/2022-02-26-pub4)


以上になります。
[Swift] 安全に割り算する Double の extension


# 安全に割り算する Double の extension

単純な実装ですが作成してみました。

```swift
extension Double {
    /// 分子が nan、分母が nan、または分母が 0 であっても安全に割り算を行う
    /// - Parameter divisor: 分母
    /// - Returns: 割り算の計算結果を返却する。ただし、分子が nan、分母が nan、または分母が 0 の場合は nil を返却する。
    func safeDivide(by divisor: Double) -> Double? {
        guard !divisor.isZero else {
            return nil
        }
        guard !divisor.isNaN else {
            return nil
        }
        guard !self.isNaN else {
            return nil
        }
        return self / divisor
    }
}
```

デフォルト値を引数で渡そうとも考えていたのですが、そうするよりも、この関数を使う側でデフォルト値は設定してあげた方がいいと思い、`nil` を返却するようにしました。

他にも `安全に◯◯する` 系の便利関数を作る場合は `nil` を返すのがよさそうですね。

# 挙動の確認

サンプルコードになります。

```swift
var a: Double = 0.0
var b: Double = 0.0

a = 0.0
b = 0.0
print("original: \(a) / \(b) = \(a / b)")
print("safeDivide: \(a) / \(b) = \(a.safeDivide(by: b) ?? 0.0)")
// original: 0.0 / 0.0 = -nan
// safeDivide: 0.0 / 0.0 = 0.0

a = 1.0
b = 1.0
print("original: \(a) / \(b) = \(a / b)")
print("safeDivide: \(a) / \(b) = \(a.safeDivide(by: b) ?? 0.0)")
// original: 1.0 / 1.0 = 1.0
// safeDivide: 1.0 / 1.0 = 1.0

a = 1.0
b = 0.0
print("original: \(a) / \(b) = \(a / b)")
print("safeDivide: \(a) / \(b) = \(a.safeDivide(by: b) ?? 0.0)")
// original: 1.0 / 0.0 = inf
// safeDivide: 1.0 / 0.0 = 0.0

a = Double.nan
b = 1.0
print("original: \(a) / \(b) = \(a / b)")
print("safeDivide: \(a) / \(b) = \(a.safeDivide(by: b) ?? 0.0)")
// original: nan / 1.0 = nan
// safeDivide: nan / 1.0 = 0.0

a = 1.0
b = Double.nan
print("original: \(a) / \(b) = \(a / b)")
print("safeDivide: \(a) / \(b) = \(a.safeDivide(by: b) ?? 0.0)")
// original: 1.0 / nan = nan
// safeDivide: 1.0 / nan = 0.0
```

通常時だと `0.0 / 0.0 = -nan` となるのは予測できませんよね。（ハマりました。。。）

以上になります。
[Swift] associatedtype の実装例


# associatedtype の実装例

まず、以下のような2つのプロトコル `MogeProtocol` と `FugaProtocol` を定義します。

```swift:protocol
protocol MogeProtocol {
    var mogemoge: String { get }
}

protocol FugaProtocol {
    var fugafuga: String { get }
}
```

次に、これらの2つのプロトコルを組み合わせて使用する新しいプロトコル `HogeProtocol` を定義します。この時、`associatedtype` を使用して、具体的な型を後から指定できるようにします。

```swift
protocol HogeProtocol {
    associatedtype MogeFugaType: MogeProtocol, FugaProtocol
    
    var mogeFuga: MogeFugaType { get }
    
    func piyopiyo(mogeFuga: MogeFugaType)
}
```

`Hoge` という構造体を定義し、`HogeProtocol` を採用させることで、具体的な型を指定します。

```swift:struct
// 複数のプロトコルを適応させる場合は & でつなぐ
struct Hoge<T: MogeProtocol & FugaProtocol>: HogeProtocol {
    typealias MogeFugaType = T
    
    let mogeFuga: MogeFugaType
    
    init(mogeFuga: MogeFugaType) {
        self.mogeFuga = mogeFuga
        print(mogeFuga)
    }
    
    func piyopiyo(mogeFuga: MogeFugaType) {
        print(mogeFuga)
    }
}
```

最後に、`MogeProtocol` と `FugaProtocol` を採用する構造体 `MogeFuga` を定義し、実際に`Hoge` で使用します。

```swift:
struct MogeFuga: MogeProtocol, FugaProtocol {
    let mogemoge: String
    let fugafuga: String
}

let hoge: Hoge<MogeFuga> = .init(mogeFuga: .init(mogemoge: "a", fugafuga: "b"))
// MogeFuga(mogemoge: "a", fugafuga: "b")

hoge.piyopiyo(mogeFuga: .init(mogemoge: "c", fugafuga: "d"))
// MogeFuga(mogemoge: "c", fugafuga: "d")
```

# まとめ

Swift の `associatedtype` は非常に強力な機能で、プロトコルの柔軟性を向上させます。具体的な型を指定せずにプロトコルを定義し、後からその型を具体的に指定することが可能です。これにより、より汎用的なコードを書くことができます。
[Swift] weak self しないと強参照で解放できないサンプルコード


# はじめに

`weak self` しないことによって、参照元が強参照のため、解放できないサンプルコードを作るのが難しかったので、メモの代わりにここに残します。

## 適当な closure を持つ struct を用意

```swift
struct Calculator {
    let numA: Double
    let numB: Double
    let closure: (Double, Double) -> Void
    
    init(numA: Double, numB: Double, closure: @escaping (Double, Double) -> Void) {
        self.numA = numA
        self.numB = numB
        self.closure = closure
    }
    
    func calc() {
        closure(numA, numB)
    }
}
```

## 強参照サンプルコード

```swift
class SampleStrongClass {
    private let taxRate = 1.1
    let numA: Double
    let numB: Double
    
    init(numA: Double, numB: Double) {
        self.numA = numA
        self.numB = numB
    }
    
    deinit {
        print("deinit: \(type(of: self))")
    }

    // 強参照なコード
    func getCalculator() -> Calculator {
        Calculator(numA: numA, numB: numB) { numA, numB in // ← `[weak self]` がないため強参照
            print("\((numA + numB) * (self.taxRate))")
        }
    }
}
```

## 弱参照サンプルコード

```swift
class SampleWeakClass {
    private let taxRate = 1.1
    let numA: Double
    let numB: Double
    
    init(numA: Double, numB: Double) {
        self.numA = numA
        self.numB = numB
    }
    
    deinit {
        print("deinit: \(type(of: self))")
    }
    
    // 弱参照なコード
    func getCalculator() -> Calculator {
        Calculator(numA: numA, numB: numB) { [weak self] numA, numB in // ← `[weak self]` をつける
            guard let self = self else {
                print("self is nil")
                return
            }
            print("\((numA + numB) * (self.taxRate))")
        }
    }
}
```

## 強参照と弱参照の比較

### 強参照の場合

```swift
// 初期化
var smapleStrongClass: SampleStrongClass? = .init(numA: 3, numB: 4)
var strongClassCalculator: Calculator? = smapleStrongClass?.getCalculator()

// クロージャーの実行
strongClassCalculator?.calc() // 7.700000000000001

// 参照元の class に nil を代入
smapleStrongClass = nil // （出力なし） ← deinit が走らない = メモリリーク

// クロージャーの実行
strongClassCalculator?.calc() // 7.700000000000001 ← 計算できてしまう
```

### 弱参照の場合

```swift
// 初期化
var smapleWeakClass: SampleWeakClass? = .init(numA: 5, numB: 6)
var weakClassCalculator: Calculator? = smapleWeakClass?.getCalculator()

// クロージャーの実行
weakClassCalculator?.calc() // 12.100000000000001

// 参照元の class に nil を代入
smapleWeakClass = nil // deinit: SampleWeakClass ← deinit が走る

// クロージャーの実行
weakClassCalculator?.calc() // self is nil ← 計算できない
```

以上になります。
Vue1系から3系にバージョンアップしたときの備忘録

# はじめに

これはVue1系で実装された社内向けツールをVue3系にバージョンアップした際の備忘録です。

以下の事柄を前提でこの記事は書かれています。
* Vue1系のみを触っていて、2系以降の知識がない状態でバージョンアップを実施した
* .vueファイルを用いた単一コンポーネントではなく、htmlファイルにjsを書くだけの形式で実装した
* Vue.jsの基本的な用語解説はない


# アプリケーションの作成方法が違う

vue1系
``` 
var app = new Vue({
    ...
});
```
vue3系
```
var app = createApp({
    ...
});
```

そもそも基幹となるアプリケーションの作成の記述方法が異なる。

作成済みのアプリケーションを継承したい場合の書き方は更に異なる。

vue1系
```
var extendApp = app.Extend({
    ...
});
```
vue3系
```
var extenApp = createApp({
    extends : app,
});
```


# アプリケーションのマウント方法が異なる

vue1系
``` 
var app = new Vue({
    el : '#templete',
});
```
vue3系
```
var app = createApp({
    ...
}).mount('#templete');
```

書き方が大きく異なるが、3系では同じ内容のアプリケーションを使い回ししやすくなった。

ただし、テンプレートを指定する場合は3系でも従来の書き方になるため、そこだけややこしい。

# ライフタイムサイクルが異なる

DOMノード生成後に処理をしたい場合のフックが`ready`から`onMounted`に変わった。
処理タイミング自体は変わらないため、1系からそのままコードを引っ張ってきた場合、修正を忘れないようにしないと動かなくなる。


# さいごに

アップデートを行った社内ツール自体にそこまで凝った機能がないため、最低限の内容のみになりました。
今後さらに3系を触ることがあれば追記したいと思います。