How to call segue/ unwind right after login with Facebook - swift

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)
}
}

Related

Force unwrapping nil optional for UIImageView when transitioning to view controller

I'm running into an error when transitioning to view controllers by overriding the built-in prepare() function in Swift. I have a UIImageView for backgrounds on my screens. Here is the code for two of the view controllers in question.
import UIKit
import FirebaseAuth
class HomeVC: UIViewController {
#IBOutlet weak var signOutButton: UIButton!
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var friendsNavButton: UIButton!
#IBOutlet weak var homeNavButton: UIButton!
#IBOutlet weak var profileNavButton: UIButton!
#IBOutlet weak var bumpButton: UIButton!
#IBOutlet weak var welcomeLabel: UILabel!
#IBOutlet weak var doNotDisturbLabel: UILabel!
#IBOutlet weak var doNotDisturbButton: UIButton!
var userName = ""
var dndIsOn: Bool = false
#IBAction func dndToggled(_ sender: Any) {
dndIsOn = !dndIsOn
User.current.available = !dndIsOn
FirestoreService.db.collection(Constants.Firestore.Collections.users).document(User.current.uid).updateData([Constants.Firestore.Keys.available : !dndIsOn])
if dndIsOn {
print("DND is on!")
setupDNDUI()
} else if !dndIsOn {
print("DND is off!")
setupActiveUI()
}
}
#IBAction func signOutTapped(_ sender: Any) {
let firAuth = Auth.auth()
do {
try firAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
print("Successfully signed out")
}
#IBAction func bumpTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toCall, sender: self)
}
#IBAction func friendsNavTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toFriends, sender: self)
}
#IBAction func profileNavTapped(_ sender: Any) {
let nav = self.navigationController //grab an instance of the current navigationController
DispatchQueue.main.async { //make sure all UI updates are on the main thread.
nav?.view.layer.add(CATransition().segueFromLeft(), forKey: nil)
nav?.pushViewController(ProfileVC(), animated: false)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
self.backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill
doNotDisturbLabel.isHidden = true
if !userName.isEmpty {
welcomeLabel.text = "Welcome Back, " + userName + "!"
} else {
welcomeLabel.text = ""
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .darkContent
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let friendsVC = segue.destination as? FriendsVC else {
return
}
FirestoreService.db.collection(Constants.Firestore.Collections.users).document(User.current.uid).getDocument { (snapshot, err) in
if let err = err {
print(err.localizedDescription)
} else {
let data = snapshot!.data()!
let requests = data[Constants.Firestore.Keys.requests] as? [String]
if let requests = requests {
friendsVC.requests = requests
}
}
}
}
class FriendsVC: UIViewController {
//var friends: [Friend] = User.current.friends
var friends: [User] = []
var requests: [String]?
#IBOutlet weak var requestsNumberLabel: UILabel!
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var friendRequestsButton: UIButton!
#IBOutlet weak var homeNavButton: UIButton!
#IBOutlet weak var friendsTitle: UILabel!
#IBOutlet weak var friendTableView: UITableView!
#IBOutlet weak var addFriendButton: UIButton!
#IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint!
#IBAction func friendRequestsTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toRequests, sender: self)
}
#IBAction func homeNavTapped(_ sender: Any) {
let nav = self.navigationController //grab an instance of the current navigationController
DispatchQueue.main.async { //make sure all UI updates are on the main thread.
nav?.view.layer.add(CATransition().segueFromLeft(), forKey: nil)
nav?.pushViewController(HomeVC(), animated: false)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill
friendTableView.backgroundView?.backgroundColor = .white
friendsTitle.isHidden = false
UserService.getUserArray(uids: User.current.friendUids, completion: { (users) in
guard let users = users else {
print("User has no friends")
return
}
self.friends = users
self.friendTableView.reloadData()
})
guard let requests = self.requests else {
friendRequestsButton.isHidden = true
requestsNumberLabel.isHidden = true
self.tableViewTopConstraint.constant = 0
return
}
requestsNumberLabel.text = requests.count.description
// Do any additional setup after loading the view.
friendTableView.delegate = self
friendTableView.dataSource = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let homeVC = segue.destination as? HomeVC {
homeVC.userName = User.current.firstName
} else if let requestsVC = segue.destination as? RequestsVC {
UserService.getUserArray(uids: self.requests!) { (requesters) in
if let requesters = requesters {
requestsVC.requesters = requesters
}
}
}
}
}
When my app loads into the home screen, there is no problem, and when a button is tapped to transition to FriendsVC, there is no problem. However, when I try to initiate the transition from HomeVC to ProfileVC or from FriendVC to HomeVC, I get the error: "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" at the self.backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill lines in my viewDidLoad methods. These segues have something in common in that these are the ones where I override the prepare() function, but I'm not sure what I'm doing wrong

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 Error: EXC BAD INSTRUCTION code=EXCI386 for userid

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)
}
}

Taking Facebook values (email, name, etc) from one view controller and transferring them to another one

So I'm currently designing an application and am working on the account registration. I've implemented Facebook login into it but I am having trouble taking a user's Facebook information and transferring it to the next page, where, ideally, the fields for name and email would be filled with those values received from Facebook.
The initial page with the Facebook login looks like this:
class RegisterVC: UIViewController, FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let loginButton = FBSDKLoginButton()
view.addSubview(loginButton)
loginButton.frame = CGRect(x: 82, y: 325, width: view.frame.width - 210, height: 59)
loginButton.delegate = self
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("Did log out of facebook")
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print(error)
return
}
print("Successfully logged in")
FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "id, name, email"]).start {(connection, result, err) in
if err != nil {
print("Failed to start graph request", err)
return
} else {
guard let data = result as? [String:Any] else {return}
let fbEmail = data["email"]
let fbName = data["name"]
}
print(result)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//get destination view an set the fullname
let vc = segue.destination as? CreateAccountVC
vc?.email = self.fbEmail
vc.fullname = self.fbName
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
And the next view controller, a typical registration page, has these text fields:
#IBOutlet weak var fullname: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var age: UITextField!
#IBOutlet weak var email: UITextField!
#IBOutlet weak var verifyEmail: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var verifyPassword: UITextField!
I have no idea how to take the values from Facebook and put them into these text entry boxes. I'm very new to programming so any help would be much appreciated, thanks!
First, store the FB values in a var(s) you can access later.
Next, You can set the values for your next view before you transition. For example if you are using a segue, you can do it in the prepareForSegue like this:
class RegisterVC: UIViewController, FBSDKLoginButtonDelegate {
var fbName:String?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//get destination view an set the fullname
let vc=segue.destination as? MyCustomVC
vc.fullName=self.fbName
}

Hide ios 8 sidebar swift?

im currently using the amazing open source library https://github.com/evnaz/ENSwiftSideMenu for my application navigation sidebar. However, I created an login page for the project, but couldn't figure out an way to hide the sidebar in my login page, can anyone help me?
my view controller (where will guide the user to login page if login does not login )
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var currentUser = PFUser.currentUser()
if currentUser != nil {
NSLog("CurrentUser:", currentUser.username)
// Do stuff with the user
} else {
// Show the signup or login screen
self.performSegueWithIdentifier("showLogin", sender: self)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func logout(sender: AnyObject) {
PFUser.logOut()
self.performSegueWithIdentifier("showLogin", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showLogin") {
// pass data to next view
segue.destinationViewController.sideMenuController()?.sideMenu?.hideSideMenu()
//sideMenuController()?.sideMenu?.hideSideMenu()
}
}
}
my login page:
import UIKit
class LoginViewController: UIViewController {
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBAction func loginButton(sender: AnyObject) {
var username = String (self.usernameField.text .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()))
var password = String (self.passwordField.text .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()))
if username.isEmpty || password.isEmpty{
let alert = UIAlertView()
alert.title = "Oops"
alert.message = "Please make sure you enter all the field"
alert.addButtonWithTitle("Okay")
alert.show()
}
else {
PFUser.logInWithUsernameInBackground(username, password:password) {
(user: PFUser!, error: NSError!) -> Void in
if user != nil {
// Do stuff after successful login.
self.navigationController?.popToRootViewControllerAnimated(true)
} else {
// The login failed. Check error to see why.
let alert = UIAlertView()
alert.title = "Oops"
alert.message = error.userInfo!["error"] as NSString
alert.addButtonWithTitle("Okay")
alert.show()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.hidesBackButton = true
//self.sideMenuController()?.sideMenu?.hideSideMenu()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
You need to call hideSideMenuView() function in your view controller. It is view controller's extension public function. Also there are showSideMenuView() and toggleSideMenuView() functions.