I am trying to save an object with the info retrieved from another object by a query with the code below. I am retrieving the object from class test2 with a query and want to save the object to class test1. However with the code below, when I make itemObj=ob1, the class name of itemObj starts to be test2. How can I carry all the info from ob1 to itemObj while keeping the class name as test1? Is there anyway to do this. I searched the web but couldn't find any similar issue? Thank you.
var itemObj = PFObject(className: "test1")
itemObj = ob1
itemObj.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
print("saved", terminator: "")
} else {
print("error", terminator: "")
}
}
When you created the var itemObj, you created a pfobject with a particular object id. You should not do it. You can either save the ob1 directly or, pass it like this:
var itemObj = PFObject(className: "test1")
itemObj["value1"] = ob1["value1"]
itemObj["value2"] = ob1["value2"]
itemObj.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
print("saved", terminator: "")
} else {
print("error", terminator: "")
}
}
Related
So im a bit new to swift and object-c as well and was wondering if someone could help me out a bit.
I'm used to creating usually a utils file where I have functions I use often in programming.
In this case im trying to call a function from another swift file and return an array of data.
For example in my mainViewController.swift im calling the function:
var Data = fbGraphCall()
In the Utils.swift file I have a function that Im trying to get it to return an array of data collected.
func fbGraphCall() -> Array<String>{
var fbData: [String] = [""]
if (FBSDKAccessToken.currentAccessToken() != nil){
// get fb info
var userProfileRequestParams = [ "fields" : "id, name, email, about, age_range, address, gender, timezone"]
let userProfileRequest = FBSDKGraphRequest(graphPath: "me", parameters: userProfileRequestParams)
let graphConnection = FBSDKGraphRequestConnection()
graphConnection.addRequest(userProfileRequest, completionHandler: { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if(error != nil) {
println(error)
} else {
// DEBUG
println(result)
let fbEmail = result.objectForKey("email") as! String
// DEBUG
println(fbEmail)
fbData.append("\(fbEmail)")
let fbID = result.objectForKey("id") as! String
if(fbEmail != "") {
PFUser.currentUser()?.username = fbEmail
PFUser.currentUser()?.saveEventually(nil)
}
println("Email: \(fbEmail)")
println("FBUserId: \(fbID)")
}
})
graphConnection.start()
}
println(fbData)
return fbData
}
I can confirm that im getting the fbEmail and fbID back from facebook with my debug statements but as I said im still new on how to return data back.
Ideally I usually want an array back if its more than one value or the ability to get back data like Data.fbEmail, Data.fbID or an array maybe like ["email" : "email#gmail.com", "id" : "1324134124zadfa"]
When I hit the return statement its blank.. so not sure why the constants are not keeping values or passing values into my fbData array.. I'm trying fbData.append(fbEmail) for example ..
any thoughts on what might be wrong?
The graphConnection.addRequest is an asynchronous function and you are trying to synchronously return the array of strings back. This won't work because the graphConnection.addRequest is done in the background to avoid blocking the main thread. So instead of returning the data directly make a completion handler. Your function would then become this:
func fbGraphCall(completion: ([String]) -> Void, errorHandler errorHandler: ((NSError) -> Void)?) {
if (FBSDKAccessToken.currentAccessToken() != nil) {
// get fb info
var userProfileRequestParams = [ "fields" : "id, name, email, about, age_range, address, gender, timezone"]
let userProfileRequest = FBSDKGraphRequest(graphPath: "me", parameters: userProfileRequestParams)
let graphConnection = FBSDKGraphRequestConnection()
graphConnection.addRequest(userProfileRequest, completionHandler: { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if(error != nil) {
println(error)
errorHandler?(error!)
} else {
var fbData = [String]() // Notice how I removed the empty string you were putting in here.
// DEBUG
println(result)
let fbEmail = result.objectForKey("email") as! String
// DEBUG
println(fbEmail)
fbData.append("\(fbEmail)")
let fbID = result.objectForKey("id") as! String
if(fbEmail != "") {
PFUser.currentUser()?.username = fbEmail
PFUser.currentUser()?.saveEventually(nil)
}
println("Email: \(fbEmail)")
println("FBUserId: \(fbID)")
completion(fbData)
}
})
graphConnection.start()
}
}
I added the completion handler and the error handler blocks that get executed according to what's needed.
Now at the call site you can do something like this:
fbGraphCall( { println($0) // $0 refers to the array of Strings retrieved }, errorHandler: { println($0) // TODO: Error handling }) // Optionally you can pass `nil` for the error block too incase you don't want to do any error handling but this is not recommended.
Edit:
In order to use the variables you would do something like this at the call site
fbGraphCall( { array in
dispatch_async(dispatch_get_main_queue(), { // Get the main queue because UI updates must always happen on the main queue.
self.fbIDLabel.text = array.first // array is the array we received from the function so make sure you check the bounds and use the right index to get the right values.
self.fbEmailLabel.text = array.last
})
}, errorHandler: {
println($0)
// TODO: Error handling
})
I want load all image uisng one id that is pointer.I have 3 class that name is "categories","Ads" and "adimages".The image of class is as.
[][2[]3
I try to implement but can not get any succes.My implement code in xcode is like below
var DetaiId : AnyObject = ""
let query = PFQuery(className:"adImages")
query.whereKey("adIMG", equalTo:DetaiId)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
self.ImagearrCate = objects!
self.getImageData(objects! as [PFObject])
print(self.ImagearrCate)
//MBProgressHUD.hideAllHUDsForView(self.view, animated: true)
}
else {
print("Error")
print("Error: \(error!) \(error!.userInfo)")
}
}
func getImageData(objects: [PFObject]) {
for object in objects {
let thumbNail = object["image"] as! PFFile
print(thumbNail)
thumbNail.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if (error == nil) {
let image = UIImage(data:imageData!)
//image object implementation
self.mixPhotoArray.append(image)
print(image)
}
}
}//for - end
}
Here Detailid is get the id from selected row of tableview.That id is passed in wherekey.I get all the image from selected row id.For example in adIMG column i 5 entry for mDjQTYaPMg id.Nut no any image find.
If try to put static id then logcat error is
Error Domain=Parse Code=102 "pointer field adIMG needs a pointer value" UserInfo={code=102, temporary=0, error=pointer
You need to pass pointer value as value of adIMG parameter means you have to create PFObject of Ads class with specific objectId.
Then you have to pass this object as value of adIMG parameter.
See following Code to better understand. May be help you.
let objectAds = PFObject(withoutDataWithClassName:"GameScore", objectId:"xWMyZ4YEGZ")
And then pass like this in PFQuery.
let query = PFQuery(className:"adImages")
query.whereKey("adIMG", equalTo:objectAds)
I want to know how I could store the entire custom column (the user Pointer<_User> column from a custom class) and put them all in an array variable so that I can see if a the user exists in that class or not. This is what I have:
Old Code
var objectUserIdArray = [String]()
let objectUserIdQuery : PFQuery = PFQuery(className: "Scores")
objectUserIdQuery.findObjectsInBackgroundWithBlock {
(objects : [PFObject]? , error : NSError?) -> Void in
var objectID = objects! as [PFObject]
for i in 0..<objectID.count {
objectUserIdArray.append(objectID[i].objectId!)
}
for _ in objectID {
print(objectUserIdArray)
}
New Code
func saveScoresOnParse() {
objectUserIdQuery.whereKey("User", equalTo: PFObject(withoutDataWithClassName: "_User", objectId: userID))
objectUserIdQuery.findObjectsInBackgroundWithBlock {
(objects : [PFObject]? , error : NSError?) -> Void in
if error == nil {
//var objectID = objects! as [PFObject]
/*for i in 0..<objectID.count {
self.objectUserIdArray.append( objectID[i].objectId! )
}*/
for _ in objects! {
print(objects)
}
// The score key has been incremented
for (var i = 0 ; i < self.objectUserIdArray.count ; i++) {
if self.userID != objects![i] {
print("New Scores")
print("R: \(self.rightAnswers)")
print("W: \(self.wrongAnswers)")
print("S: \(self.skippedQuestions)")
self.scores["User"] = PFUser.currentUser()
self.scores["Right"] = self.rightAnswers
self.scores["Wrong"] = self.wrongAnswers
self.scores["Skipped"] = self.skippedQuestions
self.scores.saveInBackground()
} else if self.userID == objects![i] {
print("Updated Scores")
self.scores.incrementKey("Right", byAmount: 1)
self.scores.incrementKey("Wrong", byAmount: 1)
self.scores.incrementKey("Skipped", byAmount: 1)
print("R: \(self.rightAnswers)")
print("W: \(self.wrongAnswers)")
print("S: \(self.skippedQuestions)")
self.scores.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The score key has been incremented
} else {
// There was a problem, check error.description
}
}
} else {
print("Error")
}
}
} else {
print(error)
}
}
But it only stores the objectId column and not the Pointer<_User> column. I know this because when I print the stuff that is inside, it prints out the objectIds.
This is what happens, instead of just updating the current user's scores, it just makes new ones. I want the if statement to check if the user already exists in that column and if it does updates the scores and if it doesn't, make new ones. (The new code's if statement doesn't work, i have to bring it out for it to save...)
Your updated question make clearer what you are actually wanting to do;
Save or update a user's scores in your Parse Score object. To do this, there is no reason to retrieve any object Ids or loop through any results. More often than not you don't do use Object Ids explicitly when using Parse; you can simply pass the object itself with Parse working out the references for you.
I am not sure how you exactly want to change the scores; in your code above you increment in one case but set the scores explicitly in another, but the code below shows the general approach.
If you are frequently or repeatedly going to update a score record then you could make your code more efficient by holding a reference to the Scores object in a property after you find it the first time and simply update & save it subsequently.
func saveScoresOnParse() {
if let currentUser=PFUser.currentUser() {
let scoreQuery= PFQuery(className: "Scores")
scoreQuery.whereKey("User",equalTo:currentUser)
scoreQuery.getFirstObjectInBackgroundWithBlock {
(object : PFObject? , error : NSError?) -> Void in
if error == nil {
var scoreObject=object ?? PFObject.objectWithClassName("Scores")
if (scoreObject["User"]==nil) {
scoreObject["User"]=currentUser
}
scoreObject["Right"]=self.rightAnswers
scoreObject.saveInBackground()
} else {
print(error)
}
}
} else {
print("No current user!")
}
}
I am trying to make changes to the data already stored in the core data in Parse. But it is not making the necessary changes. And I looked at the documentation for parse regarding objects here: https://parse.com/docs/ios/guide#objects. And it seems that I am doing exactly what the document is telling me to do. Maybe I am missing something? Here is my code:
import UIKit
import Parse
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var products = PFObject(className:"Products")
products["name"] = "ice cream"
products["description"] = "Strawberry"
products["price"] = 4.99
products.saveInBackgroundWithBlock {
(success, error) -> Void in
if (success) {
println("Object saved with id \(products.objectId)")
} else {
println("Not successful!")
print(error)
}
}
//ignore the code below this line for now please :)
var query = PFQuery(className: "Products")
query.getObjectInBackgroundWithId("7lmnxHxibK", block: { (object: PFObject?, error) -> Void in
if error != nil {
print(error)
} else if let product = object {
print("YO")
product["description"] = "Rocky Road"
product["price"] = 5.99
products.saveInBackground()
}
})
}
}
So the code above created an object with the ID 7lmnxHxibK. The description being Strawberry, the name being ice cream, and the price being 4.99. Which worked as it should. So now as an attempt to change the attributes in the object with the ID 7lmnxHxibK, I wrote the following code:
var query = PFQuery(className: "Products")
query.getObjectInBackgroundWithId("7lmnxHxibK", block: { (object: PFObject?, error) -> Void in
if error != nil {
print(error)
} else if let product = object {
print("YO")
product["description"] = "Rocky Road"
product["price"] = 5.99
products.saveInBackground()
}
})
This code should make the necessary changes to the object with the id 7lmnxHxibK. But rather than making the necessary changes to the object's attributes, it is creating a new object with it's description, name, and price all being (undefined). Anybody have a solution to fix this?
You have to change products.saveInBackground() to product.saveInBackground(). Also by the time you call your second query parse may not be done saving the object for the first time.
I have a save button to save Score and Playername to GameScore in Parse. When I load the GameScore from Parse I want to set the value that i loaded to the variable "score". This don't work, can anyone please tell me what i am doing wrong?
Thanks
Exapmle: let score = gameScore["score"] as Int
// Load button tapped
#IBAction func loadButtonTapped(sender: UIButton) {
var query = PFQuery(className:"GameScore")
query.getObjectInBackgroundWithId("F1efANYzOE") {
(gameScore: PFObject?, error: NSError?) -> Void in
if error == nil && gameScore != nil {
println(gameScore)
let score = gameScore["score"] as Int
} else {
println(error)
}
}
}
}
Try this following code for retrieving specific data from specific columns. You have to enter your object name, Object ID and column name in the below code and run it. It will work.
let query = PFQuery(className:"Your Object name")
query.getObjectInBackgroundWithId("Your Object ID") {
(gameScore: PFObject?, error: NSError?) -> Void in
if error == nil {
print(gameScore!.objectForKey("your column name") as! String)
} else {
print(error)
}
}