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

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

ただいまの
回答率

87.48%

アルバムの写真をCellに表示できない

解決済

回答 1

投稿 編集

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

score 3

画像加工ができるアプリを開発しています

アルバムの画像をCollectionViewのCellに、複数枚表示しようと考えていますが表示されません。

記事をたくさん読みすぎてコードがごちゃごちゃになっている気がしています...。
もし対処法がわかる方いらっしゃいましたら、教えていただけると幸いです

⑴画像を表示するためのViewControllerです

import UIKit
import Photos
import DKImagePickerController

class MakeViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    @IBOutlet var cameraImageView : UIImageView!
    @IBOutlet var filterButton : UIButton!
    @IBOutlet var editButton : UIButton!
    @IBOutlet var collectionView : UICollectionView!

    //画像加工するための元となる画像
    var originalImage: UIImage!

    //画像加工するフィルターの宣言
    var filter: CIFilter!

    override func viewDidLoad() {
        super.viewDidLoad()
        //UICollectionViewFlowLayoutをインスタンス化
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 15, left: 5, bottom: 15, right: 5)//レイアウトを調整
        layout.minimumInteritemSpacing = 0
        collectionView.collectionViewLayout = layout

        collectionView.delegate = self
        collectionView.dataSource = self
    }

    //表示するセルの数
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
           //今回はセルを9個にしてみる
           return 9
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
           //表示するCellの登録
           let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MyCustomCell
          cell.cameraImageView.image = originalImage

           return cell
       }

    //セルの配置について決める
      func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
          let horizontalSpace : CGFloat = 10
          let cellSize : CGFloat = self.view.bounds.width / 3 - horizontalSpace
          return CGSize(width: cellSize, height: cellSize)
      }

    //カメラロールにある画像を読み込むメソッド
    @IBAction func openAlbum(){

        let pickerController = DKImagePickerController()
        // 選択可能な枚数を9にする
        pickerController.maxSelectableCount = 9
        pickerController.didSelectAssets = { [unowned self] (assets: [DKAsset]) in

        // 選択された画像はassetsに入れて返却されるのでfetchして取り出す
        for asset in assets {
        asset.fetchFullScreenImage(completeBlock: { (image, info) in
        // ここで取り出せる
        self.cameraImageView.image = image
                    })
                }
            }
               self.present(pickerController, animated: true) {}
                performSegueToEdit()
                performsegueToFilter()
             }

    func performSegueToEdit(){
        performSegue(withIdentifier: "toEditViewController", sender: nil)
    }
    func performsegueToFilter(){
        performSegue(withIdentifier: "toFilterViewController", sender: nil)
    }

    @IBAction func back(){
          self.dismiss(animated: true, completion: nil)
      }
}

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
⑵画像を表示したいCellのコードです

import UIKit
import DKImagePickerController

class MyCustomCell: UICollectionViewCell, UIImagePickerControllerDelegate {
    @IBOutlet weak var cameraImageView: UIImageView!
    var originalImage: UIImage!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    //カメラ、カメラロールを使った時に選択した画像をアプリ内に表示するためのメソッド
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){

        cameraImageView.image = info[.editedImage] as? UIImage

        originalImage = cameraImageView.image //カメラで写真撮った後に画像を加工する元画像として記憶しておく
    }


}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

コードを切り貼りする作業そのものは否定いたしませんが、それぞれのコードを役割をよく理解した上でつなぎ合わせないと、必要のない処理を入れてしまったり、同じような処理を重複して宣言したりとバグの温床になりますのでご注意ください。

とりあえず、ご提示いただいたコードをもとに、DKImagePickerController を使って選択した複数の画像を CollectionView に表示させるためのコードは次のようになります。

本質的に足りない部分は

  • DKImagePickerControllerで選択した複数の画像を一旦配列に保存する部分
  • 配列に保存された画像をセルに反映される部分
    と少ないのですが、いくつかのコードを切り貼りした結果、余分な部分もかなりありましたのでコメントアウトしてあります。

新しい処理を追加する際には、もしそのコードの理解が不十分であれば、無闇に現在のプロジェクトに追加せず、まずは新しい処理だけに特化したごく簡単なサンプルプログラムを作成し、その処理を理解した上で追加した方がより見通しの効く作業になります。

コード中のコメントも合わせて参考にしていただければと思います。

import UIKit
import Photos
import DKImagePickerController

// MARK: 削除 - 必要のないプロトコルは削除する。
// DKImagePickerController を使うのであれば、UIImagePickerControllerDelegate,UINavigationControllerDelegate は関係ないので削除
//class MakeViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
class MakeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    // MARK: 削除 - 使わないアウトレットは削除
//    @IBOutlet var cameraImageView : UIImageView!
//    @IBOutlet var filterButton : UIButton!
//    @IBOutlet var editButton : UIButton!
    @IBOutlet var collectionView : UICollectionView!
    // MARK: 追加 - 選択した画像を保存する配列
    var imageArray : [UIImage] = [UIImage]()

    // MARK: 削除 - 使わないプロパティは削除
    //画像加工するための元となる画像
    //var originalImage: UIImage!
    //画像加工するフィルターの宣言
    //var filter: CIFilter!

    override func viewDidLoad() {
        super.viewDidLoad()
        //UICollectionViewFlowLayoutをインスタンス化
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 15, left: 5, bottom: 15, right: 5)//レイアウトを調整
        layout.minimumInteritemSpacing = 0
        collectionView.collectionViewLayout = layout

        collectionView.delegate = self
        collectionView.dataSource = self
    }

    //表示するセルの数
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // MARK: 変更 - セルの数は固定にするのではなく、iamgeArray の数に合わせて動的に変更する
        //今回はセルを9個にしてみる
        // return 9
        return imageArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        //表示するCellの登録
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MyCustomCell
        // MARK: 変更 - 選択する画像は一つではなく「複数」なので、セルに配置する画像は配列に入れた画像を順次利用する
        //cell.cameraImageView.image = originalImage
        cell.cameraImageView.image = imageArray[indexPath.row]

        return cell
    }

    //セルの配置について決める
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let horizontalSpace : CGFloat = 10
        let cellSize : CGFloat = self.view.bounds.width / 3 - horizontalSpace
        return CGSize(width: cellSize, height: cellSize)
    }

    //カメラロールにある画像を読み込むメソッド
    @IBAction func openAlbum(){

        let pickerController = DKImagePickerController()
        // 選択可能な枚数を9にする
        pickerController.maxSelectableCount = 9
        pickerController.didSelectAssets = { [unowned self] (assets: [DKAsset]) in
            // MARK: もし、DKImagePickerController を呼び出すごとに配列をリセットするのであれば、次の行を有効にする
            // self.imageArray.removeAll()

            // 選択された画像はassetsに入れて返却されるのでfetchして取り出す
            for asset in assets {
                asset.fetchFullScreenImage(completeBlock: { (image, info) in
                    // ここで取り出せる
                    // MARK: 変更 - 複数枚選択するので、配列に代入する
                    //self.cameraImageView.image = image
                    // MARK: image が nil の場合は早期リターン
                    guard let appendImage = image else {
                        return
                    }

                    // MARK: 追加 - 配列 imageArray に選択した画像を追加し、collectionView をリロードして追加した画像を表示させる
                    self.imageArray.append(appendImage)
                    self.collectionView.reloadData()
                })
            }
        }
        self.present(pickerController, animated: true) {}
        // MARK: 削除 - 先日の質問で指摘した「余分な処理」が残ったままなので削除
        //performSegueToEdit()
        //performsegueToFilter()
    }

    func performSegueToEdit(){
        performSegue(withIdentifier: "toEditViewController", sender: nil)
    }
    func performsegueToFilter(){
        performSegue(withIdentifier: "toFilterViewController", sender: nil)
    }
}
import UIKit
import DKImagePickerController

// MARK: -  削除
// DKImagePickerController を使うのであれば、UIImagePickerControllerDelegate は必要ない
//class MyCustomCell: UICollectionViewCell, UIImagePickerControllerDelegate {
class MyCustomCell: UICollectionViewCell {
    @IBOutlet weak var cameraImageView: UIImageView!
    // MARK: 削除
    //var originalImage: UIImage!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    // MARK: 削除 - DKImagePickerController を使うのであれば必要ない
    // そもそも、セルに画像を入れる処理は MainViewController で行えば良いので必要ない
//    //カメラ、カメラロールを使った時に選択した画像をアプリ内に表示するためのメソッド
//    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
//
//        cameraImageView.image = info[.editedImage] as? UIImage
//
//        originalImage = cameraImageView.image //カメラで写真撮った後に画像を加工する元画像として記憶しておく
//    }
//
//
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/14 12:15

    昨日書き直す中でvar imageArray : [UIImage] = [UIImage]()の追加や
    performSegueToEdit()とperformsegueToFilter()の削除は行っていたのですが、書き直す以前のコードを載せてしまっていました。編集のお手数をおかけしてしまい申し訳ありません。
    TsukubaDepot様の仰るようにコードに対する理解が追いついていなかったと反省しています。2週間でアプリをリリースするというスクールの課題があり、期日に追われて基礎が曖昧になっていました。
    無事TsukubaDepot様のようにコードを書き直したところ、複数枚表示することができました!!ありがとうございます。
    最後に一点だけ質問をお伺いしたいのですが、この画像を画面遷移する際には下のようにprepareのコードが必要だと思います。

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "toEditViewController"{
    let EditViewController: EditViewController = segue.destination as! EditViewController

    //EditViewController.originalImage = self.cameraImageView.image
    }
    もうcameraImageViewはないので、cameraImageViewのところにimageArray[indexPath.row]を代入することはできないのでしょうか?
    EditViewの方でもコードを書き直し、UIImageであるoriginalImageをimageArray[indexPath.row]にする予定です。

    キャンセル

  • 2020/06/14 18:14

    値渡しですが、1)どのような条件のときに 2) どのようなデータを渡す、ということが質問者さんで明確になっていない限り何とも言えません。
    1)はたとえば「画面上のボタンを押したとき」など、Segueを実行する条件、2)は何枚も選んだ写真すべてのデータなのか、それとも特定の一枚なのか、ということなどです。
    もしご自身の中で明確になっていないようであればそれをまず明確にし、遷移先の画面で何を表示したいのかも決めた上、まずは実装してみてはいかがでしょうか。

    もちろん、それでも思いつかないのであれば、新しい質問として立ち上げていただければわかる範囲でアドバイスいたします。

    キャンセル

  • 2020/06/14 22:26

    @TsukubaDepot様
    丁寧にご返信下さりありがとうございます。
    ⑴ボタンを押した時に⑵複数画像のまま遷移させるという条件を考えています
    いま自分で実装していたところ遷移前のコードエラーは解決したのですが遷移先のコードで大量にエラーが出てしまいます。
    もう少し自力で取り組んでみようと思いますが、何度試しても解決策がわからなかった場合またteratail上で質問させて頂きたいです
    この度は複数枚表示に関して明確なアドバイスを頂きありがとうございました。

    キャンセル

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

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

関連した質問

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