iPhone Simulator で zoom モードを再現するまでの過程

By | 2014年10月9日

「Xcode 6 時代のマルチデバイス対応 ~Size Classとベクター画像~」を参考にしながら 6/6 Plus に最適化させようとしていたのですが、iOS 8 から追加された zoom/standard モードを iPhone Simulator でデバッグするにはどうすればいいのかを調べていてカオスってたのでメモ。
そもそも iPhone Simulator で zoom/standard モードの切り替えができないのがどうかと思うけど。。。

先にまとめだけいうと、zoom モードにした実機でするのが一番確実

さて 6/6 Plus の解像度に対応しようとすると zoom/standard モードのサイズを考慮する必要があります。
サイズは 6 Plus の UIScreen の bounds です。
* zoom モード(375×667)
* standard モード(414×736)
* 解像度を対応させない(320×568)

6/6 Plus の解像度に対応させる方法

「Xcode 6 時代のマルチデバイス対応 ~Size Classとベクター画像~」より引用

* Launch 画像を登録する
* Launch Screen Fileを指定する

対応表

zoom/standard モードで解像度を対応している/いないかで [UIScreen mainScreen].bounds.size, [UIScreen mainScreen].scale, [UIScreen mainScreen].nativeBounds.size, [UIScreen mainScreen].nativeScale のそれぞれ値を取得してみました。

iPhone 6 Plus

bounds scale nativeBounds nativeScale
zoom – 非対応 320×568 2.000000 921.60004×1635.8401 2.880000
zoom – 対応 375×667 3.000000 1080×1920.9601 2.880000
standard – 非対応 320×568 2.000000 834.78265×1481.7391 2.608696
standard – 対応 414×736 3.000000 1080×1920.0001 2.608696

iPhone 6 Plus Simulator

iPhone 6 Plus Simulator では standard モードのみ実行可能。

bounds scale nativeBounds nativeScale
standard – 非対応 320×568 2.000000 960×1704 3.000000
standard – 対応 414×736 3.000000 1242×2208 3.000000

そこで zoom モードの解像度を再現するために Resizable Simulator を使えば可能なのでは?!と思いたって試してみました。

Resizable Simulator

起動後に w375 x h667 に変更して試してみました。

bounds scale nativeBounds nativeScale
非対応 768×1024 2.000000 1536×2048 2.000000
対応 768×1024 2.000000 1536×2048 2.000000

Simulator のサイズは変わってるけど、UIScreen の bounds が。。。
おそらくバグだと思われるけど UIScreen でほしいサイズはは Resize した後のサイズなのに。。。
UIScreen の bounds を元にしてコード上で自分でレイアウトしている場合はこれだと再現できないですね。

まとめ

AutoLayout のレイアウト確認くらいだと Resizable Simulator で確認できる。
とはいえ scale が 2 になっているためおそらく @2x を使いそうなので、その辺りの動作確認は zoom モードにした実機で確認するのが一番確実だと思います。
自力でレイアウトしている場合は何も考えずに実機でやりましょう。

あと Storyboard の preview も standasrd/zoom の切り替えはサポートしてないみたいですね。

何かいい方法があったりしたら教えてください。

yidev 第16回で発表してきた

By | 2014年9月29日

先日 yidev#16 で発表してきました。
第16回 #yidev 横浜iPhone勉強会に参加してきたよ」がとても分かりやすいです。
また運営の @es_kumagai さんありがとうございました。

発表の際に @sonson_twit さんがデバッグ情報をスクショの EXIF に埋め込めば?というアドバイスをもらってそれだとコピペもできるしいいな〜と思ったので、実装しようと思ってた矢先にまさかの PR が。

仕事がはやい!!感謝感謝です。

というわけで 0.0.4 をリリースしました。
挙動は今までとかわりませんが、保存されたデバッグ用の画像の EXIF(userComment) に保存されています。

スクショを撮った時に Slack や Hipchat への自動送信の機能を考えてるので、それを実装する時にでも本物のスクショの EXIF を操作するようにしようかなと思います。

See also

* スクショを送られてきた時にデバッグを楽にするライブラリを作った

#confwd で CocoaPods の Plugin の作り方について LT してきた

By | 2014年2月11日

少し遅れましたが「Conference With Developers 2」で LT をさせてもらいました。

@ninjinkun さんが発表していた「GitHub活動を通して個人のキャリアを積みつつ仕事の成果を出す方法」の中にGitHub チャンスというフレーズがあります。
便利なライブラリや意外にもこういう普段使ってるようなエコシステムの中にも GitHub チャンスは埋もれているので気軽に作って公開することでチャンスを生かせるかもしれませんね。
個人的には CocoaPods の Plugin は本家に取り入れられる可能性もあるので結構チャンスが埋もれてるのではないかと思っています。

また運営者の方々はこのような素敵なイベントを開催していただきありがとうございました。次回も参加したいと思います。

と、ここまでは感想なのですが、LT の中で CocoaPods Plugin の作り方の詳細 は blog に書くと言ってしまってましたが 以下がそれです。

この記事を書いた時の各 gem の version です。

gem の作り方ですが「君がOpsでもRubyで書いたライブラリはGemで配ろう」がとてもまとまっていてわかりやすいです。

plugin を作る際に参考になるのが cocoapods-try-release-fixcocoapods-0.29.0/lib/cocoapods/command 以下のコードが分かりやすいです。コード量も少ないので読めばある程度理解できるかと思います。

重要になってくるのが pod コマンドを実行した時の処理の流れです。

1. プラグイン読み込み(lib/cocoapods_plugin.rb が require される)
2. 該当するコマンドの instance を作成
3. 作成した instance の validate! を実行
4. 作成した instance の run
(claid-0.4.0/lib/claide/command.rb 参照)

これさえ把握できていれば後は簡単です。
サンプル用に引数を出力する echo コマンドを作ってみました。

$ git clone git://github.com/dealforest/sandbox.git
$ cd sandbox/cocoapods-echo
$ rake install
$ pod echo hogehoge
hogehoge
$ pod echo --test hogehoge
test

bundle gem cocoapods-echo を実行した後の diff です。
説明については GitHub 上にしておいたので分からない場合はコメントをもらえればレスします。

clone してきて rake install をしてもらえれば pod echo を実行できます。

ではでは。

iOS7 で UITableViewCell の深度を変更する時に気をつけること

By | 2013年10月25日

UITableView に対して bringSubviewToFront: のメッセージを送って UITableViewCell の深度を変更していたですけど
iOS7 からだと深度がかわらんなくなって困ったというお話です。

原因は iOS7 と iOS6 とで UITableView の構造が変わったためです。
iOS6 では UITableViewCell を UITableView が抱えていたのですが
iOS7 からは UITableViewWrapperView が間に加わりそいつが UITableViewCell を抱えてます。

[iOS6]
UITableView
    ├── UITableViewCell
    ├── ...
    └── UITabelViewCell

[iOS7]
UITableView
    └── UITableViewWrapperView
                   ├── UITableViewCell
                   ├── ...
                   └── UITableViewCell

bringSubViewToFront: は抱えてる view に対して実行してやる必要がるので
iOS7 の場合は UITableViewWrapperView に対して実行してやれば深度が変更されるというわけです。

とはいえ UITableView から UITableViewWrapperView にアクセスができません。
正確には subviews をたどればできるけど諸々考慮すると最終手段にしておきたい手段です。

superview が抱える view を指しているので、ようするに UITableViewCell の superview に対して実行してやれば
iOS7 と iOS6 共に同一のコードで深度が変更できます。

[旧]: [tableView bringSubViewToFront:cell]
[新]: [cell.superview bringSubViewToFront:cell]

元から UITableViewCell の superview をたどってメッセージを投げていれば問題なかったというわけです。
つまりは構造が変わってるから気をつけろよといったお話ですね。はい。
今回のとは関係ありませんが UITableViewCell の構造も変わったので注意しないといけないですね。

あと、iOS6 の時は深度変更した際にスクロールバーが消えるバグがあったんですけど iOS7 では直っていました。
iOS6 では 「UITableViewCell の深度を変更した時に scrollbar を正常に表示する方法」で表示することができますがパフォーマンスは若干落ちます。

UITableViewCell の深度を変更した時に scrollbar を正常に表示する方法

By | 2013年7月27日

UITableView をハックして Feedly ライクな UITableView を作ってたのですが scrollViewDidScroll: で UITableViewCell の深度を無理矢理いじったりしたせいで scrollbar が UITableViewCell の後ろに隠れるようになって困ってました。
地味にこういうのは気になって仕方がないたちです。

で、解決方法がわかったのでメモがわりに残しておきます。
UITableViewCell の深度を変更する前に UITableView のプロパティ “showsVerticalScrollIndicator” をオフにして深度変更後に再度オンにすれば scrollbar が表示されるようになります。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [self.tableView setShowsVerticalScrollIndicator:NO];     // ここ超重要!!!
 
    for (UITableViewCell *cell in [self.tableView visibleCells])
        [self.tableView bringSubviewToFront:cell];
 
    [self.tableView setShowsVerticalScrollIndicator:YES];     // ここ超重要!!!
}

サンプルは github にあげてあります。
この辺りのコードを変更してもらえれば確認できるかと思います。