I am trying to make a Sign in / Sign up screen with Firebase. And i created a swift class for send data to Firebase and i called the class "DataService". I have also Sign in and Sign up classes. In the "DataService" class i cant create more than one function, i am getting error like Value of type DataService has no member "Sign up" when i am trying to create a sign up function. But the other function works fine. I can have just only one function in this class(DataService).
DATASERVICE class
import Foundation
import Firebase
import FirebaseAuth
import FirebaseStorage
let rootRef = FIRDatabase.database().reference()
class DataService {
static let dataService = DataService()
private var _BASE_REF = rootRef
private var _PHOTO_REF = rootRef.child("photos")
var BASE_REF: FIRDatabaseReference {
return _BASE_REF
}
var PHOTO_REF: FIRDatabaseReference {
return _PHOTO_REF
}
var storageRef: FIRStorageReference{
return FIRStorage.storage().reference()
}
var fileUrl: String!
// Share Photo Data
func shareNewPhoto(user: FIRUser, caption: String, data: NSData) {
let filePath = "\(user.uid)/\ (Int(NSDate.timeIntervalSinceReferenceDate))"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
storageRef.child(filePath).put(data as Data, metadata: metaData) { (metadata, error) in
if let error = error {
print("Error uploading: /\(error.localizedDescription)")
}
// Create a Url for data ( Story Photo)
self.fileUrl = metadata!.downloadURLs![0].absoluteString
if let user = FIRAuth.auth()?.currentUser {
let idPhotoRoom = self.BASE_REF.child("PhotoRooms").childByAutoId()
idPhotoRoom.setValue(["caption": caption, "StoryPhotoUrlFromStorage": self.storageRef.child(metadata!.path!).description, "fileUrl": self.fileUrl])
}
}
// Story Photo (upload and dowload from server)
func fetchDataFromServer(callback:#escaping (StoryPhoto) -> ()) {
DataService.dataService._PHOTO_REF.observe(.childAdded, with: { (snapshot) in
let photo = StoryPhoto(key: snapshot.key, snapshot: snapshot.value as! Dictionary<String, AnyObject>)
callback(photo)
})
// Sign Up
func signUp(username: String, email: String, password: String, data: NSData) {
FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
let changeRequest = user?.profileChangeRequest()
changeRequest?.displayName = username
changeRequest?.commitChanges(completion: { (error) in
if let error = error{
print(error.localizedDescription)
return
}
})
let filePath = "profileimage/\(user!.uid)"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpeg"
self.storageRef.child(filePath).put(data as Data, metadata: metaData, completion: { (metadata, error) in
if let error = error {
print("\(error.localizedDescription)")
return
}
self .fileUrl = metadata?.downloadURLs![0].absoluteString
let changeRequestPhoto = user!.profileChangeRequest()
changeRequestPhoto.photoURL = NSURL(string: self.fileUrl) as URL?
changeRequestPhoto.commitChanges(completion: { (error) in
if let error = error {
print(error.localizedDescription)
return
}else{
print("profile uptaded")
}
})
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.Login()
})
})
}
}
}
}
Sign Up class. Here i am getting error like Value of type DataService has no member "Sign up".
// Register Button
#IBAction func RegisterDidTapped(_ sender: AnyObject) {
guard let email = emailTextField.text, let password = passwordTextField.text, let username = usernameTextField.text else {
return
}
var data = NSData()
data = UIImageJPEGRepresentation(profileImage.image!, 0.1)! as NSData
//Signin up
Here i am getting Error: (Value of type DataService has no member "sign Up")
DataService.dataService.signUp(username: username, email: email, password: password, data: data)
}
}
check correct open and close {}. looks like your signUp function are inside other function.
Related
I am using this code to retrieve the first name from my Firebase database and trying to display it in a label but it always returns the "Document does not exist in cache". My firebase security is set to read and write true. Do you know what I am doing wrong?
func nameGreeting() -> String{
let db = Firestore.firestore()
let userId = Auth.auth().currentUser!.uid;(Auth.auth().currentUser!.uid);
let docRef = db.collection("users").document(userId)
docRef.getDocument(source: .cache) { (document, error) in
if let document = document {
let name = document.get("firstname")
print("Cached document data: \(String(describing: name))")
} else {
print("Document does not exist in cache")
}
}
return ""
}
you are using an async function (docRef.getDocument...) inside "nameGreeting", so you are returning "" before the firebase function is finished. Try something like this:
func nameGreeting(completion: #escaping ((String?) -> Void)) {
let db = Firestore.firestore()
let userId = Auth.auth().currentUser!.uid
let docRef = db.collection("users").document(userId)
docRef.getDocument(source: .cache) { (document, error) in
if let document = document {
let name = document.get("firstname")
print("Cached document data: \(String(describing: name))")
completion(name)
} else {
print("Document does not exist in cache")
completion(nil)
}
}
}
and call it like this:
nameGreeting() { userName in
print("----> userName: \(userName)")
}
I am trying to add an image to Firebase storage and then get the location of that image and store it in a Firestore document with the other user profile data. I am trying to do all of this when the user first creates an account. I was trying to use the image URL to do this but that does not appear to be working. When I run the code below it will sign up a new user and add the photo to Firebase storage but no document gets created in the Firestore database. What am I doing wrong?
#objc func handleSignUp() {
//Signup properties
guard let email = emailTextField.text else { return }
guard let password = passwordTextField.text else { return }
guard let fullName = fullNameTextField.text else { return }
guard let username = usernameTextField.text?.lowercased() else { return }
createUser(email: email,
password: password,
fullName: fullName,
userName: username)
}
func createUser(email: String, password: String, fullName: String, userName: String) {
Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in
//Handle error
if let error = error {
print("DEBUG: Failed to create user with error: ", error.localizedDescription)
return
}
guard let profileImg = self.plusPhotoBtn.imageView?.image else { return }
guard let uploadData = profileImg.jpegData(compressionQuality: 0.3) else { return }
let userID = Auth.auth().currentUser!.uid
let filename = NSUUID().uuidString
//Storage location for photo in Firebase
let storageRef = Storage.storage().reference().child("profile_images").child(userID).child(filename)
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
//Handle error
if let error = error {
print("Failed to upload image to Firebase Storage with error", error.localizedDescription)
return
}
guard metadata != nil else { return }
let path = storageRef.fullPath;
guard let username = self.usernameTextField.text?.lowercased() else { return }
storageRef.downloadURL { (url, _) in
let data = ["name": fullName,
"username": username,
"profileImagePath": path,
"email" : email] as [String : Any]
self.addDocument(userData: data)
}
})
}
}
I think you should add the "downloadURL" part inside the "putData".
After completion of the put data process you should try to get the URL or else it will fail.
Try this and see if it works:
#objc func handleSignUp() {
//Signup properties
guard let email = email.text else { return }
guard let password = password.text else { return }
guard let fullName = name.text else { return }
guard let username = name.text?.lowercased() else { return }
createUser(email: email,
password: password,
fullName: fullName,
userName: username)
}
func createUser(email: String, password: String, fullName: String, userName: String) {
Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in
//Handle error
if let error = error {
print("DEBUG: Failed to create user with error: ", error.localizedDescription)
return
}
guard let profileImg = self.plusPhotoBtn.imageView?.image else { return }
guard let uploadData = profileImg.jpegData(compressionQuality: 0.3) else { return }
let filename = NSUUID().uuidString
//Storage location for photo in Firebase
let storageRef = Storage.storage().reference().child("profile_images").child(filename)
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
//Handle error
if let error = error {
print("Failed to upload image to Firebase Storage with error", error.localizedDescription)
return
}
guard let metadata = metadata else { return }
guard let username = self.usernameTextField.text?.lowercased() else { return }
storageRef.downloadURL { (url, _) in
guard let downloadURL = url else {
print("DEBUG: Profile image url is nil")
return
}
let data = ["name": fullName,
"username": username,
"profileImageUrl": downloadURL,
"email" : email]
self.addDocument(userData: data)
}
})
}
}
func addDocument(userData: [String: Any]) {
Firestore.firestore().collection("profile_data").addDocument(data: userData) { (err) in
if let err = err {
debugPrint("Error adding document: \(err)")
} else {
self.navigationController?.popViewController(animated: true)
}
}
}
After I update Firebase pod I got this Error :
Cannot invoke initializer for type 'User' with an argument list of type '(snapshot: (DataSnapshot))'
And here is my code enter image description here
Any Idea to solve this ..???
func loadUserInfo(){
let userRef = dataBAseRef.child("users/\(Auth.auth().currentUser!.uid)")
userRef.observe(.value, with: { (snapshot) in
let user = User(snapshot: snapshot)
self.usernameLabel.text = user.username
self.userCountry.text = user.country!
self.userBiographyTextView.text = user.biography!
let imageURL = user.photoURL!
self.storageRef.reference(forURL: imageURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (imageData, error) in
if error == nil {
DispatchQueue.main.async {
if let data = imageData {
self.userImageView.image = UIImage(data: data)
}
}
} else {
print(error!.localizedDescription)
}
})
}) { (error) in
print(error.localizedDescription)
}
}
After I update everything to firebase 4.0.4 I got the error, here is the whole codes :
import Foundation
import Firebase
import FirebaseStorage
import FirebaseDatabase
import FirebaseAuth
struct AuthService {
var dataBAseRef: DatabaseReference! {
return Database.database().reference()
}
var storageRef: StorageReference! {
return Storage.storage().reference()
}
// 1- creating the signup function
func signUp(username:String,email:String,country:String,password:String,biography: String, pictureData:NSData!) {
Auth.auth().createUser(withEmail: email, password: password, completion: {(user, error) in
if error == nil {
self.setUserInfo(user: user, username: username, country: country, password: password, biography: biography, pictureData: pictureData)
} else {
print(error?.localizedDescription as Any)
}
})
}
// 2- create the set user info function
private func setUserInfo(user: User!, username: String, country: String, password: String, biography: String, pictureData: NSData!)
{
let imagePath = "profileImage\(user.uid)/userPic.jpg"
let imageRef = storageRef.child(imagePath)
let metaData = StorageMetadata()
metaData.contentType = "image/jpeg"
imageRef.putData(pictureData as Data, metadata: metaData) {(newMetaData, error) in
if error == nil {
let changeRequest = user.profileChangeRequest()
changeRequest.displayName = username
if let photoURL = newMetaData!.downloadURL() {
changeRequest.photoURL = photoURL
}
changeRequest.commitChanges(completion: { (eroor) in
if error == nil {
self.saveUserInfo(user: user, username: username, country: country, password: password, biography: biography )
} else {
print(error?.localizedDescription as Any)
}
})
} else {
print(error?.localizedDescription as Any)
}
}
}
// 3- save the User info in Firebase
private func saveUserInfo(user: User!, username: String, country: String, password: String, biography: String)
{
let userInfo = ["Email": user.email!, "username": username, "country": country,"biography": biography, "uid": user.uid, "photoURL": String(describing: user.photoURL!)]
let userRef = dataBAseRef.child("users").child(user.uid)
userRef.setValue(userInfo) { (error, ref) in
if error == nil {
print("user info saved successfully")
self.logIn(email: user.email!, password: password)
} else {
print(error?.localizedDescription as Any)
}
}
}
// logging the user in function
func logIn(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password, completion: { (user, error) in
if error == nil {
if let user = user {
print("\(user.displayName!) has logged in successfully")
let appDel: AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDel.logUser()
}
}
else {
print(error?.localizedDescription as Any)
}
})
}
}
Now I have 2 errors :
here is the errors
I tried to update profileChangeRequest() to createProfileChangeRequest() but didn't help
Here is User class:
import Foundation
import Firebase
import FirebaseDatabase
struct User {
var username: String!
var email: String?
var country: String?
var biography: String?
var photoURL: String!
var uid: String!
var ref: DatabaseReference?
var key: String?
init(snapshot: DataSnapshot) {
key = snapshot.key
ref = snapshot.ref
username = (snapshot.value! as! NSDictionary)["username"] as! String
email = (snapshot.value! as! NSDictionary)["email"] as? String
country = (snapshot.value! as! NSDictionary)["country"] as? String
uid = (snapshot.value! as! NSDictionary)["uid"] as! String
biography = (snapshot.value! as! NSDictionary)["biography"] as? String
photoURL = (snapshot.value! as! NSDictionary)["photoURL"] as! String
}
}
I think your user class is clashing with with the FIRUser class which they changed from FIRUser to User in the 4.x SDK. Try renaming your user class to something like LocalUser and see if that helps, if it does then there's your problem
I am trying to make a Sign in / Sign up screen with Firebase. And i created a swift class for send data to Firebase and i called the class "DataService". I have also Sign in and Sign up classes. In the "DataService" class i cant create more than one function, i am getting error like Value of type DataService has no member "Sign up" when i am trying to create a sign up function. But the other function works fine. I can have just only one function in this class(DataService).
DATASERVICE class
import Foundation
import Firebase
import FirebaseAuth
import FirebaseStorage
let rootRef = FIRDatabase.database().reference()
class DataService {
static let dataService = DataService()
private var _BASE_REF = rootRef
private var _PHOTO_REF = rootRef.child("photos")
var BASE_REF: FIRDatabaseReference {
return _BASE_REF
}
var PHOTO_REF: FIRDatabaseReference {
return _PHOTO_REF
}
var storageRef: FIRStorageReference{
return FIRStorage.storage().reference()
}
var fileUrl: String!
// Share Photo Data
func shareNewPhoto(user: FIRUser, caption: String, data: NSData) {
let filePath = "\(user.uid)/\ (Int(NSDate.timeIntervalSinceReferenceDate))"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
storageRef.child(filePath).put(data as Data, metadata: metaData) { (metadata, error) in
if let error = error {
print("Error uploading: /\(error.localizedDescription)")
}
// Create a Url for data ( Story Photo)
self.fileUrl = metadata!.downloadURLs![0].absoluteString
if let user = FIRAuth.auth()?.currentUser {
let idPhotoRoom = self.BASE_REF.child("PhotoRooms").childByAutoId()
idPhotoRoom.setValue(["caption": caption, "StoryPhotoUrlFromStorage": self.storageRef.child(metadata!.path!).description, "fileUrl": self.fileUrl])
}
}
// Story Photo (upload and dowload from server)
func fetchDataFromServer(callback:#escaping (StoryPhoto) -> ()) {
DataService.dataService._PHOTO_REF.observe(.childAdded, with: { (snapshot) in
let photo = StoryPhoto(key: snapshot.key, snapshot: snapshot.value as! Dictionary<String, AnyObject>)
callback(photo)
})
// Sign Up
func signUp(username: String, email: String, password: String, data: NSData) {
FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
let changeRequest = user?.profileChangeRequest()
changeRequest?.displayName = username
changeRequest?.commitChanges(completion: { (error) in
if let error = error{
print(error.localizedDescription)
return
}
})
let filePath = "profileimage/\(user!.uid)"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpeg"
self.storageRef.child(filePath).put(data as Data, metadata: metaData, completion: { (metadata, error) in
if let error = error {
print("\(error.localizedDescription)")
return
}
self .fileUrl = metadata?.downloadURLs![0].absoluteString
let changeRequestPhoto = user!.profileChangeRequest()
changeRequestPhoto.photoURL = NSURL(string: self.fileUrl) as URL?
changeRequestPhoto.commitChanges(completion: { (error) in
if let error = error {
print(error.localizedDescription)
return
}else{
print("profile uptaded")
}
})
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.Login()
})
})
}
}
}
}
Sign Up class. Here i am getting error like Value of type DataService has no member "Sign up".
// Register Button
#IBAction func RegisterDidTapped(_ sender: AnyObject) {
guard let email = emailTextField.text, let password = passwordTextField.text, let username = usernameTextField.text else {
return
}
var data = NSData()
data = UIImageJPEGRepresentation(profileImage.image!, 0.1)! as NSData
//Signin up
Here i am getting Error: (Value of type DataService has no member "sign Up")
DataService.dataService.signUp(username: username, email: email, password: password, data: data)
}
}
Your issue is that you putting functions inside other functions. Don't do that in this case. Functions that need to be called from other code should be top-level functions of the class, not embedded inside other functions.
And, unrelated, please use proper, standard naming conventions. Method and variable names should start with lowercase letters. Classnames start with uppercase letters.
I've linked my app to both the Facebook SDK and Parse, but now I'm trying to integrate Facebook's login with Parse but keep running into issues. My current issue is that the app runs, but when I press the FBSDKLoginButton, it will go to safari and ask for permissions (as it should), but then when pressing okay, it simply returns to the app's login screen like nothing happened and does not perform the segue to the rest of the app. I also checked Parse and it did not create a new PFUser. I will post the code I think may be relevant from my LoginViewController below (that means the code will be missing sections like my viewDidLoad for it has nothing in it that affects the login process):
import UIKit
import Parse
import FBSDKCoreKit
import FBSDKLoginKit
protocol LoginViewControllerDelegate {
func onRegister(loginViewController : LoginViewController)
func onFacebookLogin(loginViewController : LoginViewController)
func onLogin(loginViewController : LoginViewController)
}
class LoginViewController: UIViewController {
#IBAction func onFacebookLogin(sender: AnyObject?) {
// Set permissions required from the facebook user account
let permissions = [ "user_about_me", "user_relationships", "user_location", "user_birthday", "public_profile", "user_friends", "user_email", "user_gender"]
// Login PFUser using Facebook
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
println("User signed up and logged in through Facebook!")
self.loadData()
self.performSegueWithIdentifier("loggedIn", sender: self)
} else {
println("User logged in through Facebook!")
self.performSegueWithIdentifier("loggedIn", sender: self)
}
if self.delegate != nil {
self.delegate!.onFacebookLogin(self)
}
} else {
println("Uh oh. The user cancelled the Facebook login.")
}
})
}
func loadData(){
let request:FBSDKGraphRequest = FBSDKGraphRequest()
request.startWithCompletionHandler { (connection:FBSDKGraphRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if error == nil{
if let dict = result as? Dictionary<String, AnyObject>{
let name:String = dict["first_name"] as AnyObject? as! String
let facebookID:String = dict["id"] as AnyObject? as! String
let email:String = dict["email"] as AnyObject? as! String
let birthday:String = dict["birthday"] as AnyObject? as! String
let gender:String = dict["gender"] as AnyObject? as! String
let hostCount:Int = 0
let attendCount:Int = 0
let pictureURL = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
var URLRequest = NSURL(string: pictureURL)
var URLRequestNeeded = NSURLRequest(URL: URLRequest!)
NSURLConnection.sendAsynchronousRequest(URLRequestNeeded, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!, error: NSError!) -> Void in
if error == nil {
var picture = PFFile(data: data)
PFUser.currentUser()!.setObject(picture, forKey: "profilePicture")
PFUser.currentUser()!.saveInBackground()
}
else {
println("Error: \(error.localizedDescription)")
}
})
PFUser.currentUser()!.setValue(name, forKey: "name")
PFUser.currentUser()!.setValue(email, forKey: "email")
PFUser.currentUser()!.setValue(birthday, forKey: "birthday")
PFUser.currentUser()!.setValue(gender, forKey: "gender")
PFUser.currentUser()!.setValue(hostCount, forKey: "hostCount")
PFUser.currentUser()!.saveInBackground()
}
}
}
}
}
I use this solution, hope it helps you. If you have a question on it, I can answer :)
func notLoggedIn() -> Bool {
let user = PFUser.currentUser()
// here I assume that a user must be linked to Facebook
return user == nil || !PFFacebookUtils.isLinkedWithUser(user)
}
func loggedIn() -> Bool {
return !notLoggedIn()
}
func performNewUser(){
if notLoggedIn() {
return
}
let user = PFUser.currentUser() // Won't be nil because is logged in
// RETURN IF WE ALREADY HAVE A USERNAME AND FBID (note that we check the fbId because Parse automatically fills in the username with random numbers)
if let fbId = user["fbId"] as? String {
if !fbId.isEmpty {
displayAlert("Erreur", error: "Il existe déjà un utilisateur avec ce compte Facebook")
println("we already have a username and fbId -> return")
return
}
}
// REQUEST TO FACEBOOK
println("performing request to FB for username and IDF...")
if let session = PFFacebookUtils.session() {
if session.isOpen {
println("session is open")
FBRequestConnection.startForMeWithCompletionHandler({ (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
println("done me request")
if error != nil {
println("facebook me request - error is not nil :(")
} else {
println("facebook me request - error is nil :)")
println(result)
println(result.name)
println(result.objectID)
// Save to Parse:
var FBSession = PFFacebookUtils.session()
var currentUser = PFUser.currentUser()
var userToSave = PFObject(className: "Utilisateurs")
var accessToken = FBSession.accessTokenData.accessToken
let url = NSURL(string: "https://graph.facebook.com/me/picture?type=large&return_ssl_resources=1&access_token="+accessToken)
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
let image = UIImage(data: data)
currentUser["image"] = data
currentUser.save()
self.performSegueWithIdentifier("connexionApplicationInscriptionViaFacebook", sender: self)
})
let firstName = result["first_name"] as String
let status = "Client"
currentUser.username = result["last_name"] as String
currentUser.email = result.email
userToSave.setObject(currentUser.username, forKey: "nom")
userToSave.setObject(currentUser.username, forKey: "username")
userToSave.setObject(firstName, forKey: "prenom")
userToSave.setObject(status, forKey: "status")
currentUser.setValue(self.tfPrenom.text, forKey: "name")
currentUser.setValue(result.objectID, forKey: "fbId")
currentUser.saveEventually() // Always use saveEventually if you want to be sure that the save will succeed
}
})
}
}
}
After updating to Parse 1.7.4 and deleting the old PFFacebookUtils Framework (keeping the PFFacebookUtilsV4) seems to have fixed the problem by itself! I hope this answer helps other people with the same problem.