以前に試したことのある人はほとんどいません( これをみて )、しかしそれは最初のアップルでした iPhone スマートフォンと モバイルOS 見る必要があります。アップルは、ハードウェアとユーザーエクスペリエンスに驚異的な進歩を遂げました。ただし、モバイルOSの動作方法や、スマートフォンアプリケーションの作成方法にも基準が設定されていることを忘れがちです。
アプリケーション間にコンクリートの壁を構築し、アプリケーションを完全に分離して相互に認識しないようにすることが、アプリケーションを安全に保ち、データを保護するための最良の方法でした。すべてのアクティビティはiOSによって綿密に監視されており、アプリがその範囲外で実行できるアクションはほんの一握りでした。
「禁欲は最高の保護です!」 -でも、その面白さはどこにあるのでしょうか。
彼らにはしばらく時間がかかりました。私に言わせれば長すぎますが、iOS8ではAppleは楽しい時間を過ごすことにしました。 iOS 8では、AppExtensionsと呼ばれる新しい概念が導入されました。この新機能は、アプリケーション間の壁を壊すことはありませんでしたが、いくつかのアプリ間で穏やかでありながら具体的な接触を提供するいくつかの扉を開きました。最新のアップデートは iOS開発者 iOSエコシステムをカスタマイズするオプションであり、この道も開かれることを望んでいます。
簡単に言うと、iOS 8 App Extensionsは、アプリケーションを起動したり画面に表示したりせずに、アプリケーションを操作する新しい方法を提供します。
予想通り、Appleはそれらがすべての上にあることを確認したので、アプリケーションが提供できる新しいエントリポイントはほんの一握りです。
アプリ拡張機能はスタンドアロンアプリではありません。これらは、効率的で単一のタスクに集中することを目的とした、アプリの拡張機能(ホストアプリと呼ばれる他のアプリからアクセスできます)を提供します。これらには独自のバイナリ、独自のコード署名、独自の要素セットがありますが、含まれているアプリのバイナリの一部としてAppStore経由で配信されます。 1つの(含む)アプリに複数の拡張子を付けることができます。ユーザーが拡張機能を備えたアプリをインストールすると、iOS全体で利用できるようになります。
例を見てみましょう。ユーザーがSafariを使用して写真を見つけ、共有ボタンを押して、共有するアプリケーション拡張機能を選択します。 Safariは、拡張機能をロードして提示するiOSSocialフレームワークと「対話」します。拡張機能のコードが実行され、システムのインスタンス化された通信チャネルを使用してデータが渡されます。タスクが完了すると、Safariは拡張機能ビューを破棄します。この直後、システムはプロセスを終了し、アプリケーションは画面に表示されませんでした。それでも、画像共有機能は完了しました。
iOSは、プロセス間通信を使用して、ホストアプリとアプリ拡張機能が連携できるようにする責任があります。開発者は、拡張ポイントとシステムによって提供される高レベルのAPIを使用するため、基盤となる通信メカニズムについて心配する必要はありません。
アプリ拡張機能のライフサイクルは、iOSアプリとは異なります。ホストアプリは、ユーザーのアクションへの応答として拡張機能のライフサイクルを開始します。次に、システムはアプリ拡張機能をインスタンス化し、それらの間に通信チャネルを設定します。拡張機能のビューは、ホストアプリのリクエストで受け取ったアイテムを使用して、ホストアプリのコンテキスト内に表示されます。拡張機能のビューが表示されると、ユーザーは拡張機能を操作できます。拡張機能は、ユーザーのアクションに応じて、タスクをすぐに実行/キャンセルするか、必要に応じてバックグラウンドプロセスを開始してタスクを実行することにより、ホストアプリのリクエストを完了します。その直後、ホストアプリは拡張機能のビューを破棄し、ユーザーはホストアプリ内の以前のコンテキストに戻ります。このプロセスを実行した結果は、プロセスが完了するとホストアプリに返される可能性があります。拡張機能は通常、ホストアプリから受信したリクエストを完了した後(またはバックグラウンドプロセスを開始して実行した後)に終了します。
システムはホストアプリからユーザーのアクションの拡張機能を開き、拡張機能はUIを表示し、いくつかの作業を実行して、データをホストアプリに返します(拡張機能のタイプに適している場合)。拡張機能の実行中は、含まれているアプリも実行されません。
今日の拡張機能は、 ウィジェット は、通知センターの[今日]ビューにあります。これらは、ユーザーに最新のコンテンツを提示したり(気象条件を表示するなど)、簡単なタスクを実行したり(To Doリストアプリのウィジェットで実行したことをマークするなど)するのに最適な方法です。私はここで指摘しなければなりません キーボード入力はサポートされていません 。
アプリからの最新情報を表示するToday拡張機能を作成しましょう( GitHubのコード )。このコードを実行するには、次のことを確認してください。 (再)構成 プロジェクトのアプリグループ(開発チームを選択します。アプリグループ名は一意である必要があり、Xcodeの指示に従う必要があることに注意してください)。
前に述べたように、アプリ拡張機能はスタンドアロンアプリではありません。アプリ拡張機能を構築するための包含アプリが必要です。含まれているアプリを入手したら、[ファイル]-> [新規]-> [Xcodeへのターゲット]に移動して、新しいターゲットを追加することを選択します。ここから、TodayExtensionを追加するための新しいターゲットのテンプレートを選択します。
次のステップでは、製品名を選択できます。これは、通知センターの[今日]ビューに表示される名前です。このステップでも、SwiftとObjective-Cの間で言語を選択するためのオプションがあります。これらの手順を完了すると、XcodeはTodayテンプレートを作成します。このテンプレートは、プリンシパルクラス(TodayViewController
という名前)のデフォルトのヘッダーファイルと実装ファイルをInfo.plist
で提供します。ファイルとインターフェイスファイル(ストーリーボードまたは.xibファイル)。 Info.plist
デフォルトでは、ファイルは次のようになります。
NSExtension NSExtensionMainStoryboard MainInterface NSExtensionPointIdentifier com.apple.widget-extension
テンプレートで提供されているストーリーボードを使用したくない場合は、NSExtensionMainStoryboard
を削除してくださいキーを押してNSExtensionPrincipalClass
を追加しますビューコントローラの名前を値として指定したキー。
Todayウィジェットは次のようにする必要があります。
アプリ拡張機能とその包含アプリはどちらも、プライベートに定義された共有コンテナー内の共有データにアクセスできます。これは、包含アプリと拡張機能の間の間接的な通信の方法です。
Appleがこれらをとても「シンプル」にする方法が好きではありませんか? :)
データトラフの共有NSUserDefaults
シンプルで一般的なユースケースです。デフォルトでは、拡張機能とそれに含まれるアプリは別々のNSUserDefaults
を使用しますデータセットであり、互いのコンテナにアクセスできません。この動作を変更するために、iOSは導入されました アプリグループ 。後 アプリグループを有効にする [NSUserDefaults standardUserDefaults]
を使用する代わりに、含まれているアプリと拡張機能で[[NSUserDefaults alloc] initWithSuiteName:@'group.yourAppGroupName']
を使用する同じ共有コンテナにアクセスするため。
コンテンツが常に最新であることを保証するために、Today拡張機能は、ウィジェットの状態を管理し、コンテンツの更新を処理するためのAPIを提供します。システムはウィジェットのビューのスナップショットをキャプチャすることがあるため、ウィジェットが表示されると、ライブバージョンのビューに置き換えられるまで最新のスナップショットが表示されます。 NCWidgetProviding
へのコンフォメーションプロトコルは、スナップショットが作成される前にウィジェットの状態を更新するために重要です。ウィジェットがwidgetPerformUpdateWithCompletionHandler:
を受信するとを呼び出すと、ウィジェットのビューが最新のコンテンツで更新され、更新の結果を説明するために、次の定数のいずれかを使用して完了ハンドラーが呼び出される必要があります。
NCUpdateResultNewData
-新しいコンテンツでは、ビューを再描画する必要がありますNCUpdateResultNoDate
-ウィジェットを更新する必要はありませんNCUpdateResultFailed
-更新プロセス中にエラーが発生しました- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { // Perform any setup necessary in order to update the view. // If an error is encountered, use NCUpdateResultFailed // If there's no update required, use NCUpdateResultNoData // If there's an update, use NCUpdateResultNewData [self updateTableView]; completionHandler(NCUpdateResultNewData); }
ウィジェットをいつ表示するかを制御するには、setHasContent:forWidgetWithBundleIdentifier:
を使用しますNCWidgetController
からのメソッドクラス。このメソッドを使用すると、ウィジェットのコンテンツの状態を指定できます。ウィジェットまたはそれを含むアプリ(アクティブな場合)から呼び出すことができます。 NO
を渡すことができますまたはYES
このメソッドにフラグを立て、ウィジェットコンテンツの準備ができているかどうかを定義します。コンテンツの準備ができていない場合、今日のビューを開いたときにiOSはウィジェットを表示しません。
NCWidgetController *widgetController = [[NCWidgetController alloc] init]; [widgetController setHasContent:YES forWidgetWithBundleIdentifier:@'com.your-company.your-app.your-widget'];
Todayウィジェットは、openURL:completionHandler:
を呼び出して含まれているアプリを開くように要求できる唯一の拡張機能です。方法。含まれているアプリがユーザーの現在のタスクのコンテキストで意味のある方法で開くようにするには、カスタムURLスキーム(ウィジェットと含まれているアプリの両方が使用できる)が必要です。 定義済み 。
[self.extensionContext openURL:[NSURL URLWithString:@'customURLsheme://URLpath'] completionHandler:nil];
ウィジェットを設計するときは、UIVisualEffectView
を利用してくださいクラスでは、ぼやけた/鮮やかなビューをcontentView
に追加する必要があることに注意してください。 UIVisualEffectView
ではありません直接。ウィジェット(NCWidgetProviding
プロトコルに準拠)は、キャッシュされた状態をviewWillAppear:
にロードする必要があります最後のビューの状態と一致させるためにviewWillDisappear:
その後、新しいデータが到着するとスムーズに移行します。これは、通常のView Controllerの場合とは異なります(UIはviewDidLoad
でセットアップされ、アニメーションとデータの読み込みをviewWillAppear
で処理します)。ウィジェットは、タスクを実行するため、または含まれているアプリをシングルタップで開くために設計する必要があります。キーボード入力はウィジェット内では使用できません。これは、テキスト入力を必要とするUIは使用しないことを意味します。
垂直方向と水平方向の両方のスクロールをウィジェットに追加することはできません。より正確には、スクロールビューを追加することは可能ですが、スクロールは機能しません。 Today拡張機能のスクロールビューでの水平スクロールジェスチャは、通知センターによってインターセプトされ、Todayから通知センターへのスクロールが発生します。今日の拡張機能内のスクロールビューを垂直方向にスクロールすると、今日のビューをスクロールすると中断されます。
ここでは、アプリ拡張機能を作成する際に留意すべきいくつかの重要な点を指摘します。
次の項目は、すべての拡張機能に当てはまります。
sharedApplicationオブジェクトは立ち入り禁止です :アプリ拡張機能は、sharedApplicationオブジェクトにアクセスしたり、そのオブジェクトに関連するメソッドを使用したりすることはできません。
カメラとマイクは立ち入り禁止です :アプリ拡張機能は、デバイスのカメラまたはマイクにアクセスできません(ただし、これはすべてのハードウェア要素に当てはまるわけではありません)。これは、一部のAPIが利用できないためです。アプリ拡張機能の一部のハードウェア要素にアクセスするには、そのAPIがアプリ拡張機能で利用可能かどうかを確認する必要があります(上記のAPI可用性チェックを使用)。
ほとんどのバックグラウンドタスクは立ち入り禁止です :アプリ拡張機能は、アップロードまたはダウンロードを開始することを除いて、長時間実行されるバックグラウンドタスクを実行できません。これについては以下で説明します。
AirDropは立ち入り禁止です :アプリ拡張機能は、AirDropを使用してデータを受信できません(ただし送信できます)。
バックグラウンドで実行できるタスクの1つは、NSURLSession object
を使用したアップロード/ダウンロードです。
アップロード/ダウンロードタスクが開始された後、拡張機能はホストアプリのリクエストを完了し、タスクの結果に影響を与えることなく終了できます。バックグラウンドタスクの完了時に拡張機能が実行されていない場合、システムは含まれているアプリをバックグラウンドで起動し、アプリのデリゲートメソッドapplication:handleEventsForBackgroundURLSession:completionHandler:
と呼ばれます。
拡張機能がバックグラウンドを開始するアプリNSURLSession
タスクには、含まれているアプリとその拡張機能の両方がアクセスできる共有コンテナーを設定する必要があります。
含まれているアプリとそのアプリ拡張機能ごとに異なるバックグラウンドセッションを作成してください(各バックグラウンドセッションには一意の識別子が必要です)。一度に1つのプロセスのみがバックグラウンドセッションを使用できるため、これは重要です。
アクション拡張機能と共有拡張機能の違いは、実際には非常に類似しているため、コーダーの観点からは完全には明確ではありません。共有拡張ターゲット用のXcodeのテンプレートはSLComposeServiceViewController
を使用します。これは、ソーシャル共有に使用できる標準の作成ビューUIを提供しますが、必須ではありません。共有拡張機能は、アクション拡張機能がSLComposeServiceViewController
から継承できるのと同じ方法で、完全にカスタム設計するためにUIViewControllerから直接継承することもできます。
これら2種類の拡張機能の違いは、それらの使用方法にあります。 Action拡張機能を使用すると、独自のUIを持たない拡張機能を構築できます(たとえば、選択したテキストを翻訳し、その翻訳をホストアプリに返すために使用される拡張機能)。共有拡張機能を使用すると、コメント、写真、ビデオ、オーディオ、リンクなどをホストアプリから直接共有できます。 UIActivityViewController
アクション拡張機能と共有拡張機能の両方を駆動します。共有拡張機能は上の行にカラーアイコンとして表示され、アクション拡張機能は下の行にモノクロアイコンとして表示されます(画像2.1)。
ヘッダーファイルでNS_EXTENSION_UNAVAILABLE
でマークされたAPIマクロ、または使用不可の同様のマクロは使用できません(たとえば、iOS8のHealthKitおよびEventKitUIフレームワークは、どのアプリ拡張機能でも使用できません)。
アプリと拡張機能の間でコードを共有している場合、アプリ拡張機能で許可されていないAPIを参照しても、AppStoreからアプリが拒否されることに注意する必要があります。これに対処するには、共有クラスを階層にリファクタリングし、共通の親と異なるターゲットの異なるサブクラスを使用します。別の方法は、#ifdef
によってプリプロセッサを使用することです。チェックします。組み込みのターゲット条件はまだないため、独自に作成する必要があります。
これを行うもう1つの優れた方法は、独自の組み込みフレームワークを作成することです。拡張機能に使用できないAPIが含まれていないことを確認してください。組み込みフレームワークを使用するようにアプリ拡張機能を構成するには、ターゲットのビルド設定に移動し、[アプリ拡張機能のみを必要とする]設定を[はい]に設定します。 Xcodeプロジェクトを構成する場合、ファイルのコピービルドフェーズで、埋め込みフレームワークの宛先として「フレームワーク」を選択する必要があります。 「SharedFrameworks」の宛先を選択した場合、送信はAppStoreによって拒否されます。
アプリ拡張機能はiOS8以降でのみ利用可能ですが、含まれているアプリを以前のiOSバージョンで利用できるようにすることができます。
AppleのiOSヒューマンインターフェイスガイドラインを覚えておいてください アプリ拡張機能の設計 。あなたはあなたの アプリの拡張機能はユニバーサルです 、含まれているアプリがサポートするデバイスに関係なく。アプリ拡張機能がユニバーサルであることを確認するには、Xcodeで「iPhone / iPad」値(ユニバーサルと呼ばれることもあります)を指定するターゲットデバイスファミリービルド設定を使用します。
アプリ拡張機能は間違いなくiOS8で最も目に見える影響を及ぼします。デバイスの79%がすでにiOS 8を使用しているため(2015年4月13日にApp Storeで測定)、アプリ拡張機能はアプリが利用する必要のある素晴らしい機能です。 APIの制限と、拡張機能とそれに含まれるアプリ間でデータを共有する方法を組み合わせることで、Appleはセキュリティモデルを損なうことなく、プラットフォームに関する最大の苦情の1つに対処できたようです。サードパーティのアプリがデータを相互に直接共有する方法はまだありません。これは非常に新しい概念ですが、非常に有望に見えます。