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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Realm

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

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

Q&A

解決済

1回答

376閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

Realm

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

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

0グッド

0クリップ

投稿2018/05/14 01:56

編集2018/05/14 13:04

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

こんにちは、質問失礼致します。
現在、Realmのファイルに保存されているデータを取得し、そのデータの中に保存されているimageStringという変数に写真のデータがString型の配列で保存されているので、String型の配列にあるデータをloop文で回し、 base64 を使用してUIImage型の配列に変換し、UICollectionViewのcellにUIImageViewがあるので、そこのimageViewに値を入れたいと考えています。

該当のソースコード

swift

1import UIKit 2import RealmSwift 3import SVProgressHUD 4 5class CategoryPhotoUpViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource { 6 @IBOutlet weak var categoryCollectionView: UICollectionView! 7 8 let realm = try! Realm() 9 10 var morningArray = try! Realm().objects(Morning.self).sorted(byKeyPath: "id", ascending: false) 11 12 var categoryXib: XibCategoryPhotoView! 13 14 override func viewDidLoad() { 15 16 // もしmorningArrayの数が0だったら遷移元の画面に戻る 17 if morningArray.count == 0 { 18 self.navigationController?.popViewController(animated: true) 19 } 20 print("DEBUG_PRINT: morningControllerが表示されました") 21 print("DEBUG_PRINT: (morningArray.count)") 22 categoryCollectionView.delegate = self 23 categoryCollectionView.dataSource = self 24 25 categoryXib = XibCategoryPhotoView() 26 categoryCollectionView.reloadData() 27 28 } 29 30 override func didReceiveMemoryWarning() { 31 } 32 33 override func viewWillAppear(_ animated: Bool) { 34 categoryCollectionView.reloadData() 35 print("DEBUG_PRINT: 画面を更新します") 36 } 37 38 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 39 print("DEBUG_PRINT: 数を返します") 40 return morningArray.count 41 } 42 43 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 44 let cell = categoryCollectionView.dequeueReusableCell(withReuseIdentifier: "Cell2", for: indexPath) as! CategoryCollectionViewCell 45 if morningArray.count == 0 { 46 print("DEBUG_PRINT: morningArrayのデータが0です") 47 } else if morningArray.count > 0 { 48 print("DEBUG_PRINT: morningArrayのデータが0以上です") 49 50 for morningArrayValue in morningArray { 51 for imageStringer in morningArrayValue.imageString { 52 var image: UIImage 53 image = UIImage(data: Data(base64Encoded: String(imageStringer), options: .ignoreUnknownCharacters)!)! 54 55 cell.imageView.image = image 56 print("DEBUG_PRINT: cellのイメージに値をセットしました。") 57 print("DEBUG_PRINT: (String(describing: cell.imageView.image))") 58 } 59 } 60 } 61 return cell 62 } 63 64 // セルサイズの自動変更を設定する 65 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 66 let width: CGFloat = view.frame.width / 3 - 1 // self.viewを/3し、-1は隙間の部分 67 let height: CGFloat = width 68 69 return CGSize(width: width, height: height) 70 } 71}

試したこと

for loop文でRealmからデータを取得している変数 morningArray を回しており、次のfor文で morningArrayから取得したデータ morningArrayValueimageStringのデータを与え回しています。変数 imageStringerbase64 を使用しUIImage型に変換しようと考えています.
シグバートエラーが image = UIImage(data: Data(base64Encoded: String(imageStringer), options: .ignoreUnknownCharacters)!)! の部分で出ています。

イメージ説明

デバックエリアはこのようになっていて、imageに何かしらの値は入ってるように感じるのですが、imageにString型のデータをUIImage型に変換して入れようとするところで止まってしまいます。これはなぜ変数imageにUIImage型で値が入らないのでしょうか?基本的には1つ上の部分のif文で morningArray の数が0以上であることは確認してあるのでnilが入ることはないと思ってるのですが、何かコードに不備があるのでしょうか?
ご存知の方がいらっしゃったらご教授いただけるとありがたいです。
初心者なので至らない点もあると思いますがよろしくお願い致します。

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

Xcode Version 9.3.1

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

追記

import RealmSwift class Morning: Object { // 管理用 ID。プライマリーキー @objc dynamic var id = 0 // 投稿ID @objc dynamic var postID = "" // UserName @objc dynamic var userName = "" // ImageString @objc dynamic var imageString = "" // caption @objc dynamic var caption = "" // date @objc dynamic var time = "" override static func primaryKey() -> String? { return "id" } }
// Date.timeIntervalSinceReferenceDateメソッドだけを取り出し、コードの量を減らす let timer = Date.timeIntervalSinceReferenceDate // もしもMorningSwitchがtrueだったら if morningSwitch.isOn == true { let morning = Morning() morning.time = String(timer) let morningArray = realm.objects(Morning.self) // もしもmorningArrayのcountプロパティが0じゃなかったら if morningArray.count != 0 { morning.id = morningArray.max(ofProperty: "id")! + 1 } try! realm.write { // タグmorningに投稿情報が保存される時 morning.caption = self.textField.text! morning.userName = (Auth.auth().currentUser?.displayName!)! morning.imageString = imageData!.base64EncodedString(options: .lineLength64Characters) // 日付の値を取得する morning.time = String(timer) realm.add(morning, update: true) } }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

修正版の回答

内側のループが不要です。
.imageString(String型)を内側のfor文で分解してしまっていたためにCharactrer型になっていました。
内側のループを削除することにより、morningArrayValue.imageStringでBase64エンコード文字列を参照できるようになります。

swift

1for morningArrayValue in morningArray { 2 //for imageStringer in morningArrayValue.imageString { //※削除 3 var image: UIImage 4 image = UIImage(data: Data(base64Encoded: morningArrayValue.imageString, options: .ignoreUnknownCharacters)!)! 5 6 cell.imageView.image = image 7 print("DEBUG_PRINT: cellのイメージに値をセットしました。") 8 print("DEBUG_PRINT: (String(describing: cell.imageView.image))") 9 //} //※削除 10}

最初の回答

Base64のデコード(String→Data)か、Data→UIImageで失敗しています。
ひとまず、内側のループを下記のコードに置き換えてどうなるか教えて下さい。

swift

1for imageStringer in morningArrayValue.imageString { 2 if let data = Data(base64Encoded: String(imageStringer), options: .ignoreUnknownCharacters) { 3 if let image = UIImage(data: data) { 4 print(image) 5 /* 6 cell.imageView.image = image 7 print("DEBUG_PRINT: cellのイメージに値をセットしました。") 8 print("DEBUG_PRINT: (String(describing: cell.imageView.image))") 9 */ 10 } else { 11 print("error: data to image (count=(data.count)") 12 } 13 } else { 14 print("error: string to data [(String(imageStringer).prefix(10))]") 15 } 16}

強制アンラップ!は使わないクセを付けた方がいいです。

投稿2018/05/14 02:22

編集2018/05/15 02:45
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/05/14 02:59 編集

ご回答ありがとうございます。 data to image (count= 0 となっており、 error: string to data の部分では様々な文字列が取り出されています。 またシグバートエラーは発生していません。 Base64のデコードで失敗しているということですが、 data.count で 0 が出てしまっているという事はString型からdata型に変換する部分で失敗していると考えてよろしいのでしょうか? また質問させていただいた時のコードでは強制アンラップを使用しないとエラーが出てしまっていたので、その表示に従い強制アンラップをしてしまっていたのですが、その場合は強制アンラップを使用しなくてもエラーが出ないコードに書き換える必要があったという認識で間違い無いでしょうか?
fuzzball

2018/05/14 04:01

>>`data.count` で0が出てしまっているという事はString型からdata型に変換する部分で失敗していると考えてよろしいのでしょうか? そうです。全て失敗しているのでしょうか?Base64エンコードはどのようにしているのでしょうか? (ちなみに「様々な文字列」というのはBase64エンコードされた文字列の冒頭部分です) >>その場合は強制アンラップを使用しなくてもエラーが出ないコードに書き換える必要があったという認識で間違い無いでしょうか? はい、その認識で合っています。強制アンラップ(Forced Unwrapping)を使うと今回のような場合にアプリが落ちてしまいます。 アンラップの方法はいくつかありますが、私のコードでは if let(Optional Binding)を使ってアンラップしています。
退会済みユーザー

退会済みユーザー

2018/05/14 08:23

ご回答ありがとうございます。 ご丁寧に教えていただき感謝します。 全て失敗しているとはどういう意味なのでしょうか? https://gyazo.com/2e0b2aece772b2256cd41688fed9ad5b あと少し質問させていただきたいのですが、imageStringerにこのような Character型の値が入っていて、Character型がString型の一種というのは理解しているのですが、これは正常に値が取り出せているのでしょうか? 申し訳ないのですが、教えていただきたいです。
fuzzball

2018/05/14 08:42 編集

全てというのは「morningArrayの全て」という意味です。言い換えると「全ての画像で失敗しているのでしょうか?」ということです。 >>Character型の値が入っていて... 一つでいいので string to data の出力を教えていただけますか? 「様々な文字列」と書いてあったのでBase64エンコードされた文字列が表示されていると思っていたのですが、もしかして一文字しか表示されていないのでしょうか?
退会済みユーザー

退会済みユーザー

2018/05/14 11:09

ご回答ありがとうございます。 morningArrayの全てで失敗しているかとの事ですが配列に3つの要素がある場合でも data to image (count=0なので全ての値の変換に失敗しています。 はい、 string to data [9] のような形で複数の値が出力されています。 error: string to data [/] error: string to data [9] error: string to data [j] error: string to data [/] error: string to data [4] error: string to data [A] error: string to data [A] error: string to data [Q] error: string to data [S] error: string to data [k] error: string to data [Z] error: string to data [J] error: string to data [R] error: string to data [g] コメントの仕方に分かりにくい点があり、申し訳ありませんでした。 このようにいくつもの文字列が表示されています。
fuzzball

2018/05/14 12:05

やはり一文字しかないようですね。 .imageStringの型はStringなのでしょうか?差し支えなければMorningクラスの定義を書いて下さい。 あとは、DB登録時のコードと。 Realmのことをよく知らないのであまり力になれないかもしれませんが‥。
退会済みユーザー

退会済みユーザー

2018/05/14 13:06 編集

お付き合いいただきありがとうございます。 Morningクラスの定義は追記の通りになっております。 またこのようにしてMorningクラスの場合、DBに書き込みも追記した通りになっております。
fuzzball

2018/05/14 12:40

追加のコードは質問内に追記して下さい。 で、クラス定義で型を明示するとどうなるでしょうか? @objc dynamic var imageString: String = ""
退会済みユーザー

退会済みユーザー

2018/05/14 12:57

失礼致しました、以後気をつけたいと思います。 クラス定義で型を明示して見ましたがデバックエリアに出力される値は今までの結果と同じものでした。
fuzzball

2018/05/14 12:59

以後ではなく、今から実践して下さい。 (質問内の追記し、コメント欄のコードは削除して下さい) で、保存するところからやり直しましたか?
退会済みユーザー

退会済みユーザー

2018/05/14 13:16

失礼致しました。 はい、アプリを削除し、保存するところからやり直して見ましたが、デバックエリアに出力される値に変化はありませんでした。 しかし、もう一度 Morning クラスの Realmファイルを見直して見て気が付いたのですが、 id や userName や caption などのプロパティはそれぞれの値で保存がされているのですが、imageStringだけ全部の要素の値が恐らく同じで保存されていました。 Firebaseで写真をData型に変換し、String型に変換させた部分では正しく長い文字列の後に、Lengthという部分があり、その部分が各それぞれ値が違うのですが、RealmのimageStringのプロパティを見ても全部の要素で長い文字列が同じであり、Lengthという部分が保存されていません。 分かりにくい説明で申し訳ありません。 このRealmに保存する際の部分が今回のエラーの原因と考えていいのでしょうか?
fuzzball

2018/05/14 13:33

RealmもFirebaseもよく分からないのでコメント出来ません。 今は開発環境も無いので試すことも出来ず、時間が取れたら明日試してみます。
退会済みユーザー

退会済みユーザー

2018/05/14 13:58

分かりにくい質問に対し、丁寧に教えていただきありがとうございます。 何か分かりましたら教えていただければ幸いです。 よろしくお願い致します。
fuzzball

2018/05/15 02:46

回答を追記しました。
退会済みユーザー

退会済みユーザー

2018/05/15 03:07

今ビルドをして確認したところ、正しくMoningクラスに保存をした写真のデータのみが表示されました。ここの処理でずっと引っかかっていた為本当に嬉しく感謝の気持ちでいっぱいです。 本当にお手数をおかけして申し訳ありませんでした。 今回ご教授いただいたことを忘れずこれからも頑張りたいと思います。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問