Think Big Act Local

iPhone開発を軸にブレブレの記事を書いていきます。

iOSDC 2016に参加してきたよ #iosdc

iOSDC 2016という、日本最大級のiOSのカンファレンスに参加してきました。

iosdc.jp

iOSDCはiOS・その周辺技術に関するカンファレンスで、公式サイトにはiOSエンジニアが聞いて面白ければ何でもOK」と説明されています。
トークは数多くの応募の中から運営スタッフにより採択されます。当日は技術的なテーマはもちろん、「海外のカンファレンスで登壇する」や「ハッピーな開発チームを築く」など、幅広い内容のトークが行われました。

以下、参加した記録として気になったセッションや会場の様子などを振り返ってみたいと思います。

振り返り

会場

f:id:himaratsu:20160823010812j:plain

会場は練馬のCoconeriホールという場所でした。

www.nerima-idc.or.jp

個人的にちゃんと練馬に上陸するのは始めてで、最初は「渋谷近辺じゃないのか」と思ってたんですが、行ってみると案外練馬近いし、家から交通の便も良いし、子連れのお母さん方とかが歩いてたりといつもと異なる環境で、良いコンディションでイベントを楽しめました。

f:id:himaratsu:20160823013359j:plain

トークが行われる部屋はこんな感じで、かなり広い空間でした。(A/Bトラックの2部屋に分かれていて、写真は大きい部屋の方のAトラック)
朝から座席がギッチリ埋まっていて、iOSエンジニアたちの早起きスキルに驚かされました。

トーク

聞いた、もしくは動画でみたトークのうち、印象深いものを並べてみます。

海外のiOSカンファレンスに登壇する - 完全版

id:shu223 さんによる、英語が苦手だったスタート地点からいかに海外カンファレンスで登壇するに至ったか、そのモチベーションと攻略法などのお話。
海外で登壇するという面白さはもちろんのこと、目標を先に設定して、そこから逆算で今自分がやるべきことを決めてやっていく堤さんの生き方がすごいなと思いました。

d.hatena.ne.jp

RxSwiftは開発をどう変えたか?

blog.ishkawa.org

@_ishkawaさんによる、RxSwiftを使った実装の紹介と、導入により開発がどのように変わるのか、というお話。
Rx は以前から興味がありつつも機会を作れずまだ試せてないのですが、その心にまた火がつけられました。記法を覚えるまでには少し時間がかかりそうですが、処理の流れが追いやすくなるので見通しの良いコードが書けるし、コードレビューも行いやすくなりそうだなと感じました。

SwiftでのGeoFence実装 - Tipsを添えて

@shmdevelopさんによる、iOSのGeoFence(正確にはGeographical Region Monitoring)のまとめとTipsの紹介。
iOSの位置情報プログラミングは色々なパターンがあり、その複雑さは年々難しくなっていってます。自分も最近実装したのですが、ドキュメント通りに実装しても挙動が怪しかったり、テストをしても不安な部分があったのですが、このトークを聞いてどこが実装による不具合でどこがOS挙動の怪しさなのかが分かってとても助かりました。

Xcode で快適なデバッグライフを追い求める

@dealforestさんによるXcodeデバッグの話。
プログラミングの大半はデバッグで、そのデバッグの効率をあげるためにどんなことをしてるか?のハウツーが複数紹介されました。出てくるケースがどれも「あ、これ困って諦めてたわ。。」というようなもので、各ケースでどうデバッグ情報を集めるかという話は毎回うならされました。今回のiOSDCで最も明日から役に立つトークだったと思います。ベストトーク賞の第3位を受賞されてました。

dealforest.hatenablog.com

ランチ

f:id:himaratsu:20160823013330j:plain

せっかく初練馬だったので、ランチは地元住まいの先輩おすすめのラーメン屋にいきました。

tabelog.com

お店も綺麗だしとても美味しかったです。スープは濃厚な豚骨魚介でした。

Tシャツ

f:id:himaratsu:20160823013725j:plain

当日、参加者にはTシャツが配られたのですが、役割や参加チケットの種類によって色が分けられていました。スタッフはピンク、登壇者は緑、スポンサーはオレンジなど。 パッと見でどういう方か分かるので、とてもコミュニケーションをとりやすかったです!

宣伝

f:id:himaratsu:20160823014258j:plain

自分はスポンサーチケットで参加させていただきました。無限コーヒーエリアの近くのジョブボードにポスターを貼っていたのですが気づいた方はおられたでしょうか?

ヤフーでは一緒に世の中の課題を解決していける仲間を募集しています。少しでも興味がある方は↓のページを見てみてね!

hr.yahoo.co.jp

まとめ

iOSDC 2016、最高に楽しかったです!iOSに興味のあるエンジニアやデザイナーがこの規模で集うのはすごいですね。
今回は普通にトークを聞くだけの人として参加したのですが、こういうカンファレンスは登壇者 or スタッフになった方が数倍楽しそうだなと感じたので、来年も開催されるようであればそんな形で参加したいと思います。

運営スタッフのみなさま、登壇者のみなさま、参加者のみなさま、ありがとうございました。おつかれさまでした!!

potatotipsでUICollectionViewの並び替えのAPIについて発表してきたよ

FiNCさんで開催された、potatotips #31 で発表してきました。

potatotips.connpass.com

発表した内容

タイトルの通り、UICollectionViewのCellをインタラクティブに並び替えるAPIの紹介です。

デモ

こんな感じで、

  • CollectionViewの(インタラクティブな)並び替え
  • サイズの異なるCell間の並び替え
  • pagingEnabled=trueの場合の並び替え

などができます。iPhoneのホーム画面のような挙動ですね。

経緯

WWDC2016で参加したセッションの1つに「What's New in UICollectionView in iOS 10」というのがありました。iOS 10でUICollectionViewがどう変わったか、どのような新しいAPIが追加されたかを紹介するセッションなのですが、そこでUICollectionViewにも並び替えのためのAPIがあることを知りました。

おー、これは!っと思って盛り上がったのですが、オチとして、このAPIsはiOS 9からすでに提供されていたことに調べていくうちに気づきましたw
iOS 10からスクロールがスムーズになったことで、並び替えの体験もより良くなったぜ!という紹介だったようです。

そんなわけで新しいAPIではなかったのですが、自分は知らなかったし、そんなにネット上に情報が出てないような気もしたので、potatotipsのLTで紹介してきました。

簡単な説明

並び替えにはUICollectionView, UICollectionViewDataSourceの以下のAPIを使います。

// UICollectionView
@available(iOS 9.0, *)
func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool
@available(iOS 9.0, *)
func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint)
@available(iOS 9.0, *)
func endInteractiveMovement()
@available(iOS 9.0, *)
func cancelInteractiveMovement()

// UICollectionViewDataSource
@objc(collectionView:canMoveItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)

UILongPressGestureなどを使って、並び替えの開始のタイミング、移動のタイミング、終了のタイミングで上記のAPIを呼ぶことで実装できます。
UITableViewと同じく、並び替えが終わったときにデータを入れ替えする処理を実装する必要があるのですが、ここでデータの不整合が起こるとクラッシュしてしまうので注意が必要です。

サンプルコード

github.com

まとめ

久しぶりにpotatotipsで発表するなー、と思って数えてみたらなんと2年ぶりの発表でした。 しばらくぶりのみなさまとお話しできてとても楽しかったです。

参加者のみなさま、素敵なオフィスにお邪魔させていただいたFiNCのみなさま、ありがとうございました!

関連してそうな記事

himaratsu.hatenablog.com

himaratsu.hatenablog.com

himaratsu.hatenablog.com

f:id:himaratsu:20160817234145p:plain

【書評】基本が身につくAndroidアプリ開発入門書

著者の森さんより、『基本からしっかり身につく Androidアプリ開発入門』を献本いただきました。

タイトルの通りAndroidアプリ開発をこれからはじめたい人向けの本で、Amazonでもベストセラーになっているようです。

この本は「ヤフー黒帯シリーズ」として出版されています。黒帯とはヤフーの中で特に優秀な人材に付与される称号で、著者の森さんはAndroid技術黒帯に認定されています。

iOSアプリ入門の黒帯本が少し前に出ていて、自分も読んだのですが、今回のAndroid黒帯本も構成などはそれに似ていると思います。

目次

本の目次は以下のようになっています。

  • 第1章 アプリ開発の準備
  • 第2章 Androidアプリを構成する要素
  • 第3章 はじめてのアプリ
  • 第4章 データの保存と共有
  • 第5章 通信とバックグラウンド処理
  • 第6章 カメラの撮影
  • 第7章 ユーザーの位置と地図
  • 第8章 アプリの公開

第1章ではアプリ開発に着手する前に考えるべきことが簡潔にまとめられています。 第2章ではAndroidで登場する「アクティビティ」「サービス」などのコンポーネントの説明。 第3~7章ではサンプルアプリを実際に作りながらxmlによるレイアウトやAndroidのクラスを使った様々な実装を学んでいくことができます。 最後の第8章で、自分の開発したアプリをGoogle Playに公開するまでの手順が紹介されています。

実はこれまでにも独学で、Webのドキュメントを読みながらAndroid開発に挑戦したことがあったのですが、「フラグメント」「サービス」「ブロードキャストレシーバ」などのiOSにはない考え方がいまいち理解できず、挫折してしまいました。 この本では丁寧な説明だけでなく、実際にそのコンポーネントを使ったサンプルアプリを作る過程があるので、しっかりと理解することができます。

また、iOSとの大きな違いにxmlによるレイアウトがあると思いますが、こちらも実際に手を動かしながら学べます。ある程度分かってくると、iOS 9からのStackViewと同じような考え方だなとか、自分の知っている知識に置き換えて理解できるので腹落ちしますね。

新しい言語を学ぶ場合、ある地点からはWeb上のドキュメントやOSSのコードなどを読んで勉強できるんですが、そこにいくまでが大変です。 この本は最初の一歩目に最適な本だと感じました。

環境構築からサポート

本書はAndroid Studio 2.xに対応しています。少しでもバージョンが違うとGUIが違ったりして本質的でない部分でハマったりするので、最新の環境に対応してくれてるのは嬉しいですね。

また、Android開発入門は、Xcodeを落としてハイスタートのiOSとは違って、JDKを落として、エミュレータを設定して、必要であればgradleファイルをほげほげして…みたいな、前準備が大変なイメージでした。 Android Studioが賢くなったのもあると思いますが、本にしたがえばスンナリ環境構築出来てしまうので、最初の障壁が超えられるのも助かります。

章の間にコラムがあるのですが、gradle ファイルがどういう役割かとか、Android Studio が登場して以前と比べてどう環境が変わったかなどにも触れられていて、歴史を知れたのも面白かったです。

画像が多く親切な説明

本書では説明の随所に画像が差し込まれていて、迷うことなく進めることができます。

f:id:himaratsu:20160803130156j:plain

例えば上の画像はAndroid Studioの機能で、xmlで組んだレイアウトをプレビューしてくれるものですが、こういう感じでどんな機能がIDEにあるのか教えてくれます。

自分が4年くらい使っているXcodeでもまだ知らない便利機能があったりしますし、こういう便利機能は先に体系的に学ぶのが良いと思います。

まだ、IDEを使っての開発は、純粋なAndroidアプリ開発に加えて、Android Studio自体の学習も必要です。

様々な機能があるなかで、どの機能をよく使うのか?どの機能は気にしなくてよいのか?がこの本を読み進めると分かりました。

仕事で使える知識が身につく

Web上のチュートリアルなども最近は充実してきてますが、最初は体系的に学べる書籍がいいのではないかと思っています。

f:id:himaratsu:20160803130814j:plain

この本ではタイトルにもある通り「しっかりと基本が身につく」内容になっています。

例えばサンプルアプリを作るときに、いきなりUI部分から始めるのではなく、先にロジックを整理して実装していくとカプセル化された良いコードが書きやすいなど、OJTで先輩エンジニアから言われそうなことが書かれています。

また、上に貼った画像はActivityのライフサイクルですが、例えばここではそれぞれのメソッドでは何をすべきか、何を意識すべきかが厚く書かれるなど、仕事でやる上では理解しておくべきポイントはしっかり書かれています。

そのため難しい部分は何度か読まないと理解できなかったりはしますが、しっかり理解できれば実戦でも良いコードが書けると思います。

ありがたいサンプルコードつき

本書で登場するサンプルアプリのソースコードこちらのページからDLして動かせます。

基本的に本の中でソースコードはすべて紹介されているのですが、Android Studioでサンプルコードを開いておくと、メソッド間をジャンプしながら処理を追えたりなどして便利です。

自分は本に出ているコードを写経しながら勉強する派なのですが、自分の書いたコードでコンパイルエラーが出て原因が分からないときにとても助かりました。

まとめ

自分はしっかり読んで理解しながら進めていきましたが、とりあえず動かしたいばの方はサンプルコードを動かしながら勉強していくこともできます。

『基本から身につくAndroid開発入門』は、これからAndroidに入門する方にピッタリな本だと思いました。

夏休みの間に勉強しようと思っていた方はぜひ読んでみてください。

「売れるもマーケ 当たるもマーケ マーケティング22の法則」を読んだ

売れるもマーケ 当たるもマーケ―マーケティング22の法則

売れるもマーケ 当たるもマーケ―マーケティング22の法則

この本は過去に実際にあったマーケティングの話をベースに、「こうしなければいけない」「こうしちゃうと死ぬ」みたいな法則をまとめている本です。一部ではマーケティングの教科書とも呼ばれているみたいです 。

自分は以前から「似たような機能をもったプロダクトは沢山あるのに、なぜこのプロダクトだけが流行るのか?」を不思議に思っていて、マーケティング系の本はたまに読んでたんですが、この本は自分の持っていた疑問の多くを解決してくれた気がします。

とても良い本だったので、自分の頭の中を整理する意味も込めてまとめてみます。

続きを読む

初級者から中級者にレベルアップするためのXcodeデバッグ術

効率よくiOSアプリ開発を行うために、効率よくデバッグを行いたいですよね。

このエントリでは「print文を書く以外デバッグの方法を知らなかったあの頃の自分」を初級者と定義して、自分がやってるデバッグ方法について書いてみます。

Xcodeデバッグ

1. printを使わずに変数の中身を確認する

age, name, coverImage という以下の3つの変数が宣言されています。

let age = 27
let name = "Ryosuke Hiramatsu"
let coverImage = UIImage(named: "sample.jpg")

これらの変数の中身をチェックしたい時、printで出力するのでも良いですが、それでは出力する値を変えたくなった時(print(age)print(age*2+1)に変更とか)に再度ビルドが必要になって時間がかかります。

printではなく、LLDBコマンドを使って確認することができます。

f:id:himaratsu:20160325214853p:plain

こんな感じで Breakpoint を貼って*1、そこで処理を止めた状態で Console に以下のように入力します。

(lldb) po age
27

(lldb) po name
"Ryosuke Hiramatsu"

単純に変数の値を出力するだけではなく、式の評価もできます。

(lldb) po age+1
28

(lldb) po name.characters.split(" ").map{ String($0) }.first
"Ryosuke"

2. QuickLookを使ってUIImageの中身を確認する

coverImage 変数に対して、printやpoコマンドではどんな画像なのか確認できません。

let coverImage = UIImage(named: "sample.jpg")
// print(coverImage) とした時のコンソール出力
Optional(<UIImage: 0x14fe19460>, {640, 640})

こういった場合、変数の上にマウスカーソルを合わせ、

f:id:himaratsu:20160325215318p:plain

現れたポップアップの目のアイコンをタップすることで画像が確認できます。

f:id:himaratsu:20160325215428p:plain

変数の値や画像の表示は、Xcodeの左下のAreaからも可能

変数の確認や QuickLook による画像の確認は Console の左のエリアからも可能です。

age や name などの変数名の横に値が出ていて一目で確認できます。

f:id:himaratsu:20160325215632p:plain

coverImage を選択した状態で目のアイコンをクリックして画像を表示することも可能です。

f:id:himaratsu:20160325215706p:plain

単純な変数の確認であればこちらの方が便利ですね。

3. 自作クラスのdescriptionをカスタマイズする

例えば以下のようなクラスを作ったとします。

class Person {
    let name: String
    let age: Int
    let coverImage: UIImage?
    
    init(name: String, age: Int, coverImage: UIImage?) {
        self.name = name
        self.age = age
        self.coverImage = coverImage
    }
}

以下のようにPersonクラスのインスタンスを生成します。

let person = Person(name: name, age: age, coverImage: coverImage)

このインスタンスのプロパティを確認しようと思ってprint(person)としてみると、Consoleには以下のように表示されます。

// print(person)
XcodeDebugPractice.Person

これは知りたい情報ではありません。LLDBでpo person.nameなどとすれば確認はできますが、少し手間がかかります。
こういうシーンではクラスのログ出力をカスタマイズしましょう。

CustomStringConvertibleを使う

先ほどの Person クラスを編集して、以下のようにします。

class Person: CustomStringConvertible { //★
    let name: String
    let age: Int
    let coverImage: UIImage?
    
    init(name: String, age: Int, coverImage: UIImage?) {
        self.name = name
        self.age = age
        self.coverImage = coverImage
    }
    
    //★
    var description: String {
        return "\(name), \(age)"
    }
}

この状態で再びprint(person)するとコンソールには以下が出力されます。

Ryosuke Hiramatsu, 27

description で指定した値が出ています。CustomStringConvertibleは print などで出力される値をカスタムするために用意されている Protocol です。

さらに、CustomStringDebugConvertible Protocol にも準拠してみます。

class Person: CustomStringConvertible,
    CustomDebugStringConvertible {  // ★
    // ... 省略 ...    
    var description: String {
        return "\(name), \(age)"
    }
    
    var debugDescription: String {  // ★
        return "\(name), \(age), \(coverImage)"
    }
}

CustomStringDebugConvertible はpoコマンドなどでデバッグプリントする際の値をカスタムできるものです。

他にも CustomReflectableCustomLeafReflectableCustomPlaygroundQuickLookable などが用意されていますので興味のある方は調べてみてください。

4. Breakpointをカスタマイズする

Breakpoint をもっと便利に使いましょう。例えば Loop で特定の条件の時だけ止めたかったり、あるいは処理は止めずに Breakpoint を通過したら Console にログを吐きたい、というような場面があるとします。そんな時には Breakpoint のカスタマイズが便利です。

例えばこんな感じのループ文を用意して試してみます。

for i in 0...50 {
    print(i)
}

ブレイクポイントを右クリックして「Edit Breakpoint」を選択し、

f:id:himaratsu:20160325221924p:plain

conditionに条件を入れます。今回は「i==22の時のみ止まる」ように設定してます。

f:id:himaratsu:20160325221955p:plain

この状態で実行すると、i==22のループの時のみ Breakpoint で処理が止まります。特定条件の時に変数の値を確認したい場合などに便利ですね。

おまけ:ブレイク時に音を出してデバッグする

Breakpoint では「ブレイク時にどんなOutputをするか」もカスタム可能です。

例えば「i==22の時だけ変数の値を確認したい。でも処理は止めずに続けたくて、値の内容は音声で確認したい」という場合は以下のように設定します。

f:id:himaratsu:20160325222529p:plain

これで実行すると「22 hit!」という音声が(おそらくsayコマンドで)発声され、下の「Automatically continue after evaluating actions」にチェックをつけているため処理は止まらずに継続されます。

いろんな特殊条件で発生する不具合を調査する際など、Condition をうまく使うことでデバッグを効率的に行うことができます。ちなみに自分は実プロジェクトで音声デバッグを使ったことはありませんw

5. アプリ内に保存したデータを確認する

NSUserDefaults や Document ディレクトリなどに保存したデータの中身を確認する方法です。
例えば以下のコードで値や画像を保存したとします:

// NSUserDefaultsに値を保存
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("@himara2", forKey: "account")
defaults.synchronize()

// Diskに画像を保存
if let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .AllDomainsMask, true).first,
  coverImage = coverImage {
    let targetPath = path.stringByAppendingString("/sample_data.jpg")
      if let data = UIImageJPEGRepresentation(coverImage, 0.5) {
        let success = data.writeToFile(targetPath, atomically: true)
        print(success)
      }
}

保存されたデータを確認してみます。

Xcode > Window > Organizer と選択して Organizer を開きます。

f:id:himaratsu:20160325223309p:plain

左メニューでアプリを実行したデバイスを選択して、対象のアプリを選択します。

f:id:himaratsu:20160325223343p:plain

設定ボタンから「Download Container...」を選択し、適当な場所に保存します。

f:id:himaratsu:20160325223425p:plain

xcappdata 拡張子のファイルが保存されますので、右クリックして「パッケージの内容を表示」します。

f:id:himaratsu:20160325223607p:plain

中身はこのようになっています。
Documents/ に保存した画像ファイル(sample_data.jpg)が存在しているのが分かります。

f:id:himaratsu:20160325224142p:plain

さらに、Library/Preferences/ 下のplistの中身をみると、

f:id:himaratsu:20160325224304p:plain

このように NSUserDefaults の値が保存されていることが分かります。

保存した内容を取り出すコードを実装するのでも良いのですが、ハマった時は原因が切り分けが大事なので、実際に保存されている情報を目視できるのは意味のあることだと思っています。

まとめ

Xcodeデバッグ手法に関する記事は以外と少なく、自分が最初にアプリ開発を始めた時は NSLog を大量に埋めて頑張ってました。
今回紹介したようなデバッグ手法を知ってからスピーディに開発できるようになったな、と思ったのでこのような記事を書かせていただきました。

何か間違ってる部分や、他に良いデバッグ方法などご存知でしたらぜひ教えてください :)

みなさんのデバッグライフに少しでもお役立ちできれば光栄です。

サンプルコード

github.com

今回引用したコードはすべてこちらでお試しいただけます。

こちらもいかがですか?

himaratsu.hatenablog.com

himaratsu.hatenablog.com

*1:Breakpointは行番号のあたりをクリックで設定/解除できます