Xcodeプラグイン紹介
iOS10は評判が良さそうですね!
未だに触れていないですが時間をみつけて触ってみたいと思います。
本エントリーではXcodeのプラグインについて紹介したいと思います。
Alcatraz
まず、Xcodeプラグインを管理するパッケージマネージャを紹介します。
プラグインのインストールは全てこれで行うのがおすすめです。
alcatraz.io
インストール
ターミナルからコマンドでインストールすることができます。
curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/deploy/Scripts/install.sh | sh
プラグイン紹介
AutoHighlightSymbol
カーソルがあたっているシンボルにハイライトがつきます。
Xcode -> Editor -> Auto Highlight Symbol を
チェックすると有効になります。
ClangFormat
コード整形プラグインです。
Xcode -> Edit -> Clang Format -> Click Format on save
をチェックすると保存時にFormatされます。
保存時だけでなく任意のタイミングでフォーマットをかけたい場合は
ショートカットキーを設定することができます。
システム環境設定 -> キーボード -> ショートカット-> アプリケーション -> +ボタンをクリック
アプリケーション : Xcode.app
メニュータイトル : Format File in Focus
キーボードショートカット : ctrl + i
この設定で ctrl + i で任意のタイミングでフォーマットすることができます。
Formatはデフォルトで以下のようなものがあります。
スタイルはカスタマイズすることもできます。詳しくはGitHubを参照してください。
ColorSenseRainbow
UIColorの指定を簡単にするプラグインです。
UIColorのプレビューが表示されるようになります。
さらにプレビュー部分をクリックすると標準の色選択ポップアップが表示されます。
DerivedData Exterminator
DerivedDataを1クリックで削除できるようにするプラグインです。
Xcode -> View Derived Data Exterminator in Toolbarを
チェックするとこのように表示されます。
真ん中のアイコンをクリックするとDerivedDataが削除されます。
XToDo
ctrl + t で //TODO: //FIXME: などを一覧で
表示できるようになるプラグインです。
以上になります。
紹介したもの以外でおすすめのものがあれば教えてください!
他に良い物をみつけたら追記していきたいと思います。
relux Swift もくもく会 #1 を開催します!
アプリUIUX事例研究 # 1 TALKIE
もうすぐWWDC2016ですね!
発表内容が今から楽しみです。
アプリUIUX事例研究
"イケてるアプリ"の"イケてるUIUX"を研究する。
話題のアプリや気になったアプリを触って
良いと思ったものを紹介していきたいと思います。
第1回目は「TALKIE」を紹介します。
会員登録画面
会員登録画面は通常のフォームではなくチャット風のUIになっています。
LINEやFacebookなどのChatbotも話題になっているので
今後このようなUIが増えていくかもしれませんね。
都道府県の選択もわかりやすいですね。
文字の入力はかなり面倒なのでこのような形の方が良いですね。
詳細画面
画面下部のタブはiOS標準アプリとおなじようなトーンなっています。
青い部分がタップ可能なテキストです。
こちらもiOS標準と同じなのでわかりやすいですが
タップすると赤くなるのが少し気になりました。
CocoaPods関連のメモ
ネットワークの問題でCocoaPodsのsetupが終る気配がないので
この記事を書いています...
本エントリではCocoaPodsの基本的な使い方などについて簡単にまとめたいと思います。
cocoapods.org
インストール
#gemを最新にする sudo gem update --system #インストール sudo gem install cocoapods
初期設定
#セットアップ pod setup #プロジェクトのディレクトリまで移動 cd projectdir #プロジェクトファイルを元に初期化 pod init
pod initを実行するとプロジェクトフォルダ内にPodfileが生成されます。
ライブラリの指定はこのPodfileに記述していきます。
ライブラリの指定
target 'sample' do pod 'hoge' pod 'fuga', '1.0' end
hogeのように記載する場合はupdate時に最新版が適用されます。
fugaのように記載する場合は1.0が適用されます。
以下にバージョンの記載方法についてまとめます。
(この書き方がわからなくなることがあります...)
記載例 | 適用されるバージョン |
---|---|
'1.0' | バージョン1.0 |
'>=1.0' | バージョン1.0以上 |
'<1.0' | 'バージョン1.0未満' |
'~>0.2' | バージョン0.2以上1.0未満 |
ライブラリのインストール
指定ライブラリのインストールを行います。
インストール時にPodfile.lockが作成されます。
Podfile.lockファイルが存在する場合は
Podfile.lockに記載されているバージョンで固定されます。
#インストール pod install
ライブラリのアップデート
指定ライブラリのアップデートを行います。
Podfile.lockファイルが存在している場合でも
Podfileでバージョン指定されていないものはアップデートされます。
# アップデート
pod update
pod updateがうまくいかないとき
Xcodeを閉じて下記コマンドを実行するとうまくいく場合があります。
#リポジトリ削除 pod repo remove master #セットアップ pod setup #インストール pod install
pod update時にリポジトリの更新をスキップしたいとき
このようなオプションをつけるとスキップできます。
結構時間がかかることがあるので覚えておくと便利です。
pod update --no-repo-update
CocoaPods 1.0.0で気をつけること
以前のバージョンではtarget指定が必須ではなかったのですが1.0.0から必須になっています。ビルド時にエラーになる場合はプロジェクトのクリーンやDerivedDataの削除で動くようになると思います。
relux iOSアプリでディープリンク対応
relux iOSアプリでディープリンク対応を行いました。
ちょうどiOS9.3がリリースされたあとに着手しはじめ、
iOSの不具合でUniversalLinksが全く動かずかなりハマりました。
ブラウザがまともに動かず悩まされた人も多いのではないでしょうか?
今回はディープリンクを以下と定義し対応方法を紹介したいと思います。
- Universal Links
- Facebook App Links
Universal Linksとは?
iOS9から導入された仕組みです。
Universal Linksでは通常のURLから直接アプリを起動することができるようになります。
- アプリがインストール済:アプリが開く
- アプリが未インストール:Webページが開く
CustomURLSchemeではSafariを経由してアプリを起動しますが、
Universal Linksではアプリにシームレスに遷移するのでUXがかなり改善されます。
また、CustomURLSchemeとは違いschemeが衝突する心配もありません。
実際の画面はこのような動きになります。
Googleの検索結果からアプリを起動しています。
Facebook App Linksとは?
Facebookアプリから直接アプリを起動することができるようになります。
Universal LinksはiOS9以降のみ対応ですが、こちらはそれ以前のOSでも動作します。
- アプリがインストール済:アプリが開く
- アプリが未インストール:AppStoreが開く
App Links - 参考資料 - 開発者向けFacebook
実際の画面はこのような動きになります。
Facebookからアプリを起動しています。
対応するページ
reluxの旅館・ホテルの施設詳細ページのみ対応しました。
Facebook, Instagram, Twitter などのSNSでURLがシェアされた際に
アプリが起動されることを想定しています。
※2016年4月現在
サーバサイドの対応
apple-app-site-associationファイルを作成してルート直下に配置します。
Universal Links
apple-app-site-associationファイル
{ "applinks": { "apps": [], "details": [ { "appID": "4M2H9MG272.com.loco-partners.relux", "paths": [ "/2????/", "/5????/" ] } ] } }
appID: TeamID + BundleIndentifierの組み合わせです。
paths: 対応するパスを記載します。
施設詳細のURLは
https://rlx.jp/20000/ もしくは https://rlx.jp/50000/ のように2または5からはじまる5桁の数字と決まっています。
パスは一般的な正規表現には対応していないので "2????", "5????" としました。
ポイント
Facebook App Links
WebページにMETAタグを入れる必要があります。
<meta property="og:url" content="https://rlx.jp/27500" /> <meta property="og:image" content="https://s3-ap-northeast-1.amazonaws.com/relux/img/hotelpictures/RP27500_1046.jpg" /> <meta property="og:site_name" content="relux" /> <meta property="fb:app_id" content="482299358457316" /> <meta property="al:ios:url" content="rlx://hotels/27500/" /> <meta property="al:ios:app_store_id" content="843104033" /> <meta property="al:ios:app_name" content="relux" />
al:ios:url CustomURLSchemeを指定
al:ios:app_store_id AppleIDを指定
al:ios:app_name アプリ名を指定
ポイント
- FacebookDebuggerで警告がでているとうまく動作しません
- METAタグが存在しない状態でキャッシュされると動作しません
iOSアプリ側の対応
Capabilitiesの設定
Associated DomainsのDomainsを設定します。
applinks:url という形で指定します。
Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler { if ([userActivity.activityType isEqual:NSUserActivityTypeBrowsingWeb]) { int hotelId = [self matchHotelId:userActivity.webpageURL pattern:UNIVERSAL_LINKS_PATTERN]; if (hotelId) { [self pushHotelDetailViewController:hotelId]; } else { [application openURL:userActivity.webpageURL]; return NO; } } return YES; }
ポイント
- ActivityTypeはNSUserActivityTypeBrowsingWebになります
- 対応しないURLの場合は openURL でブラウザを開いたほうが良いです
Facebook App Links
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if ([url.scheme isEqualToString:CUSTOM_URL_SCHEME]) { int hotelId = [self matchHotelId:url pattern:CUSTOM_URL_SCHEME_PATTERN]; if (hotelId) { [self pushHotelDetailViewController:hotelId]; return YES; } } return NO; }
ポイント
- CustomURLSchemeに関する実装がされていれば、追加で実装する必要はありません
relux 開発合宿 in 箱根湯本
先日、relux開発合宿を箱根湯本で行いました。
オフィスを離れ、リラックス&集中できる環境で開発に取り組めました。
その時の様子を紹介したいと思います。
お世話になった施設
今回お世話になったのは 「ホテルおかだ」という和風リゾートホテルで
4/15(金)〜4/16(土)の1泊2日の合宿を行いました。
手配はreluxコンシェルジュデスクにお願いしました!
開発合宿の目的
しっかり時間をとり、普段取り組めないことを行う
優先度が低く、あとまわしになってしまっている部分を改修することにしました。
アプリチームでは「ユーザ登録情報変更画面のマテリアルデザイン対応」を行いました。
開発合宿の様子
新宿駅へ集合(1日目 07:00)
早朝に移動して10時から開発する計画です。
特急券を予約したリーダーが寝坊しましたがギリギリ間に合いました。
ロマンスカーでの移動
座席の説明
イケメンAndroidエンジニア
移動中の車内でフライング開発?
昼食・散歩(1日目 12:00)
昼食は暁庵でお蕎麦をいただきました。
www.hakoneyumoto.com
近くにコンビニはありませんが箱根ベーカリーがあります。
メロンパンがすごく美味しいです。
少し歩くと滝もあるのでリフレッシュには最適です。
暁庵
見事なコシです
天ぷらも美味しい
玉簾の瀧
アヒルちゃん
箱根ベーカリー
開発再開
19時の夕食までかなり集中して開発できました。
途中で不具合にハマったので気分転換に足湯へ
足湯のおかげか不具合も無事に解消しました。
気持ちいい
もちろんパソコンもあります
足湯コーディング
せっかくなので見晴らし茶屋で休憩?
夕食(1日目 19:00)
アプリチームはこの時点で実装はほぼほぼ終わっていました。
残りはコードレビューと動作確認のみです。
夕食もとても美味しかったです。
ここでは一旦作業のことは忘れ、先日おこなった勉強会の話題で盛り上がりました!
ビールで乾杯
開発再開(1日目 21:00)
お風呂に入り開発再開です。
会議室は0時までの利用だったので部屋に戻って作業しました。
部屋でもWiFiが使えたので快適に作業できました。
リラックスしながら開発
深夜の様子
朝食・散歩(2日目 09:00)
朝食はバイキング形式でした。
朝食後は箱根ベーカリーでカフェラテを買うついでに散歩
遅くまで作業していたので眠そう
箱根ベーカリー(2回目)でカフェラテを購入
景色も最高
癒やされます
デバッグ(2日目 10:00)
アプリチームは動作確認を終え、成果発表用の資料も完成!
しかし、Webチームで作業がコンフリクトしてしまいバタバタ
チェックアウト時間になってしまい発表会をやる時間がとれませんでした。
成果発表会のみオフィスで行うことに。。。
BBQ(2日目 13:00)
ホテルチェックアウト後にみんなでBBQ!
準備や後片付けをすべてやってくれるので便利
僕の愛用するCHUMSのショップもありました!
www.herofield.com
BBQスタート
登山が趣味のデザイナーが焼いてくれています
フランクフルト最高
美味しい
BBQ中でもパソコン
ダッチオーブンスチーム
成果発表会
合宿中にできなかった成果発表はオフィスで行いました。
今回行った「マテリアルデザイン対応」は後日まとめて紹介したいと思います。
発表の様子
反省点
- 前半 Webチームのデバッグを手伝えなかった
- 時間をしっかり切って発表会をするべきだった
良かった点
- 差込タスクがなく快適
- WiFi / 会議室が自由につかえて良かった
- 合宿前に少しだけ着手していたので時間通り終えられた
- 景色が良くリフレッシュできた
- 足湯のおかげで(?)不具合が解消した
- メロンパンが美味しかった
開発合宿を振り返って
今回relux開発チームでの開発合宿は初の試みでした。
やってみると想像以上に集中して取り組めたのではないかなと思います。
普段あとまわしにしてしまっている気になる部分を
改修できエンジニアとしても嬉しかったです。
やりたいことやチャレンジしたいことは他にもたくさんあるので
次回の開発合宿までにネタをいろいろ考えてみたいと思います。
リラックス&集中できる環境を用意していただきありがとうございました。
relux iOSアプリにNavigationDrawerを実装
relux iOSアプリにNavigationDrawerを実装しました。
いくつかライブラリも検討したのですが、条件に会うものがなくスクラッチ開発しました。
その時に気をつけたことや工夫したことを紹介したいと思います。
NavigationDrawerとは?
画像のように左側からスライドして表示されるメニューがNavigationDrawerです。
詳しくはGoogle design guidelinesを参照
Navigation drawer - Patterns - Google design guidelines
求める要件
レイアウト
レイアウトはあとから変更になる可能性が高いので
Storyboard(AutoLayout)を使用しています。
左側のメニュー部分はUITableView、右側の透過している部分はUIViewです。
透過している部分はTouch時にドロワーメニューを閉じるようになっています。
ユーザ情報セル
背景画像は季節毎に変更できるようにサーバから取得するようにしています。
頻繁に変わるものではないですが変更した際にすぐに反映させたかったので
画像のキャッシュ期間は1日としています。
ここでは画像の上に文字をのせるので視認性をあげるためにグラデーションをかけています。
// グラデーションをかける処理 UITableViewCellなどでは複数回呼ばれないように注意 CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height); gradient.colors = @[ (id)[UIColor clearColor].CGColor, (id)[UIColor blackColor].CGColor ]; [view.layer addSublayer:gradient];
アイコン画像は丸くトリミングし、名前と会員IDをアイコンの横にならべて表示しています。
// 画像を丸くトリミング view.layer.cornerRadius = view.frame.size.width * 0.5f; view.clipsToBounds = YES;
名前のフォントサイズはかなり大きめに設定していますが
スペースを十分に設けているので実機でみると違和感はありませんでした。
メニューセル
メニューのアイコンはGoogleのMaterial iconsを使用しています。
Androidアプリでよく使われるアイコンですがiOSで使用しても違和感はありません。
ただし、システムアイコンとならべるとボーダーが太いので気をつける必要があります。
design.google.com
メニューセルではRippleEffect(波紋アニメーション)はあえてつけませんでした。
技術的にはつけることは可能なのですが、
iOSらしくない動きであること
古い端末を考慮するとスペック的に厳しいことから実装しませんでした。
レイアウト順序
メニュー部分のレイアウト順序は追加・変更になることがわかっていたので
担当エンジニア以外でも簡単に変更できるように定数で持っています。
#define NAVIGATION_DRAWER_USER_INFO_ROW 0 #define NAVIGATION_DRAWER_USER_BOOKING_CONFIRMATION_ROW 1 #define NAVIGATION_DRAWER_USER_FAVORITE_ROW 2 #define NAVIGATION_DRAWER_USER_HISTORY_ROW 3
スピード優先で実装しているとハードコーディングしてしまいがちですが
あとで困るのは自分なので こういう部分は意識して定数にするようにしています。
CustomTransitionの実装
今回使用したのは以下になります。
UIViewControllerAnimatedTransition
- transitionDuration
- animateTransition
UIPanGestureRecognizer
UIPercentDrivenInteractiveTransition
実装方法についてはAppleドキュメントに記載されているので
紹介はしませんが工夫した点があるので紹介します。
developer.apple.com
指にあわせて動かす工夫
実装時に一番苦労した部分でもあります。
右側の透過部分を含めて1画面としているので
そのまま実装してしまうと指についてこないように見えてしまいます。
そこで画面の幅から計算して擬似的に指についてくるように実装しました。
offset分だけずらしてcontrollerの横幅で除算することで割合を算出しています。
case UIGestureRecognizerStateChanged: { CGFloat width = controller.view.bounds.size.width; CGFloat fraction = MAX([gesture translationInView:controller.view].x + offset, 0) / width; if (fraction > 1.0f) { fraction = 1.0f; } _shouldCompleteTransition = fraction > INTERACTION_THRESHOLD; [self updateInteractiveTransition:fraction]; }
やってみて感じたこと
今までCustomTransitionはあまり使っていなかったのですが、実装してみるとそんなに難しくありませんでした。
CustomTransitionを実装るすことによって他のアプリとは違った動きになるので、他の画面でもどんどん取り入れていきたいと考えています。
良かったら実際のアプリを触ってみてください!
いつものreluxを、アプリでも。 | relux