Swift Error: EXC BAD INSTRUCTION code=EXCI386 for userid - swift

I am writing an app login page when I countered this error. I do not know how to debug it so I am asking where I coded wrong. I got a problem on the keychain wrapper code:
KeychainWrapper.standard.set((user?.uid)!,forKey: "uid")
I am following a YouTube tutorial on Swift 4, the most updated version. However, it seems this line of code has some problems, therefore I would like to know the problem in the whole code, whether I missed I bracket or failed to import.
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseCore
import SwiftKeychainWrapper
import FirebaseStorage
class ViewController: UIViewController {
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var userimageview: UIImageView!
var imagePicker: UIImagePickerController!
var selectedImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
if KeychainWrapper.standard.object(forKey: "KEY_UID") != nil {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
func storeuserdata(userId: String) {
if let imageData = UIImageJPEGRepresentation(selectedImage, 0.2) {
Storage.storage().reference().putData(imageData, metadata: nil) { (metadata, error) in
guard let metadata = metadata else {
// Uh-oh, an error occurred!
return
}
// Metadata contains file metadata such as size, content-type, and download URL.
let downloadURL = metadata.downloadURL
Database.database().reference().child("users").child(userId).setValue(["username": self.usernameField.text!,"userImg": downloadURL
])
}
}
}
#IBAction func signinpressed(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil && (self.usernameField.text?.isEmpty)! && self.userimageview.image != nil {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
self.storeuserdata(userId: (user?.uid)!)
KeychainWrapper.standard.set((user?.uid)!,forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}else {
KeychainWrapper.standard.set((user?.uid)!,forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
}
#IBAction func getPhoto (_ sender: AnyObject) {
present(imagePicker, animated: true, completion: nil)
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
selectedImage = image
}
imagePicker.dismiss(animated: true, completion: nil)
}
}

Related

How to show alerts in Swift UIKit using MVVM, Firebase and Delegates

I would like to know how can i implement a delegate or a function that helps me to show an alert in the ViewModel. Basically i need to validate two text fields and when the user writes a wrong password or a wrong email it should trigger an alert. The function to trigger this alert is inside of the ViewController and i need to create a new class (ViewModel) that helps me to validate the text fields and sign to firebase
Here is my code:
ViewController
import UIKit
import FirebaseAuth
class ViewController: UIViewController, UIWindowSceneDelegate {
//MARK: - #IBOutlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var startButton: UIButton!
//MARK: - LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
setDelegates()
startButton.isEnabled = false
}
//MARK: - Delegates
func setDelegates()->Void {
emailTextField.delegate = self
passwordTextField.delegate = self
}
// Function that i need to trigger in the ViewModel
fileprivate func showErrorMessage(_ errorMessage : String) {
let alertController = UIAlertController(title: "UPS!", message: errorMessage, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Aceptar", style: .default))
self.present(alertController, animated: true, completion: nil)
}
// Function to go to the next ViewController
fileprivate func navigateToHomeViewController() {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let homeViewController = storyBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
homeViewController.modalPresentationStyle = .fullScreen
self.present(homeViewController, animated: true, completion: nil)
}
// Function of the ViewModel all validations
fileprivate func validateUserLogin(_ error: Error?, _ result: AuthDataResult?) {
switch error {
case .some(let error as NSError) where error.code == AuthErrorCode.wrongPassword.rawValue:
// validate the text field and then show the alert, i need to this, but inside the ViewModel
self.showErrorMessage("Contraseña incorrecta")
case .some(let error as NSError) where error.code == AuthErrorCode.userNotFound.rawValue:
// validate the text field and then show the alert, i need to this, but inside the ViewModel
self.showErrorMessage("Correo incorrecto")
case .some(let error):
// validate the text field and then show the alert, i need to this, but inside the ViewModel
self.showErrorMessage("Login error: \(error.localizedDescription)")
self.hideActivityIndicatorView()
case .none:
if (result?.user) != nil {
navigateToHomeViewController()
}
}
}
#IBAction func startButtonAction(_ sender: Any) {
if let email = emailTextField.text, let password = passwordTextField.text{
// Function to sing in firebase, it would be inside the ViewModel
Auth.auth().signIn(withEmail: email, password: password){(result, error) in
self.validateUserLogin(error, result)
}
}
}
fileprivate func validateFields() -> Bool {
return (passwordTextField.text!.count >= 8) && (isValidEmail(emailTextField.text ?? ""))
}
fileprivate func updateView() {
if(validateFields()){
startButton.isEnabled = true
startButton.tintColor = UIColor.blue
}else{
startButton.isEnabled = false
startButton.tintColor = UIColor.gray
}
}
}
func isValidEmail(_ email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: email)
}
//MARK: - Text Field Delegate Methods
extension ViewController : UITextFieldDelegate{
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString
string: String) -> Bool {
if textField == self.emailTextField {
updateView()
} else if textField == self.passwordTextField {
updateView()
}
return true
}
}
StoryBoard
Here is the solution, thanks to Not Bad.
Model
import Foundation
struct User{
var email : String
var password : String
}
ViewModel
import Foundation
import FirebaseAuth
class AuthViewModel {
var delegate: AuthViewModelDelegate?
var user : User? = User(email: "", password: "")
func checkCredentials(user: User) {
Auth.auth().signIn(withEmail: user.email, password: user.password){(result, error) in
switch error {
case .some(let error as NSError) where error.code == AuthErrorCode.wrongPassword.rawValue:
self.delegate?.showError("Contraseña incorrecta")
self.delegate?.hideActivityIndicator()
case .some(let error as NSError) where error.code == AuthErrorCode.userNotFound.rawValue:
self.delegate?.showError("Correo incorrecto")
self.delegate?.hideActivityIndicator()
case .some(let error):
self.delegate?.showError("Login error: \(error.localizedDescription)")
self.delegate?.hideActivityIndicator()
case .none:
if (result?.user) != nil {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = storyboard.instantiateViewController(identifier: "HomeViewController")
self.delegate?.navigateToHomeViewController(homeViewController)
self.delegate?.hideActivityIndicator()
}
}
}
}
}
View
import UIKit
import FirebaseAuth
//MARK: - # protocols
protocol AuthViewModelDelegate {
func showError(_ message: String)
func hideActivityIndicator()
func navigateToHomeViewController(_ homeViewController: UIViewController)
}
class ViewController: UIViewController {
//MARK: - #IBOutlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var startButton: UIButton!
//MARK: - # Variables
var activityIndicator:UIActivityIndicatorView!
var authViewModel : AuthViewModel = AuthViewModel()
//MARK: - # Life cycle
override func viewDidLoad() {
super.viewDidLoad()
setDelegates()
setupUI()
}
fileprivate func setupUI() {
setActivityIndicator()
startButton.isEnabled = false
}
func setDelegates()->Void {
authViewModel.delegate = self
emailTextField.delegate = self
passwordTextField.delegate = self
}
func setActivityIndicator()->Void{
activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
activityIndicator.center = view.center
activityIndicator.isHidden = true
self.view.addSubview(activityIndicator)
}
func displayActivityIndicatorView() -> () {
self.view.isUserInteractionEnabled = false
self.view.bringSubviewToFront(self.activityIndicator)
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
}
#IBAction func startButtonAction(_ sender: Any) {
self.displayActivityIndicatorView()
guard let email = emailTextField.text else {return}
guard let password = passwordTextField.text else {return}
self.authViewModel.user?.email = email
self.authViewModel.user?.password = password
self.authViewModel.checkCredentials(user: self.authViewModel.user!)
}
fileprivate func validateFields() -> Bool {
return (passwordTextField.text!.count >= 8) && (isValidEmail(emailTextField.text ?? ""))
}
fileprivate func updateView() {
if(validateFields()){
startButton.isEnabled = true
}else{
startButton.isEnabled = false
}
}
}
func isValidEmail(_ email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: email)
}
//MARK: - Text Field Delegate Methods
extension ViewController : UITextFieldDelegate{
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString
string: String) -> Bool {
if textField == self.emailTextField {
updateView()
} else if textField == self.passwordTextField {
updateView()
}
return true
}
}
//MARK: - # AuthViewModel Delegate Methods
extension ViewController : AuthViewModelDelegate{
func hideActivityIndicator() {
DispatchQueue.main.async {
if !self.activityIndicator.isHidden{
DispatchQueue.main.async {
self.view.isUserInteractionEnabled = true
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
}
}
}
func navigateToHomeViewController(_ homeViewController: UIViewController) {
(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.changeRootViewController(homeViewController)
}
func showError(_ message: String) {
DispatchQueue.main.async {
let alertController = UIAlertController(title: "UPS!", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Aceptar", style: .default))
self.present(alertController, animated: true, completion: nil)
}
}
}

Facebook login user data in Authentication doesn’t show in firebase consoles

Every time, when I use a Facebook account to log in the application is supposed to have identified email shows up on the Firebase console but it doesn’t work properly. Users can use their Facebook account to access the application, but the problem is my profile page always got a crash when I attempt to make that page shows email of the users up. but if I use an email account to log in it doesn’t have any problem the email that I used to sign up able to shows up normally.
I have done everything in this link but can’t fix this problem.
https://firebase.google.com/docs/auth/ios/facebook-login
On the profile page, I use this code to call the email and user
import UIKit
import Firebase
import FirebaseAuth
import FacebookLogin
import FacebookCore
import FirebaseStorage
class ProfileViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var passTextField: UITextField!
#IBOutlet weak var changeNameText: UITextField!
#IBOutlet weak var menuButton: UIBarButtonItem!
#IBOutlet weak var imageProfile: UIImageView!
#IBOutlet weak var alertButton: UIBarButtonItem!
let imageUniqueName = UUID().uuidString
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
let user = Auth.auth().currentUser
setUserDataToView(withFIRUser: user!)
customizeNavBar()
sideMenus()
let tapGesture = UITapGestureRecognizer()
tapGesture.addTarget(self, action: #selector(ProfileViewController.openGallery(tapGesture:)))
imageProfile.isUserInteractionEnabled = true
imageProfile.addGestureRecognizer(tapGesture)
imageProfile.drawAsCircle()
}
func setUserDataToView(withFIRUser user: User) {
nameLabel.text = user.displayName
emailLabel.text = "อีเมล์ : \(user.email!)"
}
this is all code on my LoginViewController page
import UIKit
import Firebase
import FirebaseAuth
import FBSDKCoreKit
import FBSDKLoginKit
import FBSDKCoreKit
import FacebookLogin
import FacebookCore
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print("โปรดตรวจสอบใหม่อีกรอบ", error.localizedDescription)
} else if result.isCancelled {
} else {
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
ProgressHUD.showSuccess("ยินดีต้อนรับ")
self.performSegue(withIdentifier: "Main", sender: self)
}
}
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
ProgressHUD.showSuccess("ออกจากระบบสำเร็จ")
}
let loginButton = FBSDKLoginButton()
//Textfields pre-linked with IBOutlets
#IBOutlet var emailTextfield: UITextField!
#IBOutlet var passwordTextfield: UITextField!
#IBOutlet weak var facebookButton: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
loginButton.delegate = self
loginButton.readPermissions = ["public_profile", "email"]
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func logInPressed(_ sender: AnyObject) {
//TODO: Log in the user
Auth.auth().signIn(withEmail: emailTextfield.text!, password: passwordTextfield.text!) { (user, error) in
if error != nil{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
print(error!)
}else{
ProgressHUD.showSuccess("ยินดีต้อนรับ")
self.performSegue(withIdentifier: "Main", sender: self)
}
}
}
#IBAction func onClickPassword(_ sender: Any) {
if self.passwordTextfield.isSecureTextEntry == true {
self.passwordTextfield.isSecureTextEntry = false
}
else {
self.passwordTextfield.isSecureTextEntry = true
}
}
override func viewDidAppear(_ animated: Bool){
super.viewDidAppear(animated)
if Auth.auth().currentUser != nil {
self.performSegue(withIdentifier: "Main", sender: nil)
}
}
}
enter image description here

Swift: Retrieve data from Firebase and display in table view

I am making an app which has a news feed of images (HomeViewController). The user can tap on each image which segues to the SiteViewController which has a table view of empty data and a button that when clicked segues to ContextSheetViewController where the user can upload data of the image that they clicked on in the news feed. The user then presses upload and this data (siteCodeTextView, areaCodeTextView, trenchTextView) is saved to firebase and it dismisses back to the SiteViewController. I then want to retrieve the data value of siteCodeTextView that has just been uploaded of the image in the table view of the SiteViewController. But when I press upload in the ContextSheetViewController the error: Unexpectedly found nil while unwrapping an Optional value occurs. And my sheetId is printing nil in SiteViewController so I am not sure how to retrieve it correctly? Any help?
Here is my storyboard of relevant view controllers:
Code for SiteViewController:
class SiteViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var sheets = [Sheet]()
var users = [User]()
var sheetId: String!
var postId: String!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
loadSheets()
print(postId)
print(sheetId)
}
func loadSheets() {
Api.Sheet.REF_SHEETS.child(self.postId!).observe(.childAdded, with: {
snapshot in
Api.Sheet.observeSheets(withSheetId: snapshot.key, completion: {
sheet in
// self.fetchUser(uid: sheet.uid!, completed: {
print("sheet id: \(sheet.id)")
print("sheet uid: \(sheet.uid)")
self.sheets.append(sheet)
self.tableView.reloadData()
// })
})
})
}
func fetchUser(uid: String, completed: #escaping () -> Void ) {
Api.User.observeUser(withId: uid, completion: {
user in
self.users.append(user)
completed()
})
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SheetSegue" {
let sheetVC = segue.destination as! SheetViewController
let sheetId = sender as! String
sheetVC.sheetId = sheetId
}
}
}
extension SiteViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sheets.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SheetCell", for: indexPath) as! SiteTableViewCell
let sheet = sheets[indexPath.row]
print("sheet id: \(sheet.id)")
print("sheet uid: \(sheet.uid)")
// let user = users[indexPath.row]
// cell.user = user
cell.sheet = sheet
cell.delegate = self
return cell
}
}
extension SiteViewController: SiteTableViewCellDelegate {
func goToSheetVC(sheetId: String) {
performSegue(withIdentifier: "SheetSegue", sender: sheetId)
}
}
Code for ContextSheetViewController:
class ContextSheetViewController: UIViewController {
#IBOutlet weak var siteCodeTextView: UITextField!
#IBOutlet weak var areaCodeTextView: UITextField!
#IBOutlet weak var trenchTextView: UITextField!
#IBOutlet weak var uploadArtefactImage: UIImageView!
#IBOutlet weak var artefactImageView: UIImageView!
var selectedImage: UIImage?
var postId: String!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleSelectPhoto))
uploadArtefactImage.addGestureRecognizer(tapGesture)
uploadArtefactImage.isUserInteractionEnabled = true
}
#objc func handleSelectPhoto() {
let pickerController = UIImagePickerController()
pickerController.delegate = self
present(pickerController, animated: true, completion: nil)
}
#IBAction func uploadButton_TouchUpInside(_sender: Any) {
if let profileImg = self.artefactImageView.image, let imageData = UIImageJPEGRepresentation(profileImg, 0.1) {
let photoIdString = NSUUID().uuidString
print(photoIdString)
let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("sheets").child(photoIdString)
storageRef.putData(imageData, metadata: nil, completion: { (metadata, error) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
let photoUrl = metadata?.downloadURL()?.absoluteString
self.sendDataToDatabase(photoUrl: photoUrl!)
})
} else {
ProgressHUD.showError("Sheet Image can not be empty!")
}
}
func sendDataToDatabase(photoUrl: String) {
// let ref = Database.database().reference()
let sheetsReference = Api.Sheet.REF_SHEETS
// let sheetsReference = ref.child("sheets")
let newSheetId = sheetsReference.childByAutoId().key
let newSheetReference = sheetsReference.child(newSheetId)
guard let currentUser = Auth.auth().currentUser else {
return
}
let currentUserId = currentUser.uid
newSheetReference.setValue(["uid": currentUserId, "photoUrl": photoUrl, "siteCodeTextView": siteCodeTextView.text!, "areaCodeTextView": areaCodeTextView.text!, "trenchTextView": trenchTextView.text!], withCompletionBlock: {
(error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
let postSheetRef = Api.Sheet.REF_SHEETS.child(self.postId!).child(newSheetId)
// let postSheetRef = Api.Sheet.REF_SHEETS.child("post-sheets").child(self.postId).child(newSheetId)
postSheetRef.setValue(true, withCompletionBlock: { (error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
})
ProgressHUD.showSuccess("Success")
self.clean()
self.navigationController?.popViewController(animated: true)
})
}
func clean() {
self.siteCodeTextView.text = ""
self.uploadArtefactImage.image = UIImage(named: "upload")
self.artefactImageView.image = UIImage(named: "image")
}
}
extension ContextSheetViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("did Finish Picking Media")
if let image = info["UIImagePickerControllerOriginalImage"] as? UIImage{
artefactImageView.image = image
// selectedImage = image
// uploadArtefactImage.image = image
}
dismiss(animated: true, completion: nil)
}
}
Code for SiteTableViewCell:
protocol SiteTableViewCellDelegate {
func goToSheetVC(sheetId: String)
}
class SiteTableViewCell: UITableViewCell {
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var siteSheetLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
var delegate: SiteTableViewCellDelegate?
var sheet: Sheet? {
didSet {
updateView()
}
}
var user: User? {
didSet {
setupUserInfo()
}
}
func updateView() {
siteSheetLabel.text = sheet?.siteCodeTextView
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setupUserInfo() {
nameLabel.text = user?.username
if let photoUrlString = user?.profileImageUrl {
let photoUrl = URL(string: photoUrlString)
profileImageView.sd_setImage(with: photoUrl, placeholderImage: UIImage(named: "placeholderImg"))
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.siteSheetLabel_TouchUpInside))
siteSheetLabel.addGestureRecognizer(tapGesture)
siteSheetLabel.isUserInteractionEnabled = true
}
#objc func siteSheetLabel_TouchUpInside() {
print(sheet?.id)
if let id = sheet?.id{
delegate?.goToSheetVC(sheetId: id)
}
}
override func prepareForReuse() {
super.prepareForReuse()
profileImageView.image = UIImage(named: "placeholderImg")
}
}
From what you have shown the culprit is the postId, you are using it to fetch data from Firebase and yet you haven't shown anywhere what its value is. When the user taps on an image, the postId is not transfered to the SiteViewController.
In the SiteViewController remove the ! and replace it with ?, put an initializer that will take the postID as a parameter.
var postId:String?
func initPost(forImage postId: String) {
self.postId=postId
}
In the previous news feed VC inside the segue or didSelectForRow(i don't know what you use for transition, initialize the SiteViewController, so when it is presented it knows which ID to retrieve data for.
Another thing that needs mentioning is that you are using observe but you are not removing the observers.
EDIT: this answer was based on me not knowing what your HomeVC looked like.
if segue.identifier == "SiteSegue" {
let siteVC = segue.destination as! SiteViewController
let postId = sender as! String
siteVC.postId = postId
}

Swift - FireBase - Snapshot - DataService

I have some problems retrieving snapshots from my FireBase child ("Users" into my UITextFields and UITextViews
After I retrieve them, I want them to be editable through code in DataService
Can anyone help ??????
enter code here
import UIKit
import Firebase
class ProfileTableViewController: UITableViewController, UINavigationControllerDelegate, UITextViewDelegate, UITextFieldDelegate {
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var email: UITextField!
var imagePicker = UIImagePickerController()
var selectPhoto: UIImageView!
#IBOutlet weak var schoolProfile: UITextField!
#IBOutlet weak var interestProfile: UITextView!
#IBOutlet weak var aboutProfile: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "EDIT PROFILE"
profileImage.layer.cornerRadius = profileImage.frame.size.height / 2
profileImage.clipsToBounds = true
// Display data in tabletcells
if let user = DataService.dataService.currentUser {
username.text = user.displayName
email.text = user.email
// schoolProfile.text = user.School
// print(user.photoURL)
if user.photoURL != nil {
if let data = NSData(contentsOf: user.photoURL!) {
self.profileImage.image = UIImage.init(data: data as Data)
}
}
}else {
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo image: UIImage, editingInfo: [String: Any]?) {
profileImage.image = image
imagePicker.dismiss(animated: true, completion: nil)
}
}
// Change profileimage
#IBAction func selectPhoto(_ sender: UITapGestureRecognizer) {
resignFirstResponder()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePicker.sourceType = .camera
}else {
imagePicker.sourceType = .photoLibrary
}
self.present(imagePicker, animated: true, completion: nil)
}
#IBAction func saveDidTapped(_ sender: AnyObject) {
var data = NSData()
data = UIImageJPEGRepresentation(profileImage.image!, 0.1)! as NSData
DataService.dataService.SaveProfile(username: username.text!, email: email.text!, data: data)
}
}
extension ProfileTableViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo image: UIImage, editingInfo: [String: Any]?) {
profileImage.image = image
imagePicker.dismiss(animated: true, completion: nil)
}
}

How to call segue/ unwind right after login with Facebook

I created a log-in screen with 3 text fields (username, email, password). with 3 action buttons (Register, Login, Facebook login).
I was able to log in with facebook account, but I can't seem to present the details of the user, such name, and profile pic.. I tried to displayed it on the currentviewcontroller or the destinationVC but I guess I'm doing something wrong with the segue and Facebook
import UIKit
import Parse
import FBSDKCoreKit
import ParseFacebookUtilsV4
var myAlert = ""
var user = PFObject(className:"User")
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var userName: UITextField!
#IBOutlet var email: UITextField!
#IBOutlet var passWord: UITextField!
#IBOutlet weak var userlab: UILabel!
let permissions = ["public_profile", "user_friends", "email"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.userName.delegate = self
self.email.delegate = self
self.passWord.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func LogInToFacebook(sender: AnyObject) {
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions) {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
print("User signed up and logged in through Facebook!")
self.userlab.text = PFUser.currentUser()?.username
self.performSegueWithIdentifier("CSegue", sender: self)
} else {
print("User logged in through Facebook!")
//self.image = UIImage(named: "logout_FB.png")!
self.userlab.text = PFUser.currentUser()?.username
//self.fbOutlet.setImage(self.image, forState: UIControlState.Normal)
self.performSegueWithIdentifier("CSegue", sender: self)
}
} else {
print("Uh oh. The user cancelled the Facebook login.")
}
}
}
at the destinationVC (HomeVC) I just created 3 labels
import UIKit
import Parse
import FBSDKCoreKit
import ParseFacebookUtilsV4
class HomeVC: UIViewController {
#IBOutlet weak var userNamelabel: UILabel!
var user: PFUser!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "LogInToFacebook" {
user = PFUser.currentUser()
userNamelabel.text = user.username
}
}
That's the segue I am trying to use:
override func perform() {
let sourceViewController: UIViewController = self.sourceViewController
let destinationViewController: UIViewController = self.destinationViewController
user = PFUser.currentUser()!
sourceViewController.view.addSubview(destinationViewController.view)
destinationViewController.view.transform = CGAffineTransformMakeScale(0.05, 0.05)
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
destinationViewController.view.transform = CGAffineTransformMakeScale(1.0, 1.0)
}) { (finished) -> Void in
destinationViewController.view.removeFromSuperview()
sourceViewController.presentViewController(destinationViewController, animated: false, completion: nil)
}
}