Swift Parse - using PFQuery orQueryWithSubqueries function - ios

I am looking at the Parse documentation, and there is this interesting function I would like to use to make validate for signing up users if the username and email provided are registered (taken) or not. The documentation provides example for the following:
var lotsOfWins = PFQuery(className:"Player")
lotsOfWins.whereKey("wins", greaterThan:150)
var fewWins = PFQuery(className:"Player")
fewWins.whereKey("wins", lessThan:5)
var query = PFQuery.orQueryWithSubqueries([lotsOfWins, fewWins])
query.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// results contains players with lots of wins or only a few wins.
}
}
my version of it is:
/*Check username and email not taken*/
let usernameInputCheck = PFQuery(className:"_User")
usernameInputCheck.whereKey("appUsername", equalTo: self.usernameTxtField.text!)
let emailInputCheck = PFQuery(className:"_User")
emailInputCheck.whereKey("email", equalTo:self.emailTxtField.text!)
let query = PFQuery.orQueryWithSubqueries([usernameInputCheck, emailInputCheck])
query.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// results contains players with lots of wins or only a few wins.
}
}
I want to be able to check if email or username is taken, and if yes set a flag so that I can set message to user saying for example: "Email provided is already registered" or "Username is not available, try a different one".
Thanks for your help in advance.
Update: Here is the link to Parse docs: https://parse.com/docs/ios/guide#queries-compound-queries

Here is some objective-c that does the trick, which you could easily adapt to Swift.
PFQuery * nameQuery = [PFQuery queryWithClassName:#"user"]
[nameQuery whereKey:"username" equalTo:username];
PFQuery * emailQuery = [PFQuery queryWithClassName:#"user"];
[emailQuery whereKey:"email" equalTo:email];
PFQuery * query = [PFQuery orQueryWithSubqueries:#[nameQuery, emailQuery]
[query countObjectsInBackgroundWithBlock:^(int number, NSError *error) {
if(number > 0) {
//Email address OR username is already in use.
}
}];

Workaround the problem:
let usernameInputCheck = PFQuery(className:"_User")
usernameInputCheck.whereKey("appUsername", equalTo: self.usernameTxtField.text!)
let emailInputCheck = PFQuery(className:"_User")
emailInputCheck.whereKey("email", equalTo:self.emailTxtField.text!)
let query = PFQuery.orQueryWithSubqueries([usernameInputCheck, emailInputCheck])
query.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error == nil {
let checkResult = self.emailOrUsernameIsTaken(results!)
if(checkResult != 0 && checkResult == 1)
{
//username taken
}else if (checkResult != 0 && checkResult == 2){
//email taken
}
}
}
and here is the function:
func emailOrUsernameIsTaken(results: [PFObject])->Int
{
/*Check if username is taken or if email is taken*/
var preferenceTaken: Int = 0
if(results[0]["email"] as! String != "" && results[0]["email"] as! String == self.userObject.email!)
{
preferenceTaken = 1
}else if(results[0]["appUsername"] as! String != "" && results[0]["appUsername"] as! String == self.userObject.username!){
preferenceTaken = 2
}
return preferenceTaken
}

Related

Is it possible to query dictionary on parse.com?

i’m trying to search dictionary match result but no luck
my parse dictionary column look like this
columnName: Tag property: object
{"firstKey”:”David”,”secondKey”:”Guetta”}
columnName: name property: string
cool

when I try to search name column
here is my code snippet,
static func parseQueryDictionary() {
let query = PFQuery(className:"TestDictionary")
query.whereKey("name", equalTo: "cool")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil && objects != nil {
print("objects is", objects)
} else {
print(error)
}
}
}
i get result below
objects is Optional([ {
Tag = {
firstKey = David;
secondKey = Guetta;
};
name = cool;
tagArray = (
David,
Guetta
);
}])
i've try array column
columnName: tagArray property: array
["David","Guetta"]
static func parseQueryDictionary() {
let query = PFQuery(className:"TestDictionary")
query.whereKey("tagArray", equalTo:"David")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil && objects != nil {
print("objects is", objects)
} else {
print(error)
}
}
}
i get result
objects is Optional([ {
Tag = {
firstKey = David;
secondKey = Guetta;
};
name = cool;
tagArray = (
David,
Guetta
);
}])
but when i try to search dictionary column
columnName: Tag property: object
{"firstKey”:”David”,”secondKey”:”Guetta”}
like this
static func parseQueryDictionary() {
let query = PFQuery(className:"TestDictionary")
query.whereKey("Tag", equalTo:"David")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil && objects != nil {
print("objects is", objects)
} else {
print(error)
}
}
}
i get no result
objects is Optional([])

i’ve try google and parse official doc but can’t find this case, is it possible to do that?
i've try search string column, array column it's work but only dictionary column not work...
search in google with "findObjectsInBackgroundWithBlock" in swift.It will give you many results.
var query = PFQuery(className: parseClassName)
query.whereKey("Position", equalTo: "iOS Developer")//Here Position is column name and Sales Manager is value.
query.findObjectsInBackgroundWithBlock ({(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
for object in objects {
}
}
else{
println("Error in retrieving \(error)")
}
})

How to check UserName taken in parse Xcode

I'm trying to check if username is already taken in parse or not, but seems don't work with my code, can you please what i'm doing wrong on it
Thanks
func usernameIsTaken(userName: String) -> Bool {
let userName = userNameTextField.text
let myUser: PFUser = PFUser.currentUser()!
//bool to see if username is taken
var isTaken : Bool = false
//access PFUsers
let query = PFUser.query()
query!.whereKey("username", equalTo: userName!)
query!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]? , error : NSError? ) in
if error == nil {
if (objects!.count > 0) {
isTaken = true
print("username is taken")
} else {
print("Username is available. ")
}
} else {
print("error")
}
}
return isTaken
}
For one, you can attempt to sign the user up and Parse will return an error code of 202 if the username has already been taken.
http://parse.com/docs/dotnet/api/html/T_Parse_ParseException_ErrorCode.htm
If this isn't your intended use, to query the User table, use PFUser.query to construct a query instead.
Try this :
query.findObjectsInBackgroundWithBlock({ (object: [PFObject]?,error: NSError?) -> Void in
if error == nil {
}
})
With that being said if your only Interested in the count parse introduced a new method similar to findObjectsInBackground but does exactly what you are looking for, the method is called countObjectsInBackground
You can call this method after you define your query.
like so
query.countObjectsInBackgroundWithBlock { (count: Int32,error: NSError?) -> Void in
if error == nil {
//code here
}
Hope this helps

Swift - Parse - Check if username is taken

I am trying to create a function that takes a username as a parameter and checks to see if that username is taken (by comparing it to other PFUsers in the Parse database. This function is in my view controller class. (I know there are similar questions to this but they do not provide quality answers and are more general than this or are not in Swift).
func usernameIsTaken(username: String) -> Bool {
//bool to see if username is taken
var isTaken: Bool = false
//access PFUsers
var query : PFQuery = PFUser.query()!
query.whereKey("User", equalTo: username)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) in
if error == nil {
if (objects!.count > 0){
isTaken = true
println("username is taken")
} else {
println("Username is available. ")
}
} else {
println("error")
}
}
return isTaken
}
The problem is that the condition in the if statement is always false so "Username is available" always prints in the console even if the username is taken."Username is taken" is never printed even when the username is taken. What should I put in the nested if statement to check if the username matches another PFUser?
You are querying for User (class) key, but you need to query for a specific key, for example email.
// First get user's inputted email
let enteredEmailAddress = "sample#gmail.com"
// Then query and compare
var query = PFQuery(className: "_User")
query.whereKey("email", equalTo: enteredEmailAddress)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) in
if error == nil {
if (objects!.count > 0){
isTaken = true
println("username is taken")
} else {
println("Username is available. ")
}
} else {
println("error")
}
}
Just thought I would throw this out there, since this doesn't seem to be well known by people as I've answered a similar question before. Parse does this kind of checking for the user class automatically. If you're trying to create a new user with any of the default fields duplicated in Parse i.e username, email, etc, then Parse will not allow user signup. This is done automatically, with you having to do nothing, except for present the error so the user knows why they weren't able to sign up successfully. An example of signing a user up that checks for username email etc duplicates follows below:
user.signUpInBackgroundWithBlock {
(succeeded: Bool, signupError: NSError?)
-> Void in
if signupError == nil {
//present new controller
println("Signed up")
}
else {
if let errorString = signupError!.userInfo?["error"] as? NSString
{
error = errorString as String
}
else {
error = "We're sorry, an error ocured! Please try again."
}
self.displayAlert("Could not sign up", error: error)
}
}
}
Check the error code. Last time I did this, code 202 = Username Taken, code 203 = e-mail taken.
if signupError == nil {
print("User \(user.username!) signed up OK!")
} else if signupError?.code == 202 {
print("Username taken. Please select another")
} else if signupError?.code == 203 {
print("e-Mail taken. Please select another")
}

Letting User Update Password - Parse - Swift

I am trying the code below to let users update their password when a uibutton is clicked. However, ever when I enter the current password right, I get the "wrong current password" message. I guess the system does not compare the entered value with the current password right. Without the first if condition, I can update the password. But I want the user to enter current password for security reasons first. May anyone help?
#IBAction func updatePasswordBtn(sender: AnyObject) {
var passwordCheckQuery = PFQuery(className: "_User")
passwordCheckQuery.whereKey("username", equalTo: PFUser.currentUser()!.username!)
var objects = passwordCheckQuery.findObjects()
for object in objects! {
if currentPassword.text == PFUser.currentUser()!.password {
if newPassword.text == retypeNewPassword.text {
var query6 = PFUser.query()
query6!.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query6!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
for object6 in objects! {
var ob6:PFObject = object6 as! PFObject
ob6["password"] = self.newPassword.text
ob6.save()
}
}
}
else { println("passwords dont match")
}
}
else { println("wrong current password")
}
}
}
I updated my code as below after #Wains comment and it started to work.
#IBAction func updatePasswordBtn(sender: AnyObject) {
PFUser.logInWithUsernameInBackground(PFUser.currentUser()!.username!, password: currentPassword.text) {
(user:PFUser?, error:NSError?) -> Void in
if error == nil {
var passwordCheckQuery = PFQuery(className: "_User")
passwordCheckQuery.whereKey("username", equalTo: PFUser.currentUser()!.username!)
var objects = passwordCheckQuery.findObjects()
for object in objects! {
if self.newPassword.text == self.retypeNewPassword.text {
var query6 = PFUser.query()
query6!.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query6!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
for object6 in objects! {
var ob6:PFObject = object6 as! PFObject
ob6["password"] = self.newPassword.text
ob6.save()
println("successfully updated password")
}
}
}
else { println("passwords dont match")
}
}
} else {
println("wrong current password")
}
}
}
The password isn't available to you, so doing PFUser.currentUser()!.password isn't going to give you something you can check against. To verify a password you need to log the user in - i.e. take the user name and password they give you and use PFUser.logInWithUsernameInBackground.... If you get a valid user back then you can set the password and save.

Calling values from a random row in Parse?

I'm trying to figure out how to call values from all columns for each variable within a random row, and each row is denoted by its own specific objectId, which is the name of the column, on Parse. Here is where I've defined the values of the variables in each column:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var voteCount1 = PFObject(className: "VoteCount")
voteCount1["choices"] = 2
voteCount1["votes"] = Int()
voteCount1["votes2"] = Int()
voteCount1["optionName"] = String()
voteCount1["optionName2"] = String()
}
I've figured out how to make it so that a button will send a vote to a variable's vote count (defined as an Int) in the row of a specific object ID, but I don't know how to call polls from a random Object ID and send votes to the corresponding choices in that row. Here's my IBAction of adding votes to a variable of a specific object ID:
#IBAction func addVote1(sender: AnyObject) {
for button in self.buttons {
button.enabled = false
}
var query = PFQuery(className: "VoteCount")
query.getObjectInBackgroundWithId("BiEM17uUYT") {
(voteCount1: PFObject!, error: NSError!) ->Void in
if error != nil {
NSLog("%#", error)
} else {
voteCount1.incrementKey("votes")
voteCount1.saveInBackgroundWithTarget(nil, selector: nil)
}
let votes = voteCount1["votes"] as Int
let votes2 = voteCount1["votes2"] as Int
let percent1 = votes * 100 / (votes + votes2)
let percent2 = votes2 * 100 / (votes + votes2)
self.pollResults1.text = "\(percent1)% (\(votes)) \(percent2)% (\(votes2))"
}
}
How do I call values from random rows?
UPDATE: I just tried the following re-written from objective-C but I'm not sure if it's right:
var query = PFQuery(className: "VoteCount")
query.findObjectsInBackgroundWithBlock {
(objects: NSArray, error: NSError!) -> Void in
if error == nil {
randNumber = arc4random_uniform(count)
query2.whereKey("voteNumber", equalTo:randNumber)
query2.getFirstObjectInBackgroundWithBlock {
(voteCount1: PFObject!, error: NSError!) -> Void in
if error != nil {
NSLog("%#", error)
} else {
let votes = voteCount1["votes"] as Int
let votes2 = voteCount1["votes2"] as Int
let option1 = voteCount1["optionName"] as String
let option2 = voteCount1["optionName2"] as String
self.showOption1.text = "\(option1)"
self.showOption2.text = "\(option2)"
}
}
}
You would never hard-code object ids in your code. In order to fetch a random row, simply fetch all of the rows from Parse and then select one at random.
For example
PFQuery *query = [PFQuery queryWithClassName:#"VoteCount"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSInteger index=arc4random_uniform(objects.count);
NSLog("The random object is %#",objects[index]);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
For a more useful implementation you would probably store the objects array into a property so that you could refer to it from outside the block.
Note that by default, only the first 100 rows will be returned. You can increase the limit up to 1000. Beyond 1000 you have to use paging with multiple queries. See https://parse.com/questions/fetch-all-data-in-a-table-using-pfquery
var query = PFQuery(className: "VoteCount")
query.findObjectsInBackgroundWithBlock {
(objects: NSArray, error: NSError!) -> Void in
if error == nil {
if let randomObject=objects[arc4random_uniform(objects.count)] {
println("The random object is \(randomObject)\")
}
} else {
println("error \(error)")
}
}

Resources