Instagramの公式ページにも書いてるし、ググれば出てくるのですが、いろいろハマったのでまとめておきます。
動作環境、Xcode 9.3 + Swift 4.1 + iOS 11
URLスキームを使ってシェアする方法
公式ページには書かれていません。しかし、レイアウトというアプリでは、アプリ内で加工した写真を選択状態にして、Instagramの投稿画面を開くことができるので、隠しであるのかも?
APIを使って直接投稿する方法
投稿APIはありません・・・
UIActivityViewControllerを使ってシェアする方法
簡単でよいのですが、Instagramアプリは起動せず、直接自分のアプリから投稿する形になります。つまり、ユーザーからするとInstagramアプリの写真加工が使えないので不便に感じるかも。
@IBAction private func didTapShare() {
do {
// UIImageをactivityItemsにわたす
let activityViewController = UIActivityViewController(activityItems: [self.image], applicationActivities: nil)
present(activityViewController, animated: true)
} catch let error {
print(error)
}
}
表示されるシェアシート
Instagramを選択すると自分のアプリ内で投稿画面が表示される。
UIDocumentInteractionControllerを使ってシェアする方法
公式ドキュメントにも書かれているこの方法。説明にはInstagramアプリのみが選択対象になると書かれているのですが、実際はそうはなりません・・・過去はそうだったのかも知れませんが、iOS 11ではそうなりませんでした。あといくつかハマりポイントがありました。
@IBAction private func didTapShare() {
do {
// UIImageをDataに変換
guard let imageData = UIImageJPEGRepresentation(image, 1.0) else {
return
}
// テンポラリファイルとして保存。拡張子はigoにする
let imageURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("image.igo"))
try imageData.write(to: imageURL, options: .atomicWrite)
// 必ずメンバ変数として保持すること。ローカル変数だと意図しないタイミングで破棄される
// 保存した画像ファイルのURLを渡す
self.documentInteractionController = UIDocumentInteractionController(url: imageURL)
self.documentInteractionController!.uti = "com.instagram.exclusivegram"
// shareButtonは押したボタン(UIBarButtonItem)
self.documentInteractionController!.presentOpenInMenu(from: shareButton, animated: true)
// よくこの方法が見られるけど、たいていはBarButtonItemから起動するのでは?iPadでは、ここきちんとやらないと変なとこからポップアップするので注意
// self.documentInteractionController!.presentOpenInMenu(from: self.view.bounds, in: self.view, animated: true)
} catch let error {
print(error)
}
}
UIDocumentInteractionControllerオブジェクトをメンバ変数として保持しないと、意図せず破棄されてしまいます。一瞬シェアシートが出たと思ったら、すぐに閉じてしまう。エラーログにInvalid Operationとか出ます。
そして実際に開かれるシェアシート。
一覧に表示されるのはInstagramだけじゃないんですよね・・・他のアプリもigo拡張子に対応したからでしょうか?
ただ先程のUIActivityControllerの時と違って、「Instagram」ではなく「Instagramにコピー」になっていて、選択すると、Instagramが起動し写真が選択された状態で投稿画面が開きます。これはこれで便利な気もしますが、シェアシートで選択できるアプリが限られてしまうのが、ユーザーからすると不便かもしれません。Twitterがないのはさすがに・・・Slackやクラシルは出てくるのですがw
そこでファイル拡張子やUTIの指定を以下のように変えてみます。
// 拡張子をjpg
let imageURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("image.jpg"))
// utiをpublic.jpeg
documentInteractionController!.uti = "public.jpeg"
この場合、表示されるシェアシートはこのようになります。
Twitterもあります。そしてInstagramとInstagramへコピーの両方が表示されます。ユーザーからしたら何が違うんだと混乱の元になりそうですが・・・でも個人的には、これが一番いいかなと思いました。
Instagramの公式ドキュメントには、以下のようにするように書かれているのですが、上記のケースとシェアシートに表示されるアプリ、およびInstagramへコピーを選択した時の挙動に違いはなさそうでした。ドキュメント用意した時と変わってしまったのかなあ。
// 拡張子をig
let imageURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("image.ig"))
// utiをcom.instagram.photo
documentInteractionController!.uti = "com.instagram.photo"