前提・実現したいこと
現在、SNSアプリを作成しています。そのため、CoreDataを使用しています。
NSAttributedString 中に画像を挿入して、タイムラインに投稿する仕組みをその一部に実装しました。
CoreData にその画像つき文章を保存して、それをタイムラインに表示する所までは上手くいっております。
ですが下記の画像のように、アプリのキル(ホームボタンを二回押してフリップして終了)をしてまたアプリを開くと、画像だけが表示されません。
この時でも、ちゃんと画像が表示されるようにしたいと考えています。
以下、質問をする上で必要と思われる情報を記載してゆきます。
CoreData の Attribute
Attribute の type を Transformable。Custom Class を NSAttributedString にする事で保存をしています。Attribute の名前はpostedAttrText
にしました。
画像の挿入
imagePickerが画像を取得し終えたときに、テキスト内に画像を入れて、そのテキストを textView の attributedText に代入するということをしています。もしかしたらこの時にimagePickerが拾った画像のデータ(?)と、アプリを消してまた表示した際のデータにくい違いがあるのではないかとも考えました。
Swift
1func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 2 if let image: UIImage = info[.originalImage] as? UIImage { 3 //画像選択時のカーソル位置を取得 4 var currentPosition: Int = 0 5 if let selectedTextRange = textView.selectedTextRange { 6 currentPosition = textView.offset(from: textView.beginningOfDocument, to: selectedTextRange.start) 7 } else { 8 currentPosition = textView.text.count 9 } 10 11 let fullString: NSMutableAttributedString = NSMutableAttributedString(string: "") 12 let leftString: NSAttributedString = textView.attributedText.attributedSubstring(from: NSRange(location: 0, length: currentPosition)) 13 let paddingRow: NSAttributedString = NSAttributedString(string: "\n") 14 let rightString: NSAttributedString = textView.attributedText.attributedSubstring(from: NSRange(location: currentPosition, length: textView.text.count-currentPosition)) 15 let textViewWidth: CGFloat = textView.frame.width 16 let imageSize: CGSize = image.size 17 let newImageSize: CGSize = CGSize(width: textViewWidth, height: textViewWidth * imageSize.height / imageSize.width) 18 let imageAttachment: NSTextAttachment = NSTextAttachment(image: image.reSizeImage(reSize: newImageSize))//reSizeImage...UIImageのExtension 19 let imageString: NSAttributedString = NSAttributedString(attachment: imageAttachment) 20 21 //How to image alignment to center??? 22 23 //padding がないと、画像真っ黒になる。 24 fullString.append(leftString) 25 fullString.append(paddingRow) 26 fullString.append(imageString) 27 fullString.append(paddingRow) 28 fullString.append(rightString) 29 30 textView.attributedText = fullString 31 } 32 dismiss(animated: true, completion: nil) 33}
CoreData への保存・読み込み
そのテキストのCoreDataへの保存・読み込みに関連する場面だけを切り取ってそれを簡略化すると、以下のようになります。ENTITLE は SecondTimeLineModel
としております。仮称として、保存する記述のあるクラスをSaveViewController
、読み込みの記述があるクラスをReadViewController
としています。
Swift
1class SaveViewController: UIViewController { 2 3 //CoreDataへの保存の際に必要な記述1 4 var secondTimeLineModel: [SecondTimeLineModel] = [SecondTimeLineModel]() 5 var managedObjectcontext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 10 //CoreDataへの保存の際に必要な記述2 11 let dataCondition = NSFetchRequest<SecondTimeLineModel>(entityName: "SecondTimeLineModel") 12 do{ 13 secondTimeLineModel = try managedObjectcontext.fetch(dataCondition) 14 }catch{ 15 print("Error") 16 } 17 } 18 19 //投稿ボタン押下時の処理(関係しない部分は省略) 20 @objc private func post(_ sender: UIBarButtonItem) { 21 22 let object = SecondTimeLineModel(context: managedObjectcontext) 23 24 object.postedAttrText = postAttrText//postAttrText...投稿ボタン押下時のTextView.attributedText 25 coreData.secondTimeLineModel.append(object) 26 (UIApplication.shared.delegate as! AppDelegate).saveContext() 27 } 28}
Swift
1class ReadViewController: UIViewController { 2 3 //CoreDataへの保存の際に必要な記述1 4 var secondTimeLineModel: [SecondTimeLineModel] = [SecondTimeLineModel]() 5 var managedObjectcontext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 10 //CoreDataへの保存の際に必要な記述2 11 let dataCondition = NSFetchRequest<SecondTimeLineModel>(entityName: "SecondTimeLineModel") 12 do{ 13 secondTimeLineModel = try managedObjectcontext.fetch(dataCondition) 14 }catch{ 15 print("Error") 16 } 17 } 18} 19 20//問題に無関係と思われるものは省略(heightForRowAtなど) 21extension SecondViewController: UITableViewDelegate, UITableViewDataSource { 22 23 //postedAttrTextを受け取ってTableViewCellの中のTextViewに表示する 24 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 25 26 let cell: TimeLineTableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! TimeLineTableViewCell 27 28 let datas = [ 29 "postedAttrText" : secondTimeLineModel[indexPath.row].postedAttrText! 30 ] as [String : Any] 31 32 //setUpTableViewCell...セルをセットアップするメソッド。この中の TextView の attributedText に postedAttrText を代入します。 33 cell.setUpTableViewCell(index: indexPath, datas: datas) 34 35 return cell 36 } 37}
試したこと
(追記:なぜか既に書いたはずのこの項目が消えてた・・・)
・iPhone, Xcode, Macの再起動・アップデート確認
・Use Core Dataでプロジェクトを作り直す
・英語でも日本語でも何時間か調べ尽くしたが、NSAttributedStringのCoreDataへの保存においてなぜか保存の事だけで読み込みに関する記事はなかった。
・print(postedAttrText)
を実行することで、文章中にしっかりとUIImageが入っていることを確認
・一方で、シミュレータ(実機)上で文章を選択するとそこには何もなく、コピー&ペーストしても空白しかない
補足情報(FW/ツールのバージョンなど)
macOS Catalina 10.15.7
Xcode 12.1
###回答よろしくお願いいたします
私情により時間がなく、他のコーディングを進めているうちにteratailでの回答待ちをするという形をとらせて頂きましたが、もしこのまま回答が得られなかった場合はこの問題を抽象化した簡単なプロジェクトを作成してみて、解決したら自己解決として終了。そうでなくても何か新たな事実が判明すれば追記していきたいと思います。
何かご存知の方は、是非回答をよろしくお願いしますm(_ _)m
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/27 10:27