この記事でできるもの
下記のキャプチャのようにアプリからインスタグラムのフィードへのシェア導線をつけることができるようになります。
どうやって実装するのか?
結論だけパッとまとめると今回の実装方法は下記の三点セットです。簡単!
- アプリでインスタグラムの Custom URL Scheme を処理できることを確認する。
- 共有したいコンテンツ(今回は写真)をフォトライブラリーに保存する。
- Custom URL Scheme を使ってインスタグラムに遷移する。
概要をつかむ
iOS からインスタグラムにシェアをする方法は主に2つあります。
Custom URL Scheme
Custom URL Scheme を使用する場合は、Info.plist の LSApplicationQueriesSchemes
に忘れずに instagram://
を追加しましょう。iOS9 からはこれを設定していないとアプリ遷移できないので気をつけましょう。
下記が インスタグラムのシェアに関するドキュメントで記載されていた各 URL の役割になります。でも今回使用するinstagram://library
についての記載がないのは疑問です 🤔
URL | 内容 |
---|---|
app | Instagramアプリを起動する(アプリが無い場合は?) |
camera | Instagramアプリをカメラビューで起動、カメラなしのデバイスの場合は写真ライブラリで起動。 |
media?id= | Instagramアプリを起動し、指定されたid値(int)と一致する投稿を読み込む。 |
user?username= | Instagramアプリを起動し、指定されたusername値(string)と一致するInstagramユーザーを読み込む。 |
location?id= | Instagramアプリを起動し、指定されたid値(int)と一致する位置情報フィードを読み込む。 |
tag?name= | Instagramアプリを起動し、指定されたname値(string)と一致するハッシュタグが付けられたページを読み込む。 |
Document Interaction API
今回はこの方法については詳しく書いていきませんが、下記に参考になるリンクを貼っておきます。
基本的には標準のUIDocumentInteractionController
のモーダル画面を使ってインスタグラムに画像をシェアしていく方法になります。具体的な実装方法については公式ドキュメントにも載っていますが、下記のようなフローになります。
- シェアしたい画像を PNG・JPEG(推奨) で Data型に変換します
- Data型に変換したものを URL型に変換します。
- ファイルに保存する際、UTI を
com.instagram.photo
にする際は拡張子は必ず.ig
にします。 - モダールで表示する共有先アプリ一覧にインスタグラムだけを表示したい場合は、UTI を
com.instagram.exclusivegram
にして拡張子igo
を使用します。 - UTI とはデータのタイプを一意に識別する文字列のことです。
- ファイルに保存する際、UTI を
- 最後に作成した URL から
UIDocumentInteractionController
を初期化して表示します。
参考
実装してみる
インスタグラムに遷移できるようにする
まずは、アプリからインスタグラムの Custom URL Scheme が利用できるように info.plist の LSApplicationQueriesSchemes
にinstagram://
を追加していきましょう。
画像を保存して LocalIdentifier を取得する
次に共有したい画像をフォトライブラリーに保存しましょう。なぜ一度フォトライブラリーに保存する必要があるのかというと、今回使う instagram://library?LocalIdentifier=
ではクエリにLocalIdentifier
を使用するためです。このLocalIdentifier
は PHObject
のプロパティである localIdentifier
のことをさしています。PhotosFramework を使ったことがある方には馴染みがあるかもしれませんが、端末に入っている画像などを取得する際に受け取ることができる PHAsset
は PHObject
を継承しているので、今回はそれを使ってクエリに値を入れていきます。
func saveImage() { UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil) } @objc private func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) { let fetchOptions: PHFetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) if (fetchResult.firstObject != nil) { guard let lastAsset = fetchResult.lastObject else { return } let localIdentifier = lastAsset.localIdentifier } }
UIImageWriteToSavedPhotosAlbum
の Selector について一点補足をしておくと、この完了ハンドラーにセットするメソッドは指定のシグネチャに準拠している必要があって、引数やメソッドなどが違うとエラーを吐くので気をつけましょう。
参考
LocalIdentifier を使って Custom URL Scheme でインスタグラムに遷移する
上記のコードの続きから書いていきます。インスタグラムの URL Scheme に最新の LocalIdentifier クエリをつけてアプリに Custom URL Scheme での遷移を促すとインスタグラムのフィード画面で指定した画像を開くことができます。
@objc private func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) { let fetchOptions: PHFetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) if (fetchResult.firstObject != nil) { guard let lastAsset = fetchResult.lastObject, let urlScheme = URL(string: "instagram://library?LocalIdentifier=\(lastAsset.localIdentifier)") else { return } if UIApplication.shared.canOpenURL(urlScheme) { UIApplication.shared.open(urlScheme) } } }
余談
インスタグラムのストーリーに対してのシェア導線の追加実装もちょこっとやってみます。
func shareToInstagramStory() { guard let urlScheme = URL(string: "instagram-stories://share"), let imageData = image.jpegData(compressionQuality: 0.9) else { return } if UIApplication.shared.canOpenURL(urlScheme) { UIPasteboard.general.setItems([["com.instagram.sharedSticker.stickerImage": imageData]], options: [:]) UIApplication.shared.open(urlScheme) } }
ストーリーに関してはシェアするコンテンツをちゃんと指定しする感じなんですね🤔 これだったら Feed へのシェアもこんな感じで指定できるようにして欲しい感が若干あります。(ドキュメントにちゃんと書かれてない情報も多いし、、) 下記がストーリーでシェアすることのできる一覧です。
コンテンツ | キー名 | タイプ | 説明 |
---|---|---|---|
バックグラウンド画像アセット* | com.instagram.sharedSticker.backgroundImage | NSData * | サポートされているフォーマット(JPG、PNG)での画像アセットのデータ。最大サイズ720x1280。推奨画像比9:16または9:18。 |
バックグラウンド動画アセット* | com.instagram.sharedSticker.backgroundVideo | NSData * | サポートされているフォーマット(H.264、H.265、WebM)での動画アセットのデータ。動画は1080p、最長20秒まで対応50MB以下を推奨 |
スタンプアセット* | com.instagram.sharedSticker.stickerImage | NSData * | サポートされているフォーマット(JPG、PNG)での画像アセットのデータ。推奨画像サイズ:640x480。この画像はスタンプとしてバックグラウンドに表示されます。 |
バックグラウンドレイヤーのトップカラー | com.instagram.sharedSticker.backgroundTopColor | NSString * | バックグラウンドレイヤーのボトムカラー値と併せて使用される16進数のカラー値。トップカラーとボトムカラーが同じ値である場合は、バックグラウンドレイヤーはソリッドカラーになります。異なる値である場合は、グラデーションカラーとなります。 |
バックグラウンドレイヤーのボトムカラー | com.instagram.sharedSticker.backgroundBottomColor | NSString * | バックグラウンドレイヤーのボトムカラー値と併せて使用される16進数のカラー値。トップカラーとボトムカラーが同じ値である場合は、バックグラウンドレイヤーはソリッドカラーになります。異なる値である場合は、グラデーションカラーとなります。 |
アトリビューションURL | com.instagram.sharedSticker.contentURL | NSString * | アプリのコンテンツへのディープリンクURL。指定されない場合、ストーリーにアトリビューションリンクは反映されません。プロトコルを含めた、完全URLを使用します(developers.facebook.comではなくhttps://developers.facebok.com) |
※ アトリビューションURL
に関しては現在、クローズドベータ版で、承認された開発者だけが利用できる見たいです。