【Swift】朝、私は可愛い女の子の声で目覚めたい。


おはようございます。お盆も半分が過ぎました。寝苦しい夜が続いております。
皆様におかれましては(きっと)ますますご健勝のこととお慶び申し上げます。

本文につきまして。彩りの無いこのご時世に華を添えようと思い立ち、筆を取らせて頂いた所存です。
皆様の英気を養う糧となればと思います。

## 可愛い女の子。
可愛い女の子の声で目覚めたい。その願望を叶えるためにはその「可愛い女の子」について知らなければなりません。

可愛い女の子が可愛い足る由縁。
その「可愛い」はどこから溢れてくるものなのでしょうか？
##### 容姿？内面？才覚？

否。

#### **声**

私の大好きな声優、**[早見沙織](https://whv-amusic.com/hayamisaori/)様**然り、可愛さ・可憐さ・美しさというのは声から溢れ、湧き出てくるものであると私は確信しています。


# そしてある朝目覚めたとき、思い立った。

## 彼女が欲しい。

そう、彼女が欲しい。

朝、私好みの声で、私の名前を耳元で囁きながら起こして欲しい。
ふとした時、私の名前を呼んで欲しい。
お風呂湧いてるよーなんて日常的な、なんてことないやりとりがしたい。

## 来たるその時のシミュレーションを行う。

前触れのないある朝、気持ちよさそうに寝息を立てる私の耳元で私の名前を呼ぶ声が聞こえたとき、私は間違いなく挙動不審を演じるだろう。

驚き慌てふためき、大好きな麦茶を大袈裟なほどに床にぶちまけ、「えっ」を連発するだろう。
私に言わせればこんな唐突なシチュエーションも、来たるべき時についても同様に対処できなくてはならない。

でないと、麦茶はいくらあっても足りない。


## 人間の一番無防備なタイミング

それは一説に寝ている時だと言われる。
寝起きに対処できることであれば、覚醒時にも対処することができるのは想像に難くないだろう。

以下はそんなシミュレーションを行うための備忘録であり、私と同様の志を持つ「同志」へ捧げるものである。

# 目覚ましとは

一般的なものは、音声によって人間を覚醒させるためのものであり、その音声は個人が任意に設定できる場合もある。
近年ではスマートフォンに発達により、目覚まし時計を必要とせず、それの目覚まし機能を利用する人間もいる。

今回はそのスマートフォンを利用する。

## シミュレーションを目覚ましで行うための手順。

まずは可愛い女の子の声を手に入れなければならない。
しかし道ゆくお方のところへ行って、むざむざと「(おはよういるべ君)と囁いてもらっていいですか？」なんて問うことはできない。

看守さんの声で目覚めることになってしまう。

### 音声を拝借

そこで今回は[効果音ラボ](https://soundeffect-lab.info/)様から音声を拝借する。
紳士向けのとてもいいサービスも展開しているので是非覗いてみて欲しい。

<img width="697" alt="効果音ラボ" src="https://user-images.githubusercontent.com/61507019/90083668-24a1ea00-dd4e-11ea-9e1a-77252d49331b.png">

今回はこの音声の中から。**「あははははっ！あははははっ！あははっ！あははっ！」**を利用する。
一日のあり方を決めるのは朝の寝起きからであり、女の子と一緒に楽しく朝を迎えられる様備えておくのに最適である。

## 目覚ましを作る。

今回はSwiftを利用してiPhone向けの目覚まし機能を作成する。
**Androidを利用している同志には心から申し訳なく思う。**

まず、紳士たるもの承諾を得るのが決まりだ。
なんの承諾か？ 可愛い女の子の声に承諾など必要ない？

**確かに。**

```swift:NotificationModel.swift
func requestAllowanceNotification() {
    center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { (granted, error) in
        if error != nil { alert(body: "やり直しをお願いします。"); return }

        if granted {
            let center = UNUserNotificationCenter.current()
            center.delegate = self
        } else {
            alert(body: "通知を許可して下さい。")
        }
    })

```

今回のやり方はローカル通知を目覚ましに見立てて実装するやり方であるからして、
上記の承諾許可取得を適切なところで行っておく。


### 目覚ましの予約

許可を取得すればあとは予約をするだけである。
女の子の画像を画面いっぱいに表示するのと同様。簡単な手順で予約ができる。

とても簡単である。

```swift:ViewController.swift
import UIKit
class ViewController: UIViewController {
    let ladyImageView: UIImageView = {
        let view = UIImageView(image: nil)
        return view
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(ladyImageView)
        ladyImageView.image = R.image.lady()
    }
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        ladyImageView.frame = view.bounds
    }
}
```
### おっと、間違えた。正しくは↓


```swift:NotificationModel.swift

func reserveNotification(uid: String, date: DateComponents, content: UNMutableNotificationContent) {
    let center = UNUserNotificationCenter.current()
    let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
    let request = UNNotificationRequest(identifier: uid, content: content, trigger: trigger)

    center.add(request)
}
```

```swift:NotificationModel.swift

func configureNotificationContent(title: String, soundName: String) -> UNMutableNotificationContent {
    let content = UNMutableNotificationContent()
    content.title = title
    content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName))
}
```

受け取る側の処置を忘れずに。

```swift:AppDelegate.swift

extension AppDelegate: UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

        completionHandler([.alert, .sound])
    }
}
```

### 目覚ましの内容について。

configureNotificationContentで返ってきた値をreserveNotificationのcontentに入れてあげれば目覚ましを受け取ることができる。
目覚ましの予約ができた。しかしこれではよく聞く通知音が朝流れてくるだけだ。

~~いやこれは女性アンドロイドの声なのか、、？~~
~~**Siriさん、、？**~~

```swift:SoundModel.swift
func saveSound(soundData: Data?) {
    let fileManager = FileManager.default
    let libraryUrl = fileManager.urls(for: .libraryDirectory, in: .userDomainMask)[0]
    let soundDirUrl = libraryUrl.appendingPathComponent("Sounds", isDirectory: true)
    
    if let data = soundData {
        try! data.write(to: soundDirUrl.appendingPathComponent("ahaha"))
    } else {
        alert(body: "save error")
    }
}
```

音声を保存するために、saveSound関数を用意して、下記の様に保存してやれば、、、

```swift:SoundModel.swift
if let ahahaSound = R.file.lineGirl1Ahahaha2Mp3() {
    let data = try Data(contentsOf: ahahaSound)
    self.saveSound(soundData: data)
}
```

reserveNotificationのsoundNameで保存した```ahaha```を入れてあげればいい。

ちなみに音声名の取得は

```swift:SoundModel.swift

var soundInfoList: [(String, URL)] {
    let fileManager = FileManager.default
    let libraryUrl = fileManager.urls(for: .libraryDirectory, in: .userDomainMask)[0]
    let soundDirUrl = libraryUrl.appendingPathComponent("Sounds", isDirectory: true)

    do {
        let fileUrls = try fileManager.contentsOfDirectory(at: soundDirUrl, includingPropertiesForKeys: [.addedToDirectoryDateKey], options: .skipsHiddenFiles)

        var soundList: [(String, URL)] = []
        for url in fileUrls {
            let name = url.absoluteString.components(separatedBy: "/").last!
            soundList.append((name, url))
        }

        return soundList
     } catch {
        print("TODO: ", #function, "sound directory error")
        abort()
    }
}
```

上記のコードで保存してある音声ファイルの名前が取得できる。
FileManagerについての説明は割愛するが、Libraryの中にDataとして音声ファイルを保存しておけばローカル通知の音声として指定できる様になる。


これらを利用することで、、、

# 可愛い女の子の笑い声が部屋に響き渡る！！！

<img width="300" alt="目覚まし" src="https://user-images.githubusercontent.com/61507019/90087945-dd6d2680-dd58-11ea-8766-491c20bc66e8.png">


# 今日も明日も、元気いっぱい楽しく強く生きています。

いるべさんでした。