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

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

ただいまの
回答率

90.34%

  • Swift

    7656questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Realm

    218questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

String型からUIImageに変換した値をUICollectionViewに全部違う値で表示させたい。

解決済

回答 1

投稿

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

 Realmで保存したString型の配列にある写真の値をloop文で回しながらUIImage型に変換して、UICollectionViewCellにそれぞれの値で格納したい。

こんにちは、質問失礼致します。
現在、Realmのファイルに保存されているデータを取得し、そのデータの中に保存されているimageStringという変数に写真のデータがString型の配列で保存されているので、String型の配列にあるデータをloop文で回し、 base64 を使用してUIImage型の配列に変換し、UICollectionViewのcellにUIImageViewがあるので、そこのimageViewに値を入れたいと考えています。これは前回teratailで質問させていただき解決したのですが、UICollectionViewのCellに表示をさせる部分でCellに同じ写真が表示されてしまいます。セルをタップしてその写真の画面に遷移すると、それぞれの画像の値が取得され表示されるのですが、問題はUICollectionViewで配列のデータを全て表示させる時に全部同じ写真が表示されてしまうことです。
解決できず困っています。どなたかご教授いただければ幸いです。よろしくお願い致します。

 該当のソースコード

 // CollectionViewのCellの数を返す
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return allArray.count
  }

  // collectionViewのCellの内容を返す
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = totalXib.totalCollectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
    // もしallArrayのcountが0だったら
    if allArray.count == 0 {
      print("DEBUG_PRINT: allArrayのデータが0です")
    } else if allArray.count > 0 {
      print("DEBUG_PRINT: allArrayのデータが0以上です")

      // for文でallArrayをloopさせ全ての要素を取り出す
      for allArrayValue in allArray {
        var image: UIImage
        image = UIImage(data: Data(base64Encoded: allArrayValue.imageString, options: .ignoreUnknownCharacters)!)!

        cell.imageView.image = image
      }
    }
    return cell
  }

 試したこと

for文の部分でimageを配列で定義し、 cell.imageView.image = image[indexPath.row] で値を格納しようとしましたが、 index out of range のシグバートエラーが発生してしまいました。この時に配列の数以上のものを取得しようとしていたわけでもなくエラーが出てしまった為、なぜそのようなエラーが発生したかもはっきりと理解出来ずにいます。そこの部分ももしよろしければ教えて頂けるとありがたいです。

 補足情報(FW/ツールのバージョンなど)

Xcode Version 9.3.1

よろしくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • tyobigorou

    2018/05/29 01:13 編集

    "for文の部分でimageを配列で定義し、 cell.imageView.image = image[indexPath.row]" ソースに書いてないような。colloectionView(cellforItem)は、allArray.count回呼ばれるので、for 文を使った、image配列の生成は他の箇所で行った方がよいのではないかと思います。
    print("DEBUG_PRINT: allArrayのデータが0以上です")が何回もコンソールに表示されませんか?

    キャンセル

  • crea7dosSantos

    2018/05/29 02:36

    質問に対してのコメントありがとうございます。現在質問させていただいている同じ写真がCollectionViewの画面で表示されてしまうという状態に関しては上のソースでビルドをした時の現象なので、for文の部分でimageを配列で定義し、 cell.imgeView.image = image[indexPath.row]の部分に関してはソース上には記載せず、試したことの部分に書かせいただきました。print("DEBUG_PRINT: allArrayのデータが0以上です")は確かにallArray.count文だけ表示されています。for文を使ってRealmの配列から型変換を行う部分を他の箇所で行うとは、具体的にどこで行えばいいのでしょうか?このメソッドの中でimage配列を生成しなければCollectionView(cellforItem)に値を入れられないと思っていたのですが違うのでしょうか?ご教授お願いしたいです。

    キャンセル

  • tyobigorou

    2018/05/29 02:55 編集

    型の変換は、今の場所でもできますが、realmからのデータ読み込み完了時とかがよいのでは?
    エラーが出ているコードを載せてもらえると回答するのが楽になるのですが…。

    キャンセル

回答 1

checkベストアンサー

+1

コードがないので、憶測ですが、こんなふうに書かれてれば、index out of range

// collectionViewのCellの内容を返す
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = totalXib.totalCollectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
    // もしallArrayのcountが0だったら
    if allArray.count == 0 {
        print("DEBUG_PRINT: allArrayのデータが0です")
    } else if allArray.count > 0 {
        print("DEBUG_PRINT: allArrayのデータが0以上です")

        // for文でallArrayをloopさせ全ての要素を取り出す
        for allArrayValue in allArray {
            var image = [UIImage]()
            image.append(UIImage(data: Data(base64Encoded: allArrayValue.imageString, options: .ignoreUnknownCharacters)!)!)

            cell.imageView.image = image[indexPath.row]
        }
    }
    return cell
}


これなら一応、index out of rangeにならずにうごくかな?

// 配列をメソッドのスコープの外で定義
var imageArray = [UIImage]()

// collectionViewのCellの内容を返す
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = totalXib.totalCollectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
    // もしallArrayのcountが0だったら
    if allArray.count == 0 {
        print("DEBUG_PRINT: allArrayのデータが0です")
    } else if allArray.count > 0 {
        print("DEBUG_PRINT: allArrayのデータが0以上です")

        // for文でallArrayをloopさせ全ての要素を取り出す
        for allArrayValue in allArray {
            var image: UIImage
            image = UIImage(data: Data(base64Encoded: allArrayValue.imageString, options: .ignoreUnknownCharacters)!)!
            imageArray.append(image)
        }
        cell.imageView.image = imageArray[indexPath.row]
    }
    return cell
}


で、型変換をする場所は状況によるのでなんとも?なのですが、コレとかが非常に参考になると思います。
https://teratail.com/questions/115488

気になったところがあるので追記します。
これ↓は、

if allArray.count == 0 {
        print("DEBUG_PRINT: allArrayのデータが0です")
    } else if allArray.count > 0 {
        print("DEBUG_PRINT: allArrayのデータが0以上です")


これ↓が、allArray.count==0なら、Cellの数が0になって、collectionViewのCellの内容を返すメソッド(cellForItemAt)が動かないのでうえ↑いらないのでは?

// CollectionViewのCellの数を返す
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return allArray.count
  }

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/29 15:20

    ありがとうございます。お陰様で狙っていた機能の実装が出来ました!
    UIImage型の配列をメソッドの外で定義し、そこの配列にfor文で型変換した値を追加していくことで index out of rangeのエラーも出ずに無事ビルドに成功しました。とても勉強になり感謝いたします。
    追記の部分に関してですが、nilチェックをしていたつもりでしたが、教えていただいた通り、allArrayのcountが0ならCellの数が0になり、collectionViewのcellForItemAtが動かないので必要のないコードでした。
    ご指摘いただきありがとうございます。
    ご指摘いただいた型変換を行う場所のことですが、非常に納得出来ました。今回のようにクラスのプロパティとしてUIImage型の配列を生成しておき、viewWillAppearメソッドの中でRealmの値を取得し、UIImage型に反感した値を今回と同様にappendメソッドで配列に追加すればいいということでよろしかったでしょうか?
    今回は本当にありがとうございました。教えていただいたことを忘れずこれからの勉強にも励んでいけたらと思います。
    ありがとうございます!

    キャンセル

  • 2018/05/29 16:45 編集

    表示ができたようでよかったです。

    型変換についてですが、回答を書く際に気が付かなかったので、追記します。
    きちんと動いて、役に立つようでしたら使ってください。

    えー、画像の配列を2つ持つのも無駄だと思うので、新たな配列の定義をせずに、
    collectionView(cellForItemAt )の中で、

    let cell = ...
    // indexPath.item(indexPath.row)に対応するデータを配列から取り出す。
    let arrayValue = allArray[indexPath.item]
    // 取り出したデータをUIImageに変換する
    let image = = UIImage(data: Data(base64Encoded: arrayValue.imageString, options: .ignoreUnknownCharacters)!)!
    // cellのイメージに設定する
    cell.imageView.image = image
    return cell

    という流れが、きちんと動けばですが、一番シンプルなのかなと思います。

    キャンセル

  • 2018/05/29 17:09

    ご指摘ありがとうございます。
    今教えていただいた方法でコードを書いてみましたがこちらでも正常に動作することが出来ました!
    確かにこちらのコードの方がfor文を使用せず、コードの量も少なく済むのでこちらのコードを使用したいと思います。
    様々なことを教えていただき本当にありがとうございました!

    キャンセル

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

  • Swift

    7656questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Realm

    218questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。