【Swift】SystemSoundID 一覧がないのですが

ちょっとしたときに、

あらかじめ用意されているシステム音を使いたい。


AudioServicesPlaySystemSound(1000)

👉 AudioServicesPlaySystemSound(_:) | Apple Developer Documentation hatena-bookmark

これだけで音が鳴る。

「1000」 は SystemSoundID というもののようなので、

「どんな音が鳴るのかリスト」を探すが、

公式で見つけられなかった。

以下にそれらしきもの。


👉 AudioServices - iPhone Development Wiki hatena-bookmark

結構、古そうなので今どきの状態を確認したい。

OSやバージョンなど環境によっても違うっぽい。

なので、コードからのぞいてみる。

 

🔊 欠番ID

ID は 2000 ぐらいまでの整数なのですが、

非公式のリストを見る限り、番号が歯抜け状態。

音声データの長さで「欠番らしき」を見分ける。

実際に再生してその時間を取得しました。


let start = Date()
AudioServicesPlaySystemSoundWithCompletion(1000) {
   let elapsed = Date().timeIntervalSince(start)
   print(elapsed)
}

// 1.566209077835083

👉 AudioServicesPlaySystemSoundWithCompletion(_:_:) | Apple Developer Documentation hatena-bookmark

おおまかに 再生時間 50ミリ秒 以下が欠番っぽい。

 

🔊 グリッドでボタン

ボタンを並べて Preview や Simulator や 実機 でどんな音があるのか確かめます 。



 

極力、deprecated な関数は避けていきたいです。

 

🔊 まとめ

実際に音声ファイルを作成する前に、雰囲気を確認したいときに使いたくなります。

しかし、ID が分からない。

そんな人用。

ファイルで探すなら、各環境内でディレクトリ名で走査するといいのですね !


Library/Audio/UISounds
❯ tree .
.
├── 3rd_party_critical.caf
├── AuthenticationMatch_Full.caf
├── AuthenticationMatch_Short.caf
...
├── ussd.caf
├── warsaw.caf
└── wheels_of_time.caf

4 directories, 321 files

あと、アプリとかショートカットもありました。

👉 「Play System Sounds」をApp Storeで hatena-bookmark
👉 System Sounds - Shortcuts hatena-bookmark


「iOS デバイスで位置情報対応の Google アプリを使用して設定を変更してください」とは ?

位置がタイムラインに正確に表示できてない。

設定を見てみると、

👉 Google - マイ アクティビティ hatena-bookmark

iOS デバイスで位置情報対応の Google アプリを使用して設定を変更してください

なんやこれ ?

 

🗺️ Google マップ コミュニティ

Google マップ コミュニティで調べます。

タイムラインがいつのまにか記録されなくなり、調べたら「iOS デバイスで位置情報対応の Google アプリを使用して設定を変更してください」となっていて、使っているデバイスが選択出来なくなっていました。googleマップは今までと同じアカウントで同じアプリを使用してるのですが…どうすれば直るでしょうか?

👉 iOS デバイスで位置情報対応の Google アプリを使用して設定を変更してください - Google マップ コミュニティ hatena-bookmark

iPhone で。


設定

 ↓

プライバシーとセキュリティ

 ↓

位置情報サービス

 ↓

Google Maps

これでも、直らん。

 

🗺️ まとめ

精度 (細かさ) が落ちたんでしょうね。

また、AndroidとiOSでは、この元データのスポットの採取タイミングに違いがあり、Androidに比べてiOSのほうが取得頻度が低いため、類推するための情報が少なくなってしまい、余計に直線になってしまうことがあるような気がしています。

取得頻度は、過去は結構な頻度で取得されていたのですが、いま時点は非常に少ないと思います。

👉 タイムライン表示で、元データはスポットとして残っているのに大部分が経路として参照されず、数点を直線で結んでしまうのはなぜでしょう。 - Google マップ コミュニティ hatena-bookmark

ここでも、また、悲しい感じとなってますね。

「iOS デバイスで位置情報対応の Google アプリを使用して設定を変更してください」 は消すことができませんし。


【Swift】プロトコル と 型 の難しさを Array のextension 化で感じた初心者

以前、so でみつけたこういうコード。


extension Array where Element: Collection { 
  func toD1() -> [Element.Element] {
    return self.flatMap { $0 } 
  }
}

👉 【 Swift 】2次元配列と1次元配列の相互変換 🤔 hatena-bookmark

なんとなく「Collection」 の部分が気持ち悪かったのであれこれやってみます。

 

■ お題

2次元配列を平坦化します。


let data = [
  ["あ", "い", "う"],
  ["え", "お"]
]

print(data.flatMap { $0 })
// ["あ", "い", "う", "え", "お"]

print(Array(data.joined()))
// ["あ", "い", "う", "え", "お"]

これを extension 化しようとして、


extension Array {
  var flattened: [String] {
    flatMap { $0 }
  }
}


Instance method 'flatMap' requires that 'Element' conform to 'Sequence'

とエラーがでるとこからスタートです。

 

■ やってみた

ドキュメントや先人の記事を読んでおきます。

👉 Element | Apple Developer Documentation hatena-bookmark
👉 Array | Apple Developer Documentation hatena-bookmark
👉 [Swift]Array型 #Swift - Qiita hatena-bookmark

型や制約の記述を確認しながら進みます。


extension Array where Element == Array<String> {
  var flattened: [String] {
    // Array(joined()) // Cannot convert return expression of type 'Array<Array<String>>' to return type '[String]'
    // joined().map { $0 } // OK
    // Array<String>(joined()) // OK
    // [Element.Element](joined()) // OK
    // [String](joined()) // OK
    flatMap { $0 } // OK
}


extension [[String]] where Element == [String] {
  var flattened: [String] {
    flatMap { $0 }
  }
}

// ["あ", "い", "う", "え", "お"]


extension Array where Element == [String], Element.Element == String {
  var flattened: [Element.Element] {
    flatMap { $0 }
  }
}

// ["あ", "い", "う", "え", "お"]

ここで、制約を先祖のプロトコルのみにします。


extension Array where Element: Collection {
  var flattened: [Element.Element] {
    flatMap { $0 }
  }
}

// ["あ", "い", "う", "え", "お"]

揃えたほうが良さげです。


extension Collection where Element: Collection {
  var flattened: [Element.Element] {
    flatMap { $0 }
  }
}

// ["あ", "い", "う", "え", "お"]

スッキリしました !

Sequence でもいけるんですね。


extension Sequence where Element: Sequence  {
  var flattened: [Element.Element] {
    flatMap { $0 }
  }
}

// ["あ", "い", "う", "え", "お"]

👉 誰もが知りたいSequenceとCollectionのすべて hatena-bookmark

ちなみに、元の配列に nil を混ぜると、


let data = [
  ["あ", nil, "う"],
  ["え", "お"]
]

上手に処理してくれてますね!


// [Optional("あ"), nil, Optional("う"), Optional("え"), Optional("お")]

 

■ まとめ

プロトコルと型。

よく分かってませんが

なんだか深そうです。

そういえば、どこかに書いてました、

プロトコルを使用することによって得られる柔軟性と、特定の型のメソッドの作成の容易さのバランス

というようなフレーズ。

ありがとうございます。

どこか継承グラフみれるとことかあるのでしょうか ? 独自に書き出さずに。

👉 Dash for macOS - API Documentation Browser, Snippet Manager - Kapeli hatena-bookmark
👉 realm/jazzy: Soulful docs for Swift & Objective-C hatena-bookmark