I am trying to store the information a user inputs for the signup page into a parse database, but can't seem to figure out how to do it.
class ViewController: UIViewController {
#IBOutlet var fullnameField: UITextField!
#IBOutlet var emailAddressField: UITextField!
#IBOutlet var usernameField: UITextField!
#IBOutlet var passwordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let userFullname = fullnameField.text
let userEmailAddress = emailAddressField.text
let userName = usernameField.text
let userPassword = passwordField.text
let User = PFObject(className: "User")
User["FullName"] = "Example Name"
User["EmailAddress"] = "JohnDoe#example.com"
User["Username"] = "Example"
User["Password"] = "Ilovesmores12345"
User.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
println("Object has been saved.")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
When a user enters his/her information to the text fields and hit's sign up, I need for the information to save into a parse database for further use on the log in page. I feel like i'm over thinking and making it more complicated, is there a way to do this easily?
For signing up don't use user.save - use user.signUpInBackgroundWithBlock
Check this link, it's Parse iOS Guide.
My example, create a button and connect it to signUpPressed method. Here's the method.
#IBAction func signUpPressed(sender: AnyObject) {
let userName = userNameField.text
let email = emailField.text.lowercaseString
let password = passwordField.text
let fullName = fullNameField.text
var user = PFUser()
user.username = userName
user.email = email
user.password = password
//for custom fields use default key-value assign
user["fullName"] = fullName
user.signUpInBackgroundWithBlock{ (succeeded: Bool, error: NSError?) -> Void in
if let error = error {
let errorString = error.userInfo?["error"] as? String
// Show the errorString somewhere and let the user try again.
} else {
// Hooray! Let them use the app now.
}
}
}
And I'd recommend to name your object's fields starting with lowercase letter, so that it can't be confused with class names.
Related
Currently learning Swift & iOS. I try to access with Parse a saved picture. However, I can't access it with getDataInBackground(block:).
Here's my code:
//
// ViewController.swift
// Instragram
//
// Created by Macbook Pro on 22.07.17.
// Copyright © 2017 Macbook Pro. All rights reserved.
//
import UIKit
import Parse
class ViewController: UIViewController {
#IBOutlet weak var picture: UIImageView!
#IBOutlet weak var senderLbl: UILabel!
#IBOutlet weak var recieverLbl: UILabel!
#IBOutlet weak var messageLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Creating tables and data in database
let imageData = UIImageJPEGRepresentation(picture.image!, 0.5)
let file = PFFile(name: "picture.jpg", data: imageData!)
let table = PFObject(className: "messages")
table["sender"] = "Akhmed"
table["reciver"] = "Bob"
table["picture"] = file
table["message"] = "Hello!"
table.saveInBackground {(success, error) -> Void in
if(success){
print("Saved successful")
} else {
print(error!)
}
}
//Recieving Data from the Server
let information = PFQuery(className: "messages")
information.findObjectsInBackground{(objects: [PFObject]?, error) -> Void in
if error == nil {
for object in objects!{
self.senderLbl.text = object["sender"] as? String
self.recieverLbl.text = object["reciver"] as? String
self.messageLbl.text = object["message"] as? String
object["picture"].getDataInBackground(...)
}
} else {
print(error!)
}
}
}
}
Down after I access the name, receiver and message string I try to access an image that has been saved on there server with:
object["picture"].getDataInBackground(block:)
However, Swift won't even autocorrect anymore after I've typed object["picture"]. I get also an error:
'Value of type "Any" has no Member 'getDataInBackground(block:)'
Any ideas what's wrong? It seems to me that Swift can't find the string picture even though the image is saved on the server under the string "picture".
You need to first cast it as a PFFfile object and then retrieve the actual image data with getDataInBackground function like this:
let imageFile = object["picture"] as? PFFile
imageFile?.getDataInBackground (block: { (data, error) -> Void in
if error == nil {
if let imageData = data {
self.myImage = UIImage(data:imageData)
}
}
})
I do not get any errors and the application builds fine but when I check parse, there is no new user added. here is the code:
import UIKit
import Parse
class ViewController: UIViewController {
#IBOutlet var passwordTextField: UITextField!
#IBOutlet var emailTextField: UITextField!
//#IBOutlet var messageLabel: UILabel!
#IBAction func loginVerifyButton(sender: AnyObject) {
var pwdEntered = passwordTextField.text
var emlEntered = emailTextField.text
if pwdEntered != "" && emlEntered != "" {
// If not empty then yay, do something
func userSignUp() {
var user = PFUser()
user.email = emlEntered
user.password = pwdEntered
user.signUpInBackgroundWithBlock {
(succeeded: Bool, error: NSError?) -> Void in
if let error = error {
let errorString = error.userInfo?["error"] as? NSString
// Show the errorString somewhere and let the user try again.
} else {
// Hooray! Let them use the app now.
}
}
}
}else {
//self.messageLabel.text = "All Fields Required"
}
You should be setting the userName of the PFUser as well, you are only setting the email and passwrod, but you should do this, ObjC, sorry:
PFUser *user = [PFUser user];
user.password = [[[self contentView] passwordField] text];
user.email = [[[self contentView] emailField] text];
user.username = [[[self contentView] emailField] text];
and then doing this:
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
//do work
} else {
//bad stuff
}
}];
Just set the userName to the the email address
AND if you read the header files for Parse API, you find this:
#abstract Signs up the user *asynchronously*.
#discussion This will also enforce that the username isn't already taken.
#warning Make sure that password and username are set before calling this method.
#param block The block to execute.
It should have the following argument signature: `^(BOOL succeeded, NSError *error)`.
*/
- (void)signUpInBackgroundWithBlock:(PF_NULLABLE PFBooleanResultBlock)block;
This means that you must have a userName declared in the PFUser. So, change from this:
var user = PFUser()
user.email = emlEntered
user.password = pwdEntered
user.signUpInBackgroundWithBlock {
to this:
func myMethod() {
var user = PFUser()
user.username = "myUsername"
user.password = "myPassword"
user.email = "email#example.com"
// other fields can be set just like with PFObject
user["phone"] = "415-392-0202"
user.signUpInBackgroundWithBlock {
(succeeded: Bool, error: NSError?) -> Void in
if let error = error {
let errorString = error.userInfo?["error"] as? NSString
// Show the errorString somewhere and let the user try again.
} else {
// Hooray! Let them use the app now.
}
}
}
from Parse's web site itself
I am trying to make an app that uses a login system. I have created an array for both the usernames and the passwords. But I need to test if the password is correct or not. How can I create an if statement that tests for values that are inside of an array? Here is my code in case you need it.
import UIKit
var namesArray = [String]()
var passWordArray = [String]()
class ViewController: UIViewController {
var username = "Ege"
var password = "Gürkan"
var trueFalse = true
#IBOutlet weak var idTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var trueWrongLabel: UILabel!
#IBAction func buttonPressed(sender: AnyObject) {
if idTextField.text == "Ege" && passwordTextField.text == "Gürkan" {
self.performSegueWithIdentifier("geçiş", sender: self)
} else {
trueWrongLabel.text = "Wrong id/pw"
idTextField.resignFirstResponder()
passwordTextField.resignFirstResponder()
trueWrongLabel.textColor = UIColor.redColor()
idTextField.text = nil
passwordTextField.text = nil
}
}
override func viewDidLoad() {
super.viewDidLoad()
NSUserDefaults.standardUserDefaults().setObject(namesArray, forKey: "nameArray")
var recalledNameArray = NSUserDefaults.standardUserDefaults().objectForKey("nameArray")! as NSArray
NSUserDefaults.standardUserDefaults().setObject(passWordArray, forKey: "passWordArray")
var recalledPassWordArray: AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("passWordArray")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In the line that says: if isTextField.text == "Ege"
I want to test if there is a value for what has the user just entered in the textfield. How can I do it?
PS: I am very new to programming in general so please don't use complicated terms while explaining
This is beginning programming stuff.
There are lots of ways to do this.
One straightforward way would be to create a struct that contains a name property and a password property. Then create an array of the structs. When the user enters a username and password, use a filter command to find the structure that contains the matching username, and then check to see if the password is correct.
If you're not comfortable with the Swift filter function (I haven't used it yet myself) then you could also loop through the array yourself looking for matches.
Why you are using Array for userName and Array for Password?
How can you know if that password for that userName?
I advice you to use Dictionary it is the best solution for you.
so one Dictionary for username and password and the values will be:
key:value
Ege:Gürkan
and the code will be:
for (key,value) in dic
{
if (key == idTextField.text && value == passwordTextField.text)
{
println("true")
}
}
I hope this is what you want!.
I have a table view in my Chat app that holds Users that are logged in to the application. This app is in Swift and the table view is embedded in a Navigation controller. I'm also using Parse.
When I click on a User, it sends me to a chat screen which it's suppose to do. Then when I click the Back button, it takes me back to the User table view as it should, but something strange happens. It has the Users that are logged in, but shows them twice. For example, If User1 is logged in to the app, I click on it to chat, then go back to the table view, it now shows User1 twice. If I repeat the process, it then shows User1 three times. Hopefully someone can help...
Variables:
import UIKit
// Global Variable
var userName = ""
class usersVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var resultsTable: UITableView!
var resultsUsernameArray = [String]()
var resultsProfileNameArray = [String]()
var resultsImageFile = [PFFile]()
override func viewDidLoad() {
super.viewDidLoad()
let theWidth = view.frame.size.width
let theHeight = view.frame.size.height
resultsTable.frame = CGRectMake(0, 0, theWidth, theHeight-64)
// PFUser.currentUser().username is part of Parse framework
userName = PFUser.currentUser()!.username!
}
Then here is the viewDidAppear where I believe is the issue:
override func viewDidAppear(animated: Bool) {
let predicate = NSPredicate(format: "username != '"+userName+"'")
var query = PFQuery(className: "_User", predicate: predicate)
var theObjects = query.findObjects()
for object in theObjects! {
// object.username is the name of the username class in Parse, as well as "profileName" and "photo"
self.resultsUsernameArray.append(object["username"] as! String)
self.resultsProfileNameArray.append(object["profileName"] as! String)
self.resultsImageFile.append(object["photo"] as! PFFile)
self.resultsTable.reloadData()
}
}
Not sure if this is needed but it had some of the same variables and deals with the Table View:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : ResultsCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ResultsCell
cell.usernameLbl.text = self.resultsUsernameArray[indexPath.row]
cell.usernameLbl.hidden = true
cell.profileNameLbl.text = self.resultsProfileNameArray[indexPath.row]
resultsImageFile[indexPath.row].getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.profileImg.image = image
}
}
return cell
}
Let me know if more code is needed!
Thank you,
Jack
You should change your viewDIdAppear() method little bit way like this,
override func viewDidAppear(animated: Bool) {
let predicate = NSPredicate(format: "username != '"+userName+"'")
var query = PFQuery(className: "_User", predicate: predicate)
var theObjects = query.findObjects()
self.resultsUsernameArray.removeAll(keepCapacity: true)
self.resultsProfileNameArray.removeAll(keepCapacity: true)
self.resultsImageFile.removeAll(keepCapacity: true)
for object in theObjects! {
// object.username is the name of the username class in Parse, as well as "profileName" and "photo"
self.resultsUsernameArray.append(object["username"] as! String)
self.resultsProfileNameArray.append(object["profileName"] as! String)
self.resultsImageFile.append(object["photo"] as! PFFile)
self.resultsTable.reloadData()
}
}
HTH, Enjoy Coding !!
I am using Swift with SQLite.swift. I have the following UIViewController:
class LoginViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
MySQLite().updateLatestEmailAddressFromUserTable() // breaks here (email is in console, though...)
}
}
Then I am trying to update it's value (through the setEmailAddress function) from another class:
class MySQLite {
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email#domain.com
LoginViewController().setEmailAddress(user[email]) // breaks here
}
}
}
above code gives me the following error
fatal error: unexpectedly found nil while unwrapping an Optional value
To explain a little further: I am retrieving the most recent entry in SQLite table to get the user's email address and update the text field in the login view controller. This allows for easier log in for returning users.
I have been struggling with this for over 2 hours now and trying various things. The main problem I believe is that when I try to simply return the email address as string from my second function and set the field directly from LoginViewController, it doesn't work (SQLite related code was not "executed" yet I believe).
possibly related thread (Obj-C):
set UITextField.text from another class
Here whats happening LoginViewController().setEmailAddress(user[email]) creates new instance of LoginViewController which is not same as your current LoginViewController.
Why don't you make protocol and define as delegate in MySQLite
And LoginViewController will have implementation of update method. Pass the delegate to MySqlite
In MySQLite when you get the value form database call the delegate update method.
Example
MySQLite
protocol loginDelegate
{
func update(NSString)
}
class MySQLite {
var delegate:loginDelegate?
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email#domain.com
if((delegate) != nil)
{
delegate?.update("example#example.com")
}
}
}
}
class LoginViewController: UIViewController,loginDelegate {
#IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
var mySQLite: MySQLite=LoginClass();
mySQLite.delegate=self;
[mySQLite .updateLatestEmailAddressFromUserTable()];
}
func update(email: NSString) {
println(email);
emailField.text = email
}
}
Make sure that the view which has the emailField has been instantiated on the screen.
#IBOutlet weak var emailField: UITextField!
This is an optional, which will be nil until the storyboard or nib for it is loaded. I assume OnBoardingRegistrationFormController is an instance of your LoginViewController class?
I see you've accepted an answer, but in this case creating a protocol is likely overkill. If sqlite is your model, why not just have the function return a value, and then you can assign the value to the text field in the controller. ex.
class LoginViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
emailField.text = MySQLite().updateLatestEmailAddressFromUserTable()
}
}
class MySQLite {
func updateLatestEmailAddressFromUserTable() -> String{
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email#domain.com
return user[email]
}
}
}
The issue is that LoginViewController's view isn't loaded when you try to assign a text to the textField. i.e: emailField is nil and unwrapping nil values leads to a runtime crash (since the outlet has not been connected to it's storyboard/xib counterpart).