wootan's diary

iOSアプリ開発を中心としたエンジニアブログ

iMessageAppへの対応

PSStore10周年セールでブラッドボーンを購入しました。
今月末はFF15が発売になるので積まないように頑張ってクリアします!
www.jp.playstation.com

本エントリーではiMessageAppの対応について簡単にご紹介したいと思います。
ReluxではiMessageApp内で旅館・ホテルの検索を行い、シェアすることができます。
Storeでもフィーチャーされているのでぜひダウンロードして触ってみてください!

プロジェクトの作成

File > New > Project > iOS > iMessage Application で新規プロジェクトを作成することできます。

f:id:wootan1102:20161114192646p:plain


ターゲットの追加

既存のアプリにExtensionを追加する場合は
プロジェクトの + からターゲットを追加してください。

f:id:wootan1102:20161114192659p:plain


アイコンの設定

通常のアプリとは異なるサイズのアイコンが必要になります。
一番大きなサイズは 1024✕768なのでそこから縮小・トリミングして必要なサイズを作成しましょう。

f:id:wootan1102:20161114201759p:plain


レイアウト作成

MainInterface.storyboard

通常のアプリケーションのStorybaordと同様にレイアウトを組むことができます。
コントローラはUIViewControllerではなくMSMessagesAppViewControllerを継承したものになります。
後ほど説明がでてきますが2種類の画面モードが存在するのでしっかりAutoLayoutに対応する必要があります。


Viewのライフサイクル

MSMessagesAppViewControllerではメッセージ専用のメソッドが用意されています。
通常のアプリケーションをつくり慣れている方なら名前から挙動を予測することができます。

Extensionの状態

willBecomeActive(with: MSConversation)
  • アクティブ状態に遷移する前に呼ばれる
didBecomeActive(with: MSConversation)
  • アクティブ状態に遷移した後に呼ばれる
willResignActive(with: MSConversation)
  • 非アクティブ状態に遷移する前に呼ばれる
didResignActive(with: MSConversation)
  • 非アクティブ状態に遷移した後に呼ばれる

メッセージのイベント

選択されたメッセージの値をつかって処理をおこなう場合は
didSelect内でおこなう必要があります。willSelect内だとselectedMessageが更新されていません。

willSelect(MSMessage, conversation: MSConversation)
  • メッセージオブジェクトを選択したあと、selectedMessageを更新する前に呼ばれる
didSelect(MSMessage, conversation: MSConversation)
  • メッセージオブジェクトを選択したあと、selectedMessageを更新した後に呼ばれる
didReceive(MSMessage, conversation: MSConversation)
  • 新しいメッセージを受け取ったときに呼ばれる

プレゼンテーションスタイル

iMessageExtensionは2種類の画面モードが存在します。

Expanded


  • 全画面表示
  • メッセージタップ時に切り替る
  • Compact時に右のボタンタップで切り替る

Compact


  • コンパクト表示(ソフトウェアキーボードと同じサイズ)
  • Expanded時に右のボタンタップで切り替る

いつでもユーザが切替えることができるので両方に対応する必要があります。

プログラム側からも画面モードをリクエストすることができます。
requestPresentationStyle(MSMessagesAppPresentationStyle)
で指定したPresentationStyleに切り替えることができます。
画面が切り替る際には下記のメソッドが呼ばれます。

willTransition(to: MSMessagesAppPresentationStyle)

  • 画面モードが切り替る前に呼ばれる

didTransition(to: MSMessagesAppPresentationStyle)

  • 画面モードが切り替った後に呼ばれる

これらの用意されたメソッドを使用して処理を行います。
ここで紹介した以外のものも存在するので詳しくはドキュメント参照。
https://developer.apple.com/reference/messages/msmessagesappviewcontroller


メッセージの送信

MSMessageTemplateLayoutを使用しメッセージを設定します。
(これ以外のやり方がわからなかったのでカスタムする方法とかあったら教えてください...)

MSMessage *message = [MSMessage new];
MSMessageTemplateLayout *layout = [MSMessageTemplateLayout new];

// ここでlayoutに値を設定

message.layout = layout;
[self.activeConversation insertMessage:message completionHandler:nil];

Layoutに設定できる値については公式のこの画像がとてもわかりやすいです。
左上のアプリアイコンは自動的に挿入されます。

f:id:wootan1102:20161115164814p:plain

https://developer.apple.com/reference/messages/msmessagetemplatelayout


iMessageAppに対応する際のポイント・Tips

キーボードについて

ソフトウェアキーボードはCompactでは表示することができません。
UITextFieldなどでキーボードを表示する場合は気をつけましょう。
Expandedになる前にソフトウェアキーボードを表示しようとするとクラッシュします。

Podsを共有するには?

複数のターゲットでPodsを共有するには以下のように書きます。

def shared
  pod 'hoge'
end

target 'SampleApp' do
  pod 'foo'
  shared
end

target 'SampleAppExtension' do
  pod 'bar'
  shared
end

Modelなどの共通クラスはどうするか?

Modelなどは本体アプリとExtensionでかわらないので共通のクラスを使うようにします。
EmbeddedFrameworkを作成する方法もありますが、一部のみであれば本体アプリのソースを参照する方法がおすすめです。

共有したいファイルを追加するとこのような画面が表示されます。

f:id:wootan1102:20161115171100p:plain

このときに「Copy items if needed.」のチェックをはずすと
ファイル自体はコピーされずに参照することができます。

本体アプリとKeychainStoreを共有するには?

Keychain Sharingを使用します。
Project > Capabilities > Keychain Sharing をONにし
Keychain Groupsを揃えるだけで共有することができます。

ローカルストレージやUserDefaultsを共有したい場合はApp Groupsを使用します。
Keychain Sharingと同様にProject > Capabilities > App Groups をONにすることで共有することができます。

本体アプリを起動するには?

AppExtensionにはUIApplicationが存在しません。
AppExtensionではNSExtensionContextを使用します。
open(URL, completionHandler: ((Bool) -> Void)? = nil)で
カスタムスキームを指定することで本体Appをひらくことができます。
Reluxではメッセージをタップすると
メッセージに設定されている施設の詳細ページに遷移するようになっています。

最後に

iMessageAppに対応することで
アプリ間を行き来することなく情報をシェアできるようになり、
iMesssage上でやりとりを完結することが出来るようになります。

より良いユーザ体験のためにもiMessageApp対応を検討してみてはいかがでしょうか?

Relux(リラックス)

Relux(リラックス)

  • Loco Partners Co., Ltd.
  • 旅行
  • 無料