RareJob Tech Blog

レアジョブテクノロジーズのエンジニア・デザイナーによる技術ブログです

10月25日「Global Engineer Night vol.1 Mercari x Quora x RareJobが考えるグローバルエンジニアの条件とは?」を開催します !!

こんにちは、レアジョブ 技術本部副部長 の @jumboOrNot です。

f:id:rj_tech_dept:20191017104430p:plain

10月25日「Global Engineer Night vol.1 Mercari x Quora x RareJobが考えるグローバルエンジニアの条件とは?」を開催します !!

Global Engineer Night vol.1とは

グローバル化の波は押し寄せており、日本と世界との垣根はどんどん下がる中、エンジニアにも国内外で活躍する場が増えています。Global Engineer Night (GEN)では、「日本でも海外でも垣根なく活躍できるエンジニアには、どのようなスキルセットが備わっているのか?」をテーマに、業界著名人をゲスト講師として招き、パネルディスカッションや交流会を開催します。

10月25日イベント概要

日時:2019年10月25日(金)19:00〜22:00 場所:東京都港区六本木6-10-1六本木ヒルズ森タワー18F 人数:60名(増枠しました!) 参加費:無料 詳細・お申込はconnpassのイベントページより。

どんなイベント?

日本と海外で要求されるスキルに違いはあるか? 英語の壁をどうやって乗り越えるか? エンジニアが世界で戦うためにはどんな準備が必要か?

などなど、普段なかなか聞けない本当にグローバルで活躍するために必要なことや、悩みをパネルセッションで聞くことができます。 今回は 広木さんをモデレーターにお迎えして、グローバルに活躍するMercari x Quora x RareJobの三社がいろいろな質問にお答えします。 当日は弊社エンジニアもスタッフとして参加したりしているので、懇親会でも是非お話しさせていただければと思います。

開催に向けて

グローバルキャリアってなんなんだ!そんなことを考えながら日々生きている私ですが、「海外で働く」「海外の人と働く」「海外向けのサービスを作る」等どんな形でも必要なのは英語力、、、だけじゃなくていろいろなスキルやマインドセットが必要だと私自身グローバルな企業で働きながら感じています。 うまく言語化できないこのハラハラやワクワク感みたいないろいろな感情をすごい勢いで乗り越えてきたであろう豪華パネリストの皆様から聞けるのは一参加者としてもとても楽しみです。

お待ちしております!

gen.connpass.com

デザインチームの運用をワークショップ形式で洗い出してみた

関東に台風が向かっております。 そのためコロッケを急いで買いに行かないといけないのですが、当番なので急いで書きます。

技術本部の副部長兼、デザインチームのリーダーのジャンボです。

皆さんは普段からの運用・作業の改善作業をどうやって洗い出しますか? 思いついても優先順位や難易度が読めずに結局着手できなくなっていませんか?

そんな時にオススメのやり方があります。

  1. ふせんかstormboardを用意する
  2. カテゴリ別に課題を洗い出す
  3. みんなで相談しながら優先度・効果のマトリクスで整理する

です。

早速ですが今回デザインチームでやってみた結果が以下です。(ちょっとぼかしてます)

f:id:jumbos5:20191011162100p:plain

赤ピンが上期で解決したものです。

エンジニアとの責務の分割や、サービスに対するUXに対するガイドラインなど解決が時間がかかりそうなものが右上に寄っています。一方でなんとなくルールはないけど、やったほうがいい・決めたほうがいいものなどは比較的すぐ実行でき効果が高いことがわかったので右下に整理されました。

最初は基準となるようなタスクを配置して、そのタスクとの相対的な位置をイメージして進めていくと進めやすいです。 これを作り右下から進めていくことで、チーム内での課題と優先度、そして効果のすり合わせをしながら良きデザインチームになっていければと思います。

www.wantedly.com

こういったプロセスをもっとよくしたい、もっと改善したい人を弊社では絶賛募集中です。

それではベランダのハーブが心配なので定時ダッシュでドロンします。 皆さんもplease keep safe.

EC2 Auto Scalingを導入する際のポイント

f:id:shino8383:20191004131442p:plain

おはようございます。レアジョブDevOpsチームのshinoです。

 

世間では消費税増税だとか軽減税率だとか話題になっています。

特に軽減税率は複雑ですよね。

私は考えることをやめました。 

 

さて、私は普段AWS上でレアジョブのシステム基盤に関わる業務を行っています。

AWSに移行した話

appeal.rarejob.co.jp

 

現在は、運用コストの削減、信頼性の向上、パフォーマンス効率の向上などの改善を主に行っています。

AWS上でアーキテクチャの設計や運用を考える際には、どのような点に気をつける必要があるのでしょうか?(突然の問題提起)

AWS上での設計や運用に関するベストプラクティスをまとめたAWS Well-Architected Frameworkなるものもありますが、こちらは非常に概念概念していて

「具体的にどうすれば?」

となる方も多いと思います。僕はなります。

 

今回はAWS上でのパフォーマンス効率化、特にEC2 Auto Scalingを導入する際にポイントとなることを言語化したいと思います。

 

 

EC2 Auto Scalingとは

Doc: EC2 Auto Scaling

端的に言えば

 

EC2インスタンス

リソースの使用状況に合わせて

自動で水平スケールする

 

サービスです。 

f:id:shino8383:20191004110903p:plain

他にも手動でのスケールやスケジュールベースのスケールもできますが、Auto Scalingを使う一番の恩恵は需要に合わせて自動スケールする機能だと思います。

 

すごく素敵なサービスに思えますが、無条件でAuto Scalingを導入できるわけではありません。

EC2 Auto Scalingを導入するためにポイントとなるアーキテクチャ設計があります。

 

EC2 Auto Scailing導入のポイント

既存のEC2クラスターにAuto Scalingを導入する際に気をつけることが大きく2つあります。

 

  1. インスタンス間の差異を無くす
  2. クラスターごとにエンドポイントを設ける

インスタンス間の差異を無くす

どういうことかというと

f:id:shino8383:20191004111738p:plain

 

AとBで設定に差があったらだめ、ということです。

・・・当たり前といえば当たり前なんですが。

 

例えばAはスレーブDB1を、BはスレーブDB2を直接参照しているような設定になっているとAuto Scalingできません。

自動で起動終了されるインスタンスは同じAMIから作られるので、同じクラスター内の既存のインスタンス間で差異がある場合は、差異がなくてもアプリケーションとして正常になるように改善する必要があります。

逆に言えば、アプリケーションの動作に関係ないcronが特定のインスタンスで動いていてそのインスタンスは消したくない、などという状況であればインスタンス間の差異があってもAuto Scalingの導入はできます。

その場合は、インスタンス保護を用いたり、Auto Scalingのインスタンス終了設定の「新しいものから消す」という設定と、最低起動台数の設定を組み合わせることで、既存のインスタンスを終了させずに保つことができます。

 

スケーラビリティを獲得するためにインスタンスをステートレスにしましょう。

 

クラスターごとにエンドポイントを設ける

ELBを使ってクラスターを形成していたらエンドポイントが既にあるはずなので、これも当たり前のように思えます。

ここで大事なのは、スケーラビリティを獲得するために意識的にエンドポイントを作る必要があるということです。

 

f:id:shino8383:20191004120724p:plain

 

 

例えば、APIがスレーブDBを参照する場合を考えます。

この場合、スレーブDBのエンドポイントを設けていれば全てのAPIインスタンスはそのエンドポイントを参照すればいいので、APIインスタンス間で設定に差異は生まれません。

しかし、エンドポイントを設けていない場合、特定のDBインスタンスを参照することになります。

APIインスタンスごとに特定のスレーブDBを指定するような設定を行えば、APIインスタンス間に差異が生まれ、Auto Scalingを適用することができなくなります。

 

また、一般的に、エンドポイントという抽象的なものに比べて、特定のDBインスタンスという具体的なものの方が変更の影響を受けやすいです。

つまり、変更される可能性が高いものに依存するということは、それだけ依存する側も変更を加える必要があります。

スレーブDBの台数を増やす場合などを考えると運用コスト的にもつらいことが想像できると思います。

 

Auto Scalingを用いることでインスタンスが勝手に増えて勝手に減るので、その変化の影響を受けない疎結合な依存関係を作る必要があるということです。

 

クラスター間の依存関係を作る際は、より抽象的なもの=エンドポイントに依存させることで、ステートレスな変更容易性を獲得し、疎結合アーキテクチャを実現させましょう。

 

あとがき

今回はEC2 Auto Scalingの導入に関して、アーキテクチャに必要なことをざっくり言語化しました。

導入する際は、どのAMIを使うか、どんなメトリクスをどんな閾値でトリガーとするかなどまだ考えなければいけないことはありますが、それはまたの機会に。

 

我々はこれからもAWS上での設計・運用のベストプラクティスを目指して邁進して参ります。

そんなチャレンジを一緒にして頂ける仲間を募集しております!

こちらからどうぞ

採用/求人情報 | アピール | 未来の教育を作る人のマガジン インフラエンジニア(AWS)

RareJobでのプロジェクトと英語の必要性について考えてみた

こんにちは。
サービス開発チームのすずきです。 RareJob(以下RJ)では弊社のメインサービスであるRareJob英会話のバックエンド開発を行っております。 最近の投稿では技術的内容が多いですが、 たまには弊社でどんなプロジェクトがあるのか知っていただき少しでもRJに興味を持っていただけたらと思います。
また、RJ採用サイトでも弊社エンジニアについて知っていただけるので ご興味あればご覧ください🙇‍♂️

RareJobでのプロジェクトって?

RJでのプロジェクトにはどんなものがあり、どのような進め方をしているのでしょうか。

  • 英会話サービスを展開しているから、みんなバリバリ英語を使ってコミュニケーションをとってるのでしょうか?🤔
  • 色々な国を跨いでプロジェクトは進められるのでしょうか?🤔

今回は私が参画しているプロジェクトに関してお話しさせていただきます。

本題

現在私が参画しているプロジェクトですが、以前プレスリリースした米国発のEdTechサービス「Voxy(ヴォクシー)」と連携 | 株式会社レアジョブになります。
Voxy社とはニューヨークに本社をもち、RJと同様に英語のeラーニングを提供している企業です。 世界150カ国以上😳に渡ってサービスを展開しており、RJにはなかったアクティビティを通じて学べる教材を提供しています。

今回のプロジェクトの目的は、

Voxyが提供する教材をRJの生徒様にシームレスに利用していただき
 Voxy社の教材を自主学習(インプット)→ RJのレッスンでアウトプット

という学習サイクルにて学習定着率を高めていただくことを目的としています。
外部のインプット教材を利用し、インプット教材に対応したスピーキングレッスンをRJが独自で開発するという RJでは初めての取り組み となります。

英語はやっぱり必要なのか?

いつくもの国を跨いでサービスを展開しているVoxy社ということで国籍は様々。
NY、ブラジル、シンガポールと様々な拠点とコミュニケーションをとって日々の開発は進められます。
やり取りの共通言語は英語になります。悲しくもここでの共通言語は笑顔ではなく英語です♪ 私自身英語でのコミュニケーションは得意ではないのですが、周りのメンバーに支えられてVoxy社との開発を進めています。 メンバーの英語力はそれぞれですが、英会話サービスを展開している弊社にジョインするからには英語の必要性は理解しており、 英語でのコミュニケーションに自信はないけれども積極的にチャレンジするメンバーには周りがサポートするような環境もあります💪

もちろん、英語はできる人に任せてオレはバリバリ開発するぜ〜っていうメンバーもいるので、 絶対に英語が必要というわけではないですが、いざという時にチャレンジできる気概があるとより良いという感じでしょうか。

(おまけ)英語よりも大切なこと

ここからポエミータイムですが、 こんな感じでRJのフィリピンメンバーやVoxyとの開発を進めいていく中で英語よりも大切なことは多様性を受け入れることなんじゃないかなと感じます。 活動時間も違うし、働き方も違うし。仕事の進め方も考え方も違います。
自分たちと違うことに対して抵抗感を持つのではなく、 そういうやり方なのだと理解して共生していく方法を探せるかが多国籍なプロジェクトでは求められる気がしました。

最後に

私が携わっているプロジェクトを簡単に説明させていただきましたが、 少しでもRJを知っていただき、興味を持っていただけたでしょうか☺️
RJでは生徒様へ今までとは違った新しい学習体験の提供にチャレンジしております。
そんなチャレンジを一緒に邁進してくれる技術でも英語でもおまかせあれエンジニアの方を募集しております!

こちらをチェケラください🤞
採用/求人情報 | アピール | 未来の教育を作る人のマガジン サーバサイドエンジニア

Android Qの折りたたみ式デバイス対応を試してみた話

ネイティブアプリ開発を担当している杉山です。 今月上旬ついにAndroid 10がリリースされたということで、そのことについて書いていこうと思います。

環境

AndroidStudio 3.5

AVD: 7.3 Foldable API 29 Android 10.0

*画面開閉を擬似的に行うには、AVDの横に表示されるメニューの画面開閉ボタン?を押してください。

f:id:r_sugiyama:20190919131044p:plainf:id:r_sugiyama:20190919131046p:plain

画面比率を意識

折りたたみデバイスでは、画面開閉時などに画面比率が変化します。

画面比率の問題をクリアするためにマニフェストファイルにmaxAspectRaitoまたはminAspectRaitoを記述しましょう。

maxAspectRaitoは、サポートできない画面比率がある場合などに用います。 またminAspectRaitoは、最小アスペクト比を設定します。

*minAspectRaitoは、10進数形式で最小アスペクト比を設定します。

*minAspectRaitoは、下記「マルチウィンドウを意識」に記述した「resizeableActivity=true」との併用はできません。(記述は可能ですが、属性が無視されます)

マルチウィンドウを意識

マルチウィンドウモードでもアプリがスムーズに動作するよう、マニフェストファイルにresizeableActivityの設定をしましょう。

resizeableActivityにtrueを設定することにより、折りたたみデバイスを含むアプリの動作環境との互換性を高めることができます。 また、resizeableActivityにfalseを設定することにより、マルチウィンドウモードを無効化することができます。

リソースへの排他的アクセスの対処は「onTopResumedActivityChanged」を利用しましょう。

こちらのコールバックメソッドは、アクティビティの再開状態を得た場合もしくは失った場合に呼び出されます。

主にマイクやカメラなどの単一ユーザーの共有リソースを使用している場合に、この情報を確保しておくことが重要となってきます。

まとめと余談

折りたたみ式スマホ(フォルダブル)の対応は、基本的に画面比率とマルチウィンドウを意識すること、 その中でリソースが欠落しないかを確認することが主なようです。

個人的には、画面の回転対応やアプリのマルチウィンドウ化の延長線のようなものだと感じました。

ほかにもAndroid Qから様々な要素が追加されているので、色々と試してみたいと思います。

Android Qの正式名称がAndroid10になり、お菓子のコードネームがなくなって少し寂しい…

Amazon S3にファイルをフロントエンドから直接アップロードしたかった話

バックエンドエンジニアです。 涼しくなってきましたが、みなさんファッション好きですか? 私は好きです。zozotownに掲載して頂きました。

今回やりたかった事

とある業務で500MB以上の動画ファイルをシステムに保存し、参照できるようにしたいという事でした。

前提

・S3にアクセスするアクセスキーとシークレットキーはセキュアにする為、Backendに持っている。
・S3には限定的なアクセス権を持たせて特定のディレクトリにアクセスしたい。

課題

原始的にバックエンド経由でアップロードする実装にしたところ、メモリ不足のエラーが出てしまった。

解決策

Amazon S3にはPre-Signed URLという機能があり、これを使うと期限付きで直接JavaScriptからS3へアップロード出来る事がわかったので、 上記課題を解決できると判断し、使ってみました。 バッファリングに仕様を変更する改修やCognitoを用いて一時的な認証方法を付与する方法も検討しましたが、今回はPre-Signed URLを使ったほうがさくっと対応出来そうなのでこちらを採用しました。

処理フロー

f:id:daichangdesu:20190913180026p:plain ざっくりとこんな感じのフローを考えました。

①request Pre-signed URL to Backend

JavaScriptからBackendにアップロード必要な情報をAPIで要求します。

②request Pre-signed URL to AWS

BackendからAWSAccess KeyとSecret Keyを使ってPre-signed URLをAWSに要求します。 ※Laravel5.5、league/flysystem-aws-s3-v3を使用したサンプルコード

public function getPreSignedUrl(string $filePath): string
{
    $s3 = Storage::disk('s3_private');
    $client = $s3->getDriver()->getAdapter()->getClient();
    $expiry = "+30 minutes";

    $command = $client->getCommand('PutObject', [
        'Bucket' => Config::get('filesystems.disks.s3_private.bucket'),
        'Key' => $filePath,
        'ACL' => 'public-read'
    ]);

    $request = $client->createPresignedRequest($command, $expiry);

    return (string) $request->getUri();
}

③return Pre-signed URL from AWS

AWSからPre-signed URLを取得します。

④return Pre-signed URL from Backend

取得したURLをJavaScriptに返します。

⑤upload file to AWS

JavaScriptから取得したURLを使ってアップロードします。

考察

結果問題なくアップロード出来るようになりました。
実装時にAWSから取得する所まではすんなり行ったのですが、フロントから動画ファイルをアップロード するときにヘッダーの書き方によってはアップロードが完了してもファイルが壊れてしまっていたりしてとても焦りました。
今回はaxiosを使って以下のようにアップロードする事により実現しました。

return axios.put(preSignedUrl, this.videoDataBinary, {
    headers: {
        'Content-Type': 'video/mp4'
},

シンプルにこれだけで行けました.... 今回の学びは今後アプリからファイルをアップロードしたりする時等に使えそうだなと思いました。

iPadのレッスンルームに端末回転をサポートした話しとユニバーサル対応のお話し

開発本部APP・UXチームの玉置(@tamappe)です。 今回の投稿が3回目になります。お盆は夏季休暇を利用して地元に帰省していました。
帰省中は暑いながらもどんな記事を書こうかなと思いながら時間が無下に過ぎ去ってしまい直近になって焦りながら記事を書いております。

今回は最近リリースしましたレッスンルームのiPad横向き対応について技術的な話しをしたいと思います。
最初は端末回転だけをサポートすればいいのかと思っていましたが色々ハマったポイントがありましたので後述します。

レッスンルームとは

そもそもレアジョブアプリを使ったことがない方向けにレッスンルームについてご紹介したいと思います。 レッスンルームとはレアジョブが提供している講師とのレッスンの場です。

f:id:qed805:20190821173322p:plain
lesson_room_ipad_portrait

(画像はiPadでの縦向きでのレッスンルームの様子です)

それぞれのUIを細かく分類すると下記のようになります。

f:id:qed805:20190821172506p:plain
lesson_room_ipad_portrait_description

動画の部分は本来はフィリピン講師が映る形になりますが開発中はレッスンルームを出入りできますしカメラで自分の顔が見れていますので 顔部分だけ加工してみました。

今回はこのレッスンルームに端末回転を許可する形で横向きのレイアウトを開発することがタスクでした。 注意したいことはこの端末回転はiPadだけですのでiPhoneではそもそも横向きはサポートしていません。

f:id:qed805:20190821172557p:plain
lesson_room_ipad_landscape

(iPadを横向きにして入室した場合の画面)

f:id:qed805:20190821172732p:plain
lesson_room_ipad_landscape_open

(教材を開いている時の画面)

こちらが今回のiPad横画面対応しました横画面のレイアウトになります。

f:id:qed805:20190821172830p:plain
lesson_room_landscape_description

このように分類分けするレイアウトにしました。
レアジョブアプリのデザインは基本的にstoryboardを使ってデザインを開発しています。
そのため、storyboardにautolayoutを貼って端末間のサイズを調整しています。

本来のやり方であればiPad横画面用のstoryboard ファイルを作成して横画面のレイアウトを作るのが最短だと思います。 ですがそのstoryboardを確認すると1つのstoryboardにUINavigationControllerや複数のContainerViewが存在していましたので レッスンルームのControllerだけを切り分けして横画面用のstoryboardを作るのは難しそうだと判断しました。

そこで今回採用したのがSizeClassという技術です。 これを使って1 つのstoryboard内で完結する様に調整したのです。

SizeClassとは

SizeClassとはAppleが提供しているデバイスのサイズを判別するための新しいクラスでiOS 8から導入されました。 iPhone 4 / iPhone 4S までは 端末のサイズが 320 x 480 だったのが
iPhone 5 の登場で初めて320 x 480 以外のサイズで iOS端末が出てきたのがきっかけです。iPhone 5 は 320 x 568 で高さが高くなっています。
さらに翌年には iPhone 6 の登場で高さだけでなく横幅も320 以外のサイズが登場してしまいiOSアプリエンジニアは端末対応に追われていた当時が懐かしく感じます。
当時のAppleはこのようなサイズ違いの端末の対応として AutoLayout という技術を使って解決するように促していましたが、 今度はタブレット端末として登場したiPadでとうとうAutoLayoutでは対応しきれない状況になりました。
iPhoneiPad で別々でstoryboardを管理したりコードでView を切り分けたりはできますが同じViewでそれぞれ2つのクラスを用意するのは非常に大変です。
さらに端末回転もサポートすると縦横比が変わってレイアウトが崩れてしまいますね

そこで登場したのがSize Class というクラスです。

AutoLayoutやSize Class の使い分けは Appleの Human Interface Guidelines にある Adaptivity and Layout という記事が参考になります。

developer.apple.com

非常に簡略化してこれを説明すると

iOS端末のサイズを大きく2つの概念に分けました。

  • Regular (denotes expansive space)
  • Compact (denotes constrained space)

このRegular と Compactをそれぞれ幅と高さに当てはめると

  • Regular width, Regular height
  • Compact width, Compact height
  • Regular width, Compact height
  • Compact width, Regular height

のように4通りに切り分けられます。この4通りは上記の参考記事にも記載されています。
この概念をiPhoneiPadにそれぞれ適用させると iPadなどのタブレットはPortrait(縦向き)やLandscape(横向き)に関わらず Regular width, Regular height に、iPhone端末は一部例外がありますがPortrait(縦向き) のときは Compact width, Regular height, Landscape(横向き) のときは Regular width, Compact height になります。

このように分類分けするときの技術が Size Class になります。

Size Class の使い方について

これをレッスンルームのstoryboardに当てはめて iPad の横画面の場合にのみ レイアウトを大幅に変える対応を行います。

記事の冒頭でお見せしましたレッスンルームのstoryboardは次の画像のようになります。

f:id:qed805:20190814135735p:plain
lesson_room_storyboard

基準がiPhone 8 Plus となっていてこれをベースにタブレット端末で横画面のときにのみレイアウトを切り替える仕様になります。

storyboardのベースの切り替え方は次のようにします。

f:id:qed805:20190814135829p:plain
lesson_room_storyboard_2

iPadを選択します。そうすると次のようにstoryboardのviewのサイズがiPad Pro のサイズに切り替わります。

f:id:qed805:20190814135928p:plain
lesson_room_storyboard_3

このようになります。

また端末の縦向き・横向きの切り替えはOrientation を切り替えることでPortrait やLandscape に切り替えられます。
これがSizeClass を適用させる上での前提知識になります。

次にstoryboardを使っている場合はAutoLayoutでレイアウト間のマージンをそれぞれ設定していると思います。 SizeClass の場合はこれが肝となります。 AutoLaytoutのNSLayoutConstraint をそれぞれのViewにRegular Size(以下R)のときの値 , Compact Size(以下C)の時の値をそれぞれ設定することができるのです。

私の場合、当てはめ方としては

  1. Rは iPad の幅と高さのすべて
  2. Cは iPhoneの幅と高さ
  3. iPhone 6 以上の高さが 縦向き のときだけR
  4. Plus 端末の幅が横向きのときだけR ( iPhone XS MaxiPhone XR の幅は横向きのときにR)

のルールで覚えています。これでも例外として() の部分が漏れてしまいます。

今回の仕様はiPadの場合でかつ横向きだったときにレイアウトを変更すればよいので例外ルールは考える必要はありません。
1のルールに従ってiPadは基本RなのでR指定でConstraint を指定すればよいと考えます。
つまりはstoryboard 上で 通常時の constraint と R 用の constraint をそれぞれ設定します。

R用のconstraint の設定の方法を紹介します。

今回は参考として 画像の灰色のView(チャット部分のView)のbottomに Regular の場合は20 px マージンを取るように変更してみます。

f:id:qed805:20190814160752p:plain
lesson_room_storyboard_4

灰色のViewが選択された状態で新しく bottom のconstraint を指定します。 20pxとします。

f:id:qed805:20190814160928p:plain
lesson_room_landscape_5

20pxのbottom のconstraint を作るとエラーが発生しますがエラーを無視します。

f:id:qed805:20190814161044p:plain
lesson_room_constraint

f:id:qed805:20190814161140p:plain
bottom_constraint

作成した20px のbottom のconstraint をダブルクリックして編集画面を表示させます。

f:id:qed805:20190814161231p:plain
bottom_constraint_2

このように表示されたあとは一番下に「+ installed」の項目があります。
この左側の「+」をタップすると

f:id:qed805:20190814161355p:plain
bottom_constraint_3

CompactとRegularを選べますのでwidth / height ともに Regular を選択して「Add Variation」をクリックして
新しい「wR hR installed」が作成されます。

これが width Regular かつ height Regular だった場合の contraint です。
ただ2つともinstalled のチェックボックスが入っているときの挙動だと不安定になりますので
「wR hR installed」の部分だけチェックボックスが入るように1つ目のチェックボックスを外します。

f:id:qed805:20190814161834p:plain
bottom_constraint_4

これで Regular width と Regular height の場合のみこのconstraint が使われるようになります。
ですがこれだけだともともとのbottomの 0px マージンのconstraint がすべての場合に適用されますのでエラーは消えません。
そこでもともとのbottomの 0px マージンのconstraint の方を修正します。

bottomの 0px マージンのconstraint をダブルクリックしてconstraint の編集画面を開きます。

f:id:qed805:20190814162149p:plain
bottom_constraint_5

このcontraint に 「wR hR installed」のvariation を追加します。追加した「wR hR installed」のチェックボックスを外します。

f:id:qed805:20190814162312p:plain
bottom_constraint_6

この設定をすればさきほどのエラーが解消されたことが分かります。
これでiPad でRegular size だったときの constraint の追加が完成します。

ただSizeClass においてはiPadはPortrait とLandscape の両方で R ですので端末が縦向きであったときと横向きだったときのハンドリングができません。
そのためここで黒魔術を使って iPadで横向きのときには 高さを C に変換する必要がありました。

特定条件で 端末のSizeを Compact や Regular に変換する

前回のSizeClass の登場とともに端末回転で重要なUITraitCollection というクラスが登場しました。
端末の向きに関するクラスUIInterfaceOrientationが非推奨になり、UITraitCollectionを使って実装しなければなりません。
結論からいうとUITraitCollectionのoverrideTraitCollection(forChildViewController:)を使うことで端末の Regular size と Compact size を入れ替えることができます。
こちらのメソッドはUIViewControllerに存在します。
レッスンルームの画面はUINavigationControllerが持ちますのでNavigationController を継承したカスタムクラスを作成して これをUINavigationController に使います。

class SampleNavigationController: UINavigationController { // UIViewController であればこちらを継承させる

    /// SizeClassを意図的に上書きすることができるメソッド
    override func overrideTraitCollection(forChild childViewController: UIViewController) -> UITraitCollection? {
        let any = UITraitCollection(verticalSizeClass: .unspecified)
        let compact = UITraitCollection(verticalSizeClass: .compact)
        
        // landscape (ここでiPad 端末かつ横向きの場合の変換処理を返す)
        if [iPad端末のフラグ] && self.view.frame.width > self.view.frame.height {
            return UITraitCollection(traitsFrom: [any, compact])
        }
        
        // portrait
        return UITraitCollection(traitsFrom: [any, any])
    }
}

このようにコードを書いたクラスをプロジェクトファイルに追加してstoryboard のUINavigationController に継承させます。
これによって iPad で横画面になったときに検知して 高さが Regular から Compact に切り替わります。

f:id:qed805:20190814170037p:plain
iPad_convert

最後になりますが、今回紹介したSize Class で上のレクチャーは「wR hR installed」でしたがプロダクトコードを確認したら 「hC installed」とちゃんとheight がcompact のときのconstraint を設定していました。
「wR hR installed」ではなくて 「hC installed」になります。

これでiPad でかつ 横向き用のConstraint が機能して横向き用のレイアウトが表示されるようになります。
この技術を使って1つのstoryboard でiPhoneiPad それぞれ別々のconstraint を設定して見栄えの異なるデザインを設計できました。

このようにうまくSize Class を利用すると特定のstoryboard にだけレイアウトの違うデザインを実現させることができます。
ぜひSize class を使ってみてください。

最後に勉強会イベントの話しを

余談としてイベントの告知をします。 来週28日(水)にメドピア社と共同で「IT x 社会貢献」をテーマに勉強会を開催します。

medpeer.connpass.com

レアジョブとしては「学習体験の向上」を軸に、アプリ開発、データ活用をメインコンテンツとしてお話します。
私はアプリ開発者として「レアジョブアプリでのアクセス負荷で生じたAPI遅延問題をアプリエンジニア視点で対策を考えてみる」をテーマにして登壇します。
近年のモバイルアプリの開発においてもはやサーバーサイドとの連携は切っても切れない役割を果たしています。 今回のイベントではそのAPIを考慮したWebRTCとの連携開発で起こり得たツラミを知見としてまとめて発表する予定です。

懇親会もあるので楽しめるイベントになると思います。 ご興味のある方はぜひこのイベントに参加していただければいいなと思います。