コンピュータ

...now browsing by category

 

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

日曜日, 6月 17th, 2018

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

上から順番に時系列で並べてあります。
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の破壊

日曜日, 6月 10th, 2018

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

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

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

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

[Swift] Arrayのインデックスに範囲外の値を入れてもクラッシュしないようにする

日曜日, 10月 22nd, 2017

概要

配列の要素のアクセスにて、クラッシュする”[]”の代わりに、nilを返す”[safe: ]”を追加して使う方法です。

序文

SwiftではArrayのインデックスに範囲外の値を指定するとクラッシュします。

    let array = ["A", "B", "C"]
    let index = 3
    let item = array[index]  // EXC_BAD_INSTRUCTION でクラッシュ

そのため、要素にアクセスする前に、インデックスのチェックを行う方法があります。

    let array = ["A", "B", "C"]
    let index = 3
    guard array.indices.contains(index) else {
        // インデックスの範囲外なら、nilを返す
        return nil
    }
    let item = array[index]  // 実行されない
}

面倒なのでついついサボって省略してしまい、後でクラッシュすることがあります。

実装

そこで、安全にアクセスできる”[safe: ]”を追加して、”[]”の代わりに使います。
これはインデックスが範囲外の場合、nilを返してくれます。
“[]”(subscript(Self.Index))はCollectionプロトコルのメソッドなので、同様にCollectionプロトコルに追加します。

extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

用例

“[]”の代わりに”[safe: ]”を使うと、インデックスが範囲外でもクラッシュせずにnilを返します。

    let array = ["A", "B", "C"]
    let index = 3
    let item = array[safe: index]  // nilを返す

注意

ちなみに配列の要素にnilが入っていた場合、戻り値の型は”Type??”になります。

    let array = ["A", "B", "C", nil]
    let index = 3
    let item = array[safe: index]  // item : String??

itemに対する最初のunwrapでnilならインデックスが範囲外、2度目のunwrapでnilなら要素がnilです。

    guard let firstUnwrappedItem = item else {
        return nil  // インデックスが範囲外
    }
    
    guard let secondUnwrappedItem = firstUnwrappedItem else {
        return nil  // 要素がnil
    }

追記

「そもそも範囲外のインデックスにアクセスするのはバグなのだから、nilを返すよりクラッシュさせてしまうべき」との意見もあるのですが、ユーザーにとってはアプリがクラッシュするのは最悪の事態なので、クラッシュするよりも動かない(nilチェックでリターンさせているとほとんどこの動きになります)方がはるかに良いと考えてます。

これは組込み系でよくある、フェイルセーフの考え方が主軸になっています。

参考

xcode – Safe (bounds-checked) array lookup in Swift, through optional bindings? – Stack Overflow

AdMob on iPhone X

日曜日, 9月 24th, 2017

自分のアプリをiPhone Xのシミュレーターで表示してみたのですが、AdMobの部分がセーフゾーンに収まらないですね。AdMobをバージョンアップすれば出来たりするのかな?

【追記】
と思ったら、別のアプリだとちゃんとセーフゾーンに収まっている・・・
やはりフレームワークのバージョンかなー。
どこでバージョン見れるんだろう。

【さらに追記】
原因は私のミスでした・・・
ちゃんとセーフゾーンに収まっていたアプリは、AdMobのバナーをStoryboard上で定義していて、ちゃんと下端が Bottom Layout Guide に合うように設定していました。
一方、セーフゾーンからはみ出していたアプリは、AdMobのバナーをソースコード上で定義していて、しかも Autolayout を使わずに、viewController.view.frame の下端に合うように frameを設定していました。

AdMobのバナーをStoryboard上で定義していて、下端が Bottom Layout Guide に合うように設定したところ、セーフゾーン内に収まるように表示されました。

Bose QuietComfort 35 wireless headphones

月曜日, 5月 1st, 2017

以前、通勤中に使っていたBluetooth接続のヘッドホンが壊れたため、新しいのを買いました。

考慮した点

絶対条件として、まずはBluetooth接続であること。以前のもBlutoothだったのですが、コードがないのは本当に便利で、身にしみていました。もうコード付きには戻れません。

次にオーバーイヤータイプであること。純正のようなイヤフォンだと、私の場合、耳からポロポロ落ちてしまうのです。また、前使っていたのはオンイヤータイプだったのですが、時々耳からずれることがありました。そんな中、家で使っている有線のオーバーイヤータイプのヘッドフォンは、外れたりずれたりする事がなく、とても具合が良かったのです。なので、今回は通勤用のヘッドフォンもオーバーイヤータイプにすることにしました。

それとノイズキャンセリング機能です。以前からとても興味があったのですが、購入したことはありませんでした。なので、今回はこれにこだわりました。

競合との比較

そうなるとSONYのMDR-1000Xも気になる所です。こちらも上記の条件を備えていて、値段も同じくらいです。

QuietComfortが良いところは、操作がシンプルであることです。電源のON/OFFはスライドスイッチで、曲のスキップとバックはダブルクリックとトリプルクリックです。対してMDR-1000Xは、電源のON/OFFは長押しで、曲のスキップとバックは専用のボタンです。実は前使っていたヘッドフォンはSONY製なのですが、この点が使いづらかったのです。専用のボタンが多い方が使いやすそうに思えるのですが、確かに目で見て操作する分にはボタンが多い方が使いやすいのですが、目で見ずに手探りで操作する場合はボタンが少ない方が分かり易いのです。特に曲のスキップとバックは、音量ボタンと取りちがえることが時々あり、またスキップとバックどちらが上のボタンだったかもよく忘れていました。

一方でMDR-1000Xの方が優れている点は、ペアリング記憶台数が8台であることです。対してQuietComfortは2台です。音源機器の数が多い場合は大変魅了的なのですが、とりあえずiPhoneとMacにつながればOKだったので、そのあたりは気にしませんでた。

良かった点

何と言ってもノイズキャンセリングがとても優秀です。基本的に通勤電車の中で使っているのですが、在来線が新幹線並みの静かさになります。これを付けていると時間が立つのが早く感じます。やはり静かなのは落ち着くみたいで、通勤がとても楽になりました。音によるストレスって以外に大きかったんですね。

また、静かになった分、音楽も小さな音でも充分に聞こえるので、耳に負担が少ないです。でも車内アナウンスはちゃんと聞こえます。車内アナウンスも音が小さくはなるのですが、走行音ほどは減衰されません。ノイズキャンセリングを周波数によって分けているみたいです。感覚としては新幹線の車内アナウンスくらいの音量です。

いまいちな所

大きくて重い点です。これはオーバーイヤータイプを選んだ時点で覚悟していたのですが、やはり荷物になります。重量はケース込みで400gくらいで、通勤カバンの中ではそれなりの容量と重さです。

あと、静かすぎるので歩きながら使うのは危険です。車が背後から来ても気づかないレベルです。ノイズキャンセリングがOFFにできないのもそれに拍車をかけます。じっと座っていられる環境でしか使ってません。