以下のような、プロフィール情報(名前・アイコン)を設定して、それらの情報とともにカメラロールから選んだ画像1枚だけを投稿できるインスタの劣化版パクリアプリを作っています。(プロジェクト名は気にしないでください、、)
現在はstoryboard下方のプロフィール設定画面(今の所firebaseにプロフィールのデータを送るところまで)とユーザーのモデル定義クラスを作っています。
プロフィール設定画面のクラス
swift
1import UIKit 2import Firebase 3 4class EditProfile: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 5 6 @IBOutlet var iconImageView: UIImageView! 7 @IBOutlet var nameTextField: UITextField! 8 9 var ref: DatabaseReference! 10 11 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 nameTextField.delegate = self 17 18 19 } 20 21 @IBAction func changeIcon(_ sender: UITapGestureRecognizer) { 22 23 if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { 24 25 let pickerView = UIImagePickerController() 26 pickerView.sourceType = .photoLibrary 27 pickerView.delegate = self 28 self.present(pickerView, animated: true) 29 30 } 31 } 32 33 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { 34 35 let image = info[UIImagePickerControllerOriginalImage] as! UIImage 36 iconImageView.image = image 37 dismiss(animated: true) 38 39 } 40 41 @IBAction func changeProfile(_ sender: Any) { 42 43 let user = User() 44 user.name = nameTextField.text! 45 user.icon = iconImageView.image! 46 47 var data: Data = Data() 48 if let image = iconImageView.image { 49 data = UIImageJPEGRepresentation(image,0.5)! as Data 50 } 51 let encodedImageData = data.base64EncodedString(options: Data.Base64EncodingOptions.lineLength64Characters) as String 52 53 let myProfile = ["myName": user.name, "myIcon": encodedImageData] 54 ref.childByAutoId().setValue(myProfile) 55 56 } 57 58 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 59 textField.resignFirstResponder() 60 return true 61 } 62 63 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 64 nameTextField.resignFirstResponder() 65 } 66 67 override func didReceiveMemoryWarning() { 68 super.didReceiveMemoryWarning() 69 // Dispose of any resources that can be recreated. 70 } 71 72}
ユーザーを定義したクラス
swift
1import UIKit 2 3class User: NSObject { 4 5 var name: String = "匿名" 6 var icon: UIImage = UIImage(named: "user.png")! 7 8}
今まではUdemyという学習サイトを見ながら、Firebaseなどのライブラリを使い、一応形だけサーバと連携して動くSNSアプリをなんとか作れるレベルだったのですがそのアプリでは、サーバから取って来た投稿をタイムラインに表示するのみで、名前をタップしてそのユーザーの詳しいプロフィールを見たり、そのユーザーの過去の投稿一覧などをみる機能はついていませんでした。
(そのアプリはユーザーモデルや投稿モデルを独自クラスで定義していなく、ばらばらのデータを配列に入れてそれをサーバに飛ばしていました。)
こんな感じです
swift
1let databaseRef = Database.database().reference() 2 3 //ユーザー名 4 let username = myProfileLabel.text 5 6 //コメント 7 let message = commentTexfView.text 8 9 //投稿画像 10 var data: NSData = NSData() 11 if let image = imageView.image { 12 data = UIImageJPEGRepresentation(image,1.0)! as NSData 13 } 14 let base64String = data.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters) as String 15 16 //プロフィール画像 17 var data2: NSData = NSData() 18 if let image2 = myProfileImageView.image { 19 data2 = UIImageJPEGRepresentation(image2,1.0)! as NSData 20 } 21 let base64String2 = data2.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters) as String 22 23 //サーバーに飛ばす箱 24 let user: NSDictionary = ["username": username!, "comment": message!, "postImage": base64String, "profileImage": base64String2] 25 databaseRef.child("posts").childByAutoId().setValue(user)
・名前をタップしてそのユーザーの詳しいプロフィールを見る機能
・そのユーザーの過去の投稿一覧などをみる機能
をつけるにはまず、ユーザーモデルや投稿モデルを独自クラスで定義してそれを利用することが必要だと講師の方に言われました。
モデル定義について調べながら作ったものが冒頭で説明したものです。
ですが、独自クラスで作った意味あるのかコレ状態になってしまいました。(結局配列で同じように送ってる、、)
上記の二つの機能を追加することを見越したユーザーモデルの定義、またそれをどのような形でfirebaseに送ればいいのでしょうか?
皆さまならどのように書いていますでしょうか?
ご存知の方がいらっしゃいましたらよろしくお願いいたします。
<追記>
変更後
swift
1import UIKit 2 3struct User { 4 let name: String 5 let icon: UIImage 6} 7 8extension User { 9 // このdictionaryはfirebaseから取得してきたデータ 10 init(dictionary: [String: Any]) { 11 self.name = dictionary["myName"] as! String 12 do { 13 let url = dictionary["iconImage"] as! String 14 let data = try Data(contentsOf: url) 15 let image = UIImage(data: data)! 16 self.icon = image 17 } catch { 18 // 何かしらのエラー処理 19 } 20 } 21} 22
間違っているのはわかるのですが、どうしてもたどり着けませんでした、、EditProfile.swiftです。
swift
1override func viewDidLoad() { 2 super.viewDidLoad() 3 4 nameTextField.delegate = self 5 6 ref.queryLimited(toLast: 1).observe(DataEventType.childAdded, with: { (snapshot) in 7 let user = User(name: "userName", icon: "userIcon") 8 nameTextField.text = user.name 9 iconImageView.image = user.icon 10 11 }) 12 13 14 } 15 16
こちらはEditProfile.swiftのプロフィール変更決定ボタンです。キーを変えました。
swift
1@IBAction func changeProfile(_ sender: Any) { 2 3 let userName = nameTextField.text 4 5 var data: Data = Data() 6 if let image = iconImageView.image { 7 data = UIImageJPEGRepresentation(image,0.5)! as Data 8 } 9 let encodedImageData = data.base64EncodedString(options: Data.Base64EncodingOptions.lineLength64Characters) as String 10 11 let user = ["userName": userName, "userIcon": encodedImageData] 12 ref.childByAutoId().setValue(user) 13 14 }
<追記2>
newmtさまにお教え頂いた様に記述したところエラーが出たのですが、修正できなかったので私の知っている、String>UIImageにする処理に直してみました。
swift
1extension User { 2 // このdictionaryはfirebaseから取得してきたデータ 3 init(dictionary: [String: Any]) { 4 self.name = dictionary["myName"] as! String 5 do { 6 /* 7 let url = dictionary["iconImage"] as! String 8 let data = Data(contentsOf: url) 9 let image = UIImage(data: data)! 10 self.icon = image 11 */ 12 13 let decodeData = (base64Encoded: dictionary["iconImage"]) 14 let decodedData = Data(base64Encoded: decodeData as! String, options: Data.Base64DecodingOptions.ignoreUnknownCharacters) 15 let decodedIcon = UIImage(data: decodedData! as Data) 16 self.icon = decodedIcon! 17 18 } catch { 19 // 何かしらのエラー処理 20 } 21 } 22} 23
ビルドしてeditProfile.swiftの対応する画面のタブをタップしたところ、editProfile.swiftのviewDidLoadでエラーがおきました。
as!周りをアンラップしろ。ということまではわかったのですが、この場合どう修正するのでしょうか?
私の修正のせいかもしれません、、
調べながらやってはいるのですが、どんどん質問が増えてしまって申し訳ありません、、
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/18 05:39 編集
2018/03/18 10:41
2018/03/18 22:13
2018/03/19 04:53
2018/03/19 06:03
2018/03/19 09:04 編集
2018/03/19 10:35
2018/03/19 11:30
2018/03/20 08:30
2018/03/20 12:13 編集