MILLEN BOX

音楽好きの組み込みソフトエンジニアによるプログラミング(主にiOSアプリ開発)の勉強の記録

URLスキームを使用してInstagramの投稿ボタンを作成する [UIApplication][share][Photos.framework][swift2.3][swift3]

作成中のアプリでInstagramへの投稿ボタンを付けたいと思いました。
しかし、以前Twitter, Facebookへの投稿機能をSocial.frameworkはInstagramへの投稿機能はありません。

anthrgrnwrld.hatenablog.com

調べたところ、Instagramへの投稿をする方法は大きく2つ存在します。
恐らく公式で一般的なのは UIDocumentInteractionController を使用する方法です。
▶︎参考 [iOS] アプリ内で管理している画像を Instagram へ投稿する | Developers.IO

もう一つの方法はURLスキームを使用した投稿方法です。
今回はこちらを説明します。

なぜURLスキームでの投稿を選択したのか。それはUIDocumentInteractionControllerに比べカッコイイ気がするから!(何となく!!)
ただしこの方法は正式にはサポートしていない方法となります。突然使用できなくなる恐れがありますので注意してください。

f:id:anthrgrnwrld:20161007225720j:plain

今回のGithubは以下です。先日やりました一連のお絵かきアプリの最終系を更新する形で実装しました。

github.com

1. URLスキームを使ってInstagramを起動する

まずは練習。URLスキームを使ってInstagramを起動してみます。
Xcode8を使用している場合には、何もしていないとこのコードの実行タイミングで落ちます。
info.plistにLSApplicationQueriesSchemesをArray型で追加し、string型のメンバーitem 0をinstagramと指定します。
f:id:anthrgrnwrld:20161007224748p:plain

  • swift2.3
let testURL = NSURL(string: "instagram://")
if UIApplication.sharedApplication().canOpenURL(testURL!) {
    UIApplication.sharedApplication().openURL(testURL!)
}
  • swift3
let testURL = URL(string: "instagram://")
if UIApplication.shared.canOpenURL(testURL!) {
    UIApplication.shared.openURL(testURL!)
}

2. URLスキームを使って指定の画像を選択した状態でInstagramを起動する

URLスキームを使って指定の画像を選択した状態でInstagramを起動するには、指定するURLを以下にすれば可能です。

let testURL = NSURL(string: "instagram://library?LocalIdentifier=" + (投稿したい画像のIDENTIFIER)")

そうすると次の疑問が出てきます。
投稿したい画像のIDENTIFIER ってどうやって取得するの??

3. 投稿したい画像のIDENTIFIERの取得方法

IDENTIFIERはPhotos Frameworkを使って画像を保存する際に同時に取得できます。
画像をカメラロールに保存するだけならUIImageWriteToSavedPhotosAlbumを使用した方法が一番お手軽で良いですが、今回はIDENTIFIER取得の為、Photos Frameworkを使用して画像を保存します。

ProjectのLinked Frameworks and Libraries にPhotos.frameworkを追加します。
そしてプログラムの頭で import Photosと記載しPhoto frameworkをimportするのも忘れずに。

またXcode8を使用している場合にはinfo.plistに”Privacy - Photo Library Usage Description””を追加するのを忘れてはいけません。画像保存の際、写真ライブラリをいじることになるので必要となります。

  • swift2.3
        var imageIdentifier: String?
        PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(self.canvasView.image!)
            let placeHolder = createAssetRequest.placeholderForCreatedAsset
            imageIdentifier = placeHolder!.localIdentifier
            }, completionHandler: { (success, error) -> Void in
                print("Finished adding asset.\(success ? "success" : "error")")
                let testURL = NSURL(string: "instagram://library?LocalIdentifier=" + imageIdentifier!)
                if UIApplication.sharedApplication().canOpenURL(testURL!) {
                    UIApplication.sharedApplication().openURL(testURL!)
                }
        })
        
    }
  • swift3
        var imageIdentifier: String?
        PHPhotoLibrary.shared().performChanges({ () -> Void in
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: self.canvasView.image!)
            let placeHolder = createAssetRequest.placeholderForCreatedAsset
            imageIdentifier = placeHolder!.localIdentifier
            }, completionHandler: { (success, error) -> Void in
                print("Finished adding asset.\(success ? "success" : "error")")
                let testURL = URL(string: "instagram://library?LocalIdentifier=" + imageIdentifier!)
                if UIApplication.shared.canOpenURL(testURL!) {
                    UIApplication.shared.openURL(testURL!)
                }
        })

上記コードの注意点。
URLスキームの実行は必ずPHPhotoLibrary.shared().performChangesのクロージャーで行うことです。
間違ってこの外で実行してしまうと、imageIdentifierの中がまだ空で、想定通りにURLスキームが実行できません。
写真の保存は別スレッドで行っている為と推測されます。

上記コードをUIButtonのIBAction内などで実行すると以下のようにInstagramのライブラリ選択画面に移行できます。

f:id:anthrgrnwrld:20161007225720j:plain

今回使用した元のお絵かきアプリについて知りたい方は以下も確認してみてください!

anthrgrnwrld.hatenablog.com

anthrgrnwrld.hatenablog.com

anthrgrnwrld.hatenablog.com

anthrgrnwrld.hatenablog.com