DroidKaigi 2017で発表します&スポンサーやります

はじめまして。ノハナ社唯一のAndroidエンジニアの瀬戸です。
最近はますます寒くなってきましたが、僕はちょっと前に業務用PCが壊れたので色々とホットです。

さて、来年の3/9、10に日本最大のAndroidカンファレンスであるDroidKaigi 2017が開催されますが、瀬戸のトーク「エンジニアが武器にするMaterial Design」が採択されました。
エンジニアがMaterial Designを勉強するとどんな利点があるのかという点を中心に、様々な知見やノウハウをお話する予定です。
聞きたい内容などがありましたら、お気軽に @seto_hi までご連絡ください。
またMateiral Designに関するライブラリをOSSとして近日公開予定です。こちらもお楽しみに!

更にノハナ社はDroidKaigiの「ランチ & おやつスポンサー」をいたします。
発表とスポンサーによってDroidKaigiをガンガン盛り上げていきます!

最後になりますがノハナ社ではAndroidエンジニアを切実に募集中です。
僕と一緒にAndroidをゴリゴリやりましょう!

社内イベント「ノハナデザインスプリント」を開催しました

こんにちは、ノハナに入社してから2ヶ月ちょっとになる渡邉です。
今回は、10月中旬に実施した社内イベント「ノハナデザインスプリント」についてご紹介したいと思います。

「ノハナデザインスプリント」って?

nds_1

今回開催したノハナデザインスプリントのテーマは、ズバリ「優勝して叙々苑の高級な肉を食べまくること!」ではなくて、「フォトブックの注文率を10%アップさせるために何ができるかを考えること」でした。

イベントを開催することになった背景のお話ですが、ノハナでは会社として下期目標を達成するために3つのミッションを設定しています。その中で唯一解決策にまで落とし込めていなかったのが、今回のテーマである「注文率アップ」でした。

一方、ノハナのメンバー内からは課題の解決に繋がりそうなアイデアがいくつかでてきていました。なにより得意分野の異なるメンバー同士が知恵を出し合えば、きっと名案が生まれるはず!ということで、キックオフから1ヶ月あまりで当イベントは開催されることになりました。

余談になりますが、当日の会場はランチや休憩をとる際に使用しているコラボスペースにしました。いつも業務を行っているオフィスよりも広く、開放的な環境なのでリラックスして課題に取り組むことができました。

イベントの実施とルール

イベントの実施に際して、いくつかのルールが設けられました。それによってアイデアはある程度、実現可能性を意識した内容になります。具体的には下記のようなルールがありました。

・3人1組のチームで課題に取り組むこと
・各チーム最低10案出し、その中でも自信たっぷりの1案を模造紙にまとめて発表すること
・施策の実現にかけられるリソースは「アプリエンジニア×2名、サーバエンジニア×1名、デザイナー×2名、総合職×1名」とする
・下期中にリリースし、効果測定を行うこと

nds_2

もちろん施策を実施することでユーザビリティが落ちるなど、ユーザーさんにとってマイナスになるアイデアは厳禁です。今回の課題は限られたリソースと期間の中で、売上や冊数ではなく「注文率」を10%アップさせるという少し難易度の高い内容だったので、各チーム、施策の案出しや数字のシミュレーションには苦戦しているようでした。行き詰った時には時間を指定して上長からのメンタリングを受けたり、「肉!肉!」と互いを励まし合うチームもありました。

始業と共に開始したイベントですが、チームごとの議論や資料作成は白熱し、気がつけば窓の外も暗くなって、あっという間に発表の時間がやってきました。

各チーム、自信たっぷりの1案を発表!

全員が同じ課題にチャレンジしたにも関わらず、なんと重複や類似した発表は全くありませんでした。各メンバーの経験や特色が良い形で表れた結果だと思います。注文率アップのために今のノハナサービスには備わっていない全く新しい機能の追加を提案するチームもあれば、運営側の都合でユーザビリティが損なわれている既存機能の改修について説明するチームもありました。

nds_3

新しい機能のアイデアとしては、注文件数に応じてちょっとしたプレゼントを贈る「ノハナちゃんボーナス」や、左右に写真をスワイプすることでフォトブックに使用する写真の取捨選択が簡単に行える「poi(ポイ)機能」などが発表されました。どの案もユーザーさんの注文が今よりももっと楽しくなるような内容なので、聞いていてワクワクしました。

nds_4

既存機能の改修案としては、チュートリアルでアップロードできる写真の枚数を増やすアイデアがでてきました。衝撃的なことに、写真を複数枚同時にアップロードすることができなかったサービス開始当初の名残により、現状チュートリアル時にアップロードできる写真の枚数が1枚であることが判明しました。
この発表についてはメンバーからも大きな反響があり、また初回ユーザーさんの使い勝手が大きく改善されることが見込まれるので、実際の改修に向けて前向きな検討が始まっています。発表を通して、ユーザーさんの目線でサービス設計を見直す必要があることを改めて痛感しました。

nds_5

プレゼンの表現は自由でしたが、中にはコミックテイストで、インパクトの強い資料を作成するチームもあり、メンバーの関心を誘いました!

nds_6

各チームの発表が終わると質問タイムに移りますが、メンバーからは多くの手が挙がり、時間いっぱいまで質疑応答が活発に行われました。

発表が終わったら、1番良いアイデアを発表したと思うチームへの投票を行いました。開票してみると各チーム、票数が拮抗するという結果に!どのチームのアイデアもノハナの現状をしっかりと捉えており、それを現実的な解決策にまで落としこめていたので、当然の結果かもしれません。激戦の中で見事優勝した1チームにはお約束通り「叙々苑お食事券10,000円分」が人数分贈呈されました!

発表後にはお待ちかねのお寿司パーティー!

nds_7

発表後には、おつかれさまでしたということで、豪華なお寿司パーティーを開催!職人さんが目の前で握ってくれる作り立てのお寿司が食べ放題なので、メンバーからは歓喜の声が飛び交いました。みんなで一緒に食べる握りたてのお寿司の味はやっぱり格別です。こうして、ちょっとリッチな懇親会も大盛況の内に終わりました!

最後に

入社してたった1週間だったにも関わらず主催者側としてジョインさせて頂いたイベントでしたが、ノハナサービスのこと、またメンバーの方々のことを知るとても良いきっかけになりました。たくさんの方に助けていただき、なんとか大きな問題なくイベントが開催されたことに対して感謝の気持ちでいっぱいです!

イベント実施後のアンケートで多く寄せられた意見でもありますが、出てきた良いアイデアについてはそのままで終わらせず、下期目標達成の為、実施に移せたら良いなと思いました。

ノハナではこのような社内外のイベントがたびたび開催されるようなので、これからもどんどん参加し、またこのような形でお知らせできればと思います!

iOSの写真アプリライクな写真ピッカーNohanaImagePickerをOSSとして公開しました

nip-logo

こんにちは。iOSエンジニアの原です。
果物の中では梨がいちばん好きです。

nohanaのiOSアプリの写真選択UIをOSS化して公開しました🎉

nohana/NohanaImagePicker: A multiple image picker for iOS app.

NohanaImagePickerとは

複数の写真を選択できるピッカーのOSSです。
nohanaの写真選択画面を作り直すことになったので、
せっかくだからということでOSSにしてみました。
nohanaのiOSアプリでは2016年の5月ごろから使っているので、多くのユーザに使われている実績があります。

特徴

オシャレトランジション

collection

写真一覧画面から写真詳細画面に遷移するときに、セルが拡大するようなオシャレトランジションがついてます。
遷移後の画面の操作によって、遷移前の画面の状態が変わっていることがあるので、トランジションをカスタムする時は 行き よりも 帰り を丁寧に作る必要があります。

transition

具体的には、写真詳細画面で写真をいっぱい切り替えて、写真一覧画面に戻ろうとすると、いま写真詳細画面で表示している写真が写真一覧画面には表示されていないという状態になります。なので、写真詳細画面から写真一覧画面に戻る直前に写真一覧画面をいいかんじにスクロールしておくという処理をしています。オシャレ〜。

モーメント

moment

iOS標準の写真アプリのモーメントのように、写真一覧を撮影した日付と場所でグルーピングして表示する機能を作りました。
グルーピング自体はiOSが自動的に実行してくれていて、グルーピングしたアルバムの一覧は

class func fetchAssetCollectionsWithType(_ type: PHAssetCollectionType, subtype subtype: PHAssetCollectionSubtype, options options: PHFetchOptions?) -> PHFetchResult

のtypeにPHAssetCollectionType.Momentを指定すると、取得できます。

ロゴ

nohana_imagepicker_logo

OSSにロゴがあるとやる気が出るので、デザイナさんにお願いしたら、かわいいロゴマークを作ってくれました!
以下、デザイナさんコメントです。

  • たくさんある写真の中からpick(選択)している様子をアイコンにしてみました。
  • 細かい違いですが、色味の調整にもこだわりました!

Swift 3.0

バージョン0.7.1でSwift3.0に対応しました🎉

使い方

基本的には以下だけで、ピッカーの表示と、選択した写真の情報を取得できます。

import NohanaImagePicker
class ViewController: UIViewController, NohanaImagePickerControllerDelegate {

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(true)
        let picker = NohanaImagePickerController()
        picker.delegate = self
        present(picker, animated: true, completion: nil)
    }

    func nohanaImagePickerDidCancel(_ picker: NohanaImagePickerController) {
        print("🐷Canceled🙅")
        picker.dismiss(animated: true, completion: nil)
    }

    func nohanaImagePicker(_ picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset]) {
        print("🐷Completed🙆\n\tpickedAssets = \(pickedAssts)")
        picker.dismiss(animated: true, completion: nil)
    }

}

READMEとDemoアプリのコードで解説しているので、詳しくはそちらを見てください。

工夫ポイント

ItemList

アルバム一覧データを格納するクラス(PhotoKitAlbumList) と 写真一覧データを格納するクラス(PhotoKitAssetList) のどちらもが 一覧データを格納するクラス という特徴を持っているので、その特徴をItemList (バージョン0.7以前はItemListType)というプロトコルで表現しました。
ImageListは以下のように定義しています。

public protocol ItemList: Collection {
    associatedtype Item
    var title:String { get }
    func update(_ handler:(() -> Void)?)
    subscript (index: Int) -> Item { get }
}

ImageListがCollectionに準拠しているので、PhotoKitAlbumListとPhotoKitAssetListは少ない実装でCollectionの強力な機能を利用することができています。
またsubscriptも実装しているので、添字で要素にアクセスでき、コードがシンプルになりました。

PhotoKitのラッパーのようなコードですが、写真選択UIのOSSなのにPhotoKitのラッパーを含んでいることは、若干やり過ぎだと思っているので、今後PhotoKitAlbumListとPhotoKitAssetListは別ライブラリにするかもしれません。

画面の状態管理

各画面には、ロード中状態ロード完了状態空状態(表示するデータがない状態)表示するデータがある状態の4つの状態があるので、それらをprotocolで表現しています。

public protocol EmptyIndicatable {
    func isEmpty() -> Bool
    func updateVisibilityOfEmptyIndicator(_ emptyIndicator: UIView)
}

public protocol ActivityIndicatable {
    func isProgressing() -> Bool
    func updateVisibilityOfActivityIndicator(_ activityIndicator: UIView)
}

protocol extensionでデフォルトの挙動を実装してあり、インジケータの表示/非表示の切り替え処理をViewController側で書く必要がありません。

public extension ActivityIndicatable where Self: UIViewController {
    
    func updateVisibilityOfActivityIndicator(_ activityIndicator: UIView) {
        if isProgressing() {
            if !view.subviews.contains(activityIndicator) {
                view.addSubview(activityIndicator)
            }
        } else {
            activityIndicator.removeFromSuperview()
        }
    }
}

ロード中状態空状態などが同時に起こりうる作りですが、1画面内だけで完結する状態管理なので今回はこれで十分かなと思います。

開発時に気をつけたこと

用語の統一

以下のように用語を統一しています。

用語 意味 備考
pick 写真を選択すること。 selectはUITableViewControllerやUICollectionViewControllerで使われているので、他のものを考えました。
drop 写真を非選択にすること。 同上。
asset 1枚の写真(または動画)のこと。 PHAssetに対応しています。
asset list 写真の集合のこと。アルバムとも呼びこともできる。 PHCollectionに対応しています。
album list asset listの集合のこと。アルバム一覧とも呼ぶことができる。 PHCollectionListに対応しています。

nohanaに特化しすぎないこと

nohanaのために書いているコードなので、nohanaに特化して書きたくなってしまうことが多々ありましたが、ぐっとこらえて汎用的に書けるように気をつけました。
おかげで、nohana側のコードで挙動をカスタムする処理が多くなってしまいましたが、逆に言えば挙動をカスタムし易いOSSになったと思います。
※nohanaは画面回転をサポートしていませんが、NohanImagePickerには画面回転にも対応しています(これが意外と大変だった)

まとめ

今後もいろいろと機能追加やリファクタをすすめていきますので、ぜひ使ってみてください。PRやissueも待ってます!

nohana/NohanaImagePicker: A multiple image picker for iOS app.

1 2 3 5