23
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSで自分のアプリから写真をInstagramでシェアする時にハマった

Last updated at Posted at 2018-05-17

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)
    }
}

表示されるシェアシート

02-1.png

Instagramを選択すると自分のアプリ内で投稿画面が表示される。

03.png

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とか出ます。

そして実際に開かれるシェアシート。

01-1.png

一覧に表示されるのは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"

この場合、表示されるシェアシートはこのようになります。

04-1.png

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"
23
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?