質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

【Swift】撮影した写真をシェアする方法

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 497

score 14

参考書の通りに以下のコードを打ったのですが
撮影した写真をTwitterに投稿することができません。

どこか間違っているのでしょうか・・・・。

教えてください。

import UIKit

class ViewController: UIViewController , UINavigationControllerDelegate , UIImagePickerControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var pictureImage: UIImageView!


    // カメラを起動するをタップすると起動
    @IBAction func cameraButtonAction(_ sender: Any) {
        // カメラが利用可能かチェック
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            print("カメラは利用できます")
            // (1)UIImagePickerControllerのインスタンスを作成
            let imagePickerController = UIImagePickerController()
            // (2)sourceTypeにcameraを設定
            imagePickerController.sourceType = .camera
            // (3)delegate設定
            imagePickerController.delegate = self
            // (4)モーダルビューで表示
            present(imagePickerController, animated: true, completion: nil)
        } else {
            print("カメラがは利用できません")
        }
    }

    // SNSに投稿するをタップすると実行
    @IBAction func shareButtonAction(_ sender: Any) {
        // 表示画像をアンラップしてシェア画像を取り出す
        if let shareImage = pictureImage.image {
            // UIActivityViewControllerに渡す配列を作成
            let shareItems = [shareImage]
            // resizeをする

            // UIActivityViewControllerにシェア画像を渡す
            let controller = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
            //iPadで落ちてしまう対策
            controller.popoverPresentationController?.sourceView = view
            //UIActivityViewControllerを表示
            present(controller, animated: true, completion: nil)
        }
    }

    // (1)機能が終わったあとに呼ばれるdelegateメソッド
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]){
        // (2)撮影した画像を配置したpictureImageに渡す
        pictureImage.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
        // (3)モーダルビューを閉じる
        dismiss(animated: true, completion: nil)
    }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • TsukubaDepot

    2020/07/15 10:04

    投稿していただいたコードを使いそのままビルドし、実機で動作させて確認したのですが、Twitter に投稿する画面まで出てきますし、実際に投稿もできました。
    質問者さんの環境だと、投稿画面にもならない、ということでしょうか。
    それとも、投稿画面切り替わるが、その画面がすぐにきえてしまうということでしょうか。
    「また共有画面(アイコン選択画面)に戻ってしまいます」ということなので、後者のほうかとは思いますが。

    LINEに投稿できるのであれば、Twitter側の問題かもしれません。私のTwitterはバージョン8.26です。

    しかし、もしTwitterに投稿できなければ支障がある、ということでなければ、同じような共有を使うLINEでは実行できていますので、現時点では問題据え置きということでいかがでしょうか。
    この問題の解決に労力を避けるよりも、次のレッスンに進まれた方が実益があるかとおもいます。

    ちなみに、書籍名はご面倒でも都度書かれた方が良いかと思います。
    時々、書籍などの教材に問題があることもありますので。

    キャンセル

  • lucia0320

    2020/07/15 10:15 編集

    分かりました。ありがとうございます。
    次回から書籍名を明記いたします。

    ちなみに下記のエラーがTwitterアイコンを押したときに出ていたのですが参考になりますでしょうか。

    2020-07-15 10:03:25.962046+0900 MyCamera[18359:2286135] [core] SLRemoteComposeViewController: (this may be harmless) viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
    2020-07-15 10:03:25.962137+0900 MyCamera[18359:2286135] viewServiceDidTerminateWithError:: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}

    また、これが原因かわからないのですが
    調べていたら下記のサイトを見つけました。

    https://qiita.com/iceApp/items/658f5ccf27f99ce64867

    当該サイトでは画像のリサイズをするとのことで
    下記のコードを追加したのですが、私の書き方が悪いのかエラーになってしまいます・・・。

    let resizeImage = shareItems?.fixedOrientation()?.shareItems()

    キャンセル

  • fuzzball

    2020/07/15 12:51

    >>次回から書籍名を明記いたします。
    今回から記載して下さい。

    キャンセル

回答 1

checkベストアンサー

0

症状を確認しました。
カメラで撮影した画像の大きさが Twitter の規定サイズを超えていたため、途中で落ちていたようです。

たしかに、コメントで参考にされた Qiita の記事の通りなのですが、この記事はさらに参考にすべきところがありますので、ソースコードにはそれも反映させる必要があります。

まずは、圧縮処理を行わせるためのコードを追加する必要があります。
これは、

の通りなのですが、一部 Swift5 ではメソッド名(関数名)が変わっているようですので、次のように変更する必要があります。

extension UIImage {

    /// 上下逆になった画像を反転する
    func fixedOrientation() -> UIImage? {
        if self.imageOrientation == UIImage.Orientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        return newImage
    }

    /// イメージ縮小
    func resizeImage(maxSize: Int) -> UIImage? {

        guard let jpg = self.jpegData(compressionQuality: 1) as NSData? else {
            return nil
        }
        if isLessThanMaxByte(data: jpg, maxDataByte: maxSize) {
            return self
        }
        // 80%に圧縮
        let _size: CGSize = CGSize(width: (self.size.width * 0.8), height: (self.size.height * 0.8))
        UIGraphicsBeginImageContext(_size)
        self.draw(in: CGRect(x: 0, y: 0, width: _size.width, height: _size.height))
        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        // 再帰処理
        return newImage.resizeImage(maxSize: maxSize)
    }

    /// 最大容量チェック
    func isLessThanMaxByte(data: NSData?, maxDataByte: Int) -> Bool {

        if maxDataByte <= 0 {
            // 最大容量の指定が無い場合はOK扱い
            return true
        }
        guard let data = data else {
            fatalError("Data unwrap error")
        }
        if data.length < maxDataByte {
            // 最大容量未満:OK ※以下でも良いがバッファを取ることにした
            return true
        }
        // 最大容量以上:NG
        return false
    }
}

上記のコードは、ViewController.swift の末尾に追加して大丈夫です。

また、画像をシェアする部分のコードは次のように変更します。

@IBAction func shareButtonAction(_ sender: Any) {
        // 表示画像をアンラップしてシェア画像を取り出す
        if let shareImage = pictureImage.image {

            // MARK: 5MB以内に収める
            let resizedImage = shareImage.fixedOrientation()?.resizeImage(maxSize: 5 * 1024 * 1024)
            // UIActivityViewControllerに渡す配列を作成
            // MARK: 圧縮後の画像を配列に入れる
            let shareItems = [resizedImage!]

            // UIActivityViewControllerにシェア画像を渡す
            let controller = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
            //iPadで落ちてしまう対策
            controller.popoverPresentationController?.sourceView = view
            //UIActivityViewControllerを表示
            present(controller, animated: true, completion: nil)
        }
    }

ここで、MARK: と書かれた部分が新たに追記したコードです。なお、一次参照された記事だと resizeImage(maxsize:)の指定がなかったのですが、実際は必要となりますのでそのように書き換えてあります。

これでおそらく問題なく投稿できるようになるかと思います。

ところで、参考にされた書籍ですが、サポート体制が非常にしっかりしているようです。

こちらに正誤表があり、かりに Xcode のバージョンアップに伴う動作不具合であっても、対処方法がきちんと掲載されています。

私が半年くらい前に見たときには Twitter のことは記載されていませんでしたし、問題も起きなかったのですが、おそらく現在の環境では発生してしまう可能性が高いと思います。

この半年間で起き得るトラブルについても、正誤表できちんと触れられていますので、是非お問い合わせフォームからも今回のトラブルについて質問者さんからお問い合わせいただければ、さらに適切な回答が得られるかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/15 12:54

    TsukubaDepot様

    ご回答ありがとうございます。
    長い時間とらせてしまって申し訳ございませんでした。

    いただいたコードで無事動作できました。
    また書籍についてもご教示頂き重ね重ねお礼を申し上げます。

    どうぞ宜しくお願いいたします。

    キャンセル

  • 2020/07/15 13:03 編集

    うまく動かない原因は、今回のように必ずしも読者に責任がない場合もかなりあります(他言語だと、コンパイルすら通らないコードが掲載されている本もあるようです)。

    書籍名が記載されていない場合、全てが質問者さんのミスと想定され、思わぬ被害を被ることもありますから、是非書籍名の記述をお願いしたいと思います。

    キャンセル

  • 2020/07/15 18:46

    ありがとうございます。
    承知しました。

    初めての書籍でここで躓くとは・・・。と幸先不安だったので
    この度は大変助かりました。

    今後とも宜しくお願い申し上げます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る