I have an app where I'm trying to load a User and all his related data. In the relations I have BodyTracking as one relation. Another is DiaryWeek, which in turn has DiaryDays (of the week).
I successfully pulled all the BodyTracking, but when I try the same for the DiaryWeeks, I get an error saying that I have to wait. I guess what is happening is that the BodyTracking, which is requested with 'findObjectsInBackgroundWithBlock' is still going on when the DiaryWeek request is called.
Is there a way to pull all the data in one go?
// Body Tracking
bodyEntries.removeAll()
let trackingQuery = PFQuery(className: "BodyTracking")
trackingQuery.whereKey("user", equalTo: member)
trackingQuery.orderByDescending("trackingDate")
trackingQuery.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) body entries.")
if let objects = objects! as? [PFObject] {
for object in objects {
let bodyEntry = BodyTracking(object: object)
self.bodyEntries.append(bodyEntry)
}
self.bodyTrackingTableView.reloadData()
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
// Food Diary
foodWeeks.removeAll()
let diaryQuery = PFQuery(className: "FoodDiaryWeek")
diaryQuery.whereKey("user", equalTo: member)
diaryQuery.orderByDescending("weekStartDate")
trackingQuery.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) food weeks")
if let objects = objects! as? [PFObject] {
for object in objects {
let foodWeek = FoodDiaryWeek(object: object)
self.foodWeeks.append(foodWeek)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
Error message: This query has an outstanding network connection. You have to wait until it's done.
It looks like you are accidentally executing the trackingQuery twice. The diaryQuery is never executed. Maybe a copy/paste error (?)
// Food Diary
foodWeeks.removeAll()
let diaryQuery = PFQuery(className: "FoodDiaryWeek")
diaryQuery.whereKey("user", equalTo: member)
diaryQuery.orderByDescending("weekStartDate")
**trackingQuery**.findObjectsInBackgroundWithBlock {
replace trackingQuery by diaryQuery
Related
I have a class named Post which stored the data of Image, Text and the upLoader.
The uploader is link or a pointer to the User class.
When I was testing
When the current user is equal to the user which is pointed, everything is good. However, when the current user is not equal to the uploader, I cannot got the data from the uploader such as username and email. The only data I could retrieve is [ {
}]
Code of Query
let query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) scores.")
if let objects = objects! as [PFObject]! {
for object in objects {
self.message.append(object["message"] as! String)
self.imageFiles.append(object["imageFile"] as! PFFile)
self.user.append(object["upLoader"] as! PFUser )
self.createdAT.append(object.createdAt!)
self.tableView.reloadData()
}
}
} else {
print("Error: \(error!) \(error!.userInfo)")
}
Can anyone help me?
Thanks
By default, Parse queries don't include the actual objects that are referenced by pointers, so your upLoader is just a reference to the object ID, not the actual object. To include the actual object, you just need to add includeKey to your query. For example:
let query = PFQuery(className:"Post")
query.includeKey("upLoader") // This should do the trick.
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) scores.")
if let returnedObjects = objects {
for object in returnedObjects {
self.message.append(object["message"] as! String)
self.imageFiles.append(object["imageFile"] as! PFFile)
self.user.append(object["upLoader"] as! PFUser )
self.createdAT.append(object.createdAt!)
dispach_async(dispatch_get_main_queue(), { () -> Void in
//UI stuff need to be on main thread
self.tableView.reloadData()
})
}
}
} else {
print("Error: \(error!) \(error!.userInfo)")
}
}
I've been getting this Command failed due to signal: Segmentation fault: 11 error for 2 days now, and I cannot wrap my head around why its doing so. The error pointed at a specific query I made to parse.. However to test if it was my code or just a bug, I copied this EXACT block from Parse's query doc into my project as a function:
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
And it threw the error once again to that block.. Xcode is has also been throwing this message to my compiler :
Why is this happening ?
UPDATE
so it seems Kevin's answer below cleared the compiler bug by letting the compiler tell me the type rather than specifying it in the query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in line , by correcting it to :
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
}
however this other block is a little more complex, how do i adjust it to rid the error? :
func loadBooks() {
var query = PFQuery(className: "Books")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
self.books.removeAll()
let bookObjects = objects as! [PFObject]
for (index, object) in enumerate(bookObjects) {
self.books.append(Book(pfBook: object))
}
}else if let secondMessage = error?.userInfo?["error"] as? String
where secondMessage == "The Internet connection appears to be offline." {
self.failedMessage(secondMessage)
self.activityIndicator.hidden = true
self.activityIndicator.stopAnimating()
}
dispatch_async(dispatch_get_main_queue()){
self.collectionView!.reloadData()
self.refreshControl.endRefreshing()
self.activityIndicator.stopAnimating()
}
}
}
objects is actually of type [PFObject]? not [AnyObject]?. A wild guess would say the root cause trying to downcast.
Anyway, just use the correct type to fix this
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
}
or just let the compiler tell you the type
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
}
let query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
print(objects)
if let objects = objects {
for object in objects {
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
Try this! It works!
How can I use a query to find the currentUser from a Parse Class and then write data into that user columns?
var query = PFQuery(className:"User")
query.whereKey("objectId", equalTo:PFUser.currentUser()!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
Change this line
query.whereKey("objectId", equalTo:PFUser.currentUser()!)
To:
query.whereKey("objectId", equalTo:PFUser.currentUser().objectId)
And also if you are querying from the parse user class it should be _User not User
To Only save data
var ObjectToSave = PFObject(className: "_User")
ObjectToSave["raw"] = "whateveryoulike"
ObjectToSave["UserId"] = PFUser.currentUser()?.objectId // this piece of code is when you create a new class
ObjectToSave.saveInBackgroundWithBlock { (success:Bool, error:NSError?) -> Void in
if error == nil{
println("data was saved")
}
else
{
println("error")
}
}
}
I don't think it is a good idea to save other data into the _User class, you should leave this class for the login or sign up. You should create a new class then save all new data with the userid...
you don't need to query for the current user.
Use this
var user = PFUser.currentUser()
user["one"] = "whateveryoulike"
user["two"] = "whateveryoulike"
user.saveInBackgroundWithBlock { (success:Bool, error:NSError?) -> Void in
if error == nil{
println("data was saved")
}
else
{
println("error")
}
}
}
I am working with Parse for the first time in my application, and everything seems to be working well with the exception of when I go to change existing data. I am simply trying to change a string value that I have stored in a column of one of my items.
This is the code I currently have:
func sendTimeToParse() {
var query = PFQuery(className: "ClassName")
query.whereKey("Name", equalTo: rideNamePassed)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil {
println("The getFirstObject request failed.")
} else {
// The find succeeded.
let object = PFObject(className: "ClassName")
object.setValue(self.timeSelected, forKey: "WaitTime")
object.saveInBackground()
println("Successfully retrieved the object.")
}
}
}
}
At the moment it just seems to create a new row of data and saves the time to that, however obviously I would like it to change the existing data in whatever row matches the name of the current record.
Anyone have any suggestions?
The problem is that you are creating a new PFObject with the line let object = PFObject(className: "ClassName") instead of using the retrieved object which is given as a parameter.
Simply delete the line let object = PFObject(className: "ClassName") and unwrap the received optional. It could look something like the following:
func sendTimeToParse() {
var query = PFQuery(className: "ClassName")
query.whereKey("Name", equalTo: rideNamePassed)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil {
println("The getFirstObject request failed.")
} else {
if let obj = object {
obj.setValue(self.timeSelected, forKey: "WaitTime")
obj.saveInBackground()
}
println("Successfully retrieved the object.")
}
}
}
I'm using Parse
I have a "Post" class with fields.
Post class have some field, and one of it is "user" linked with "User" class
I want query Post class and get all the users in the response.
let query = PFQuery(className: "Post")
// How to get all user in the post class
Is there another way like..
let query = PFQuery(className: "Post")
let usersQuery = PFUser.query()
usersQuery.whereKey("SELF", matchesKey: "user", inQuery: query)
But I know there is no SELF keyword
Objective C is also fine
Given this page in the Parse documentation, it should look something like this:
let query = PFQuery(className: "Post")
query.findObjectsInBackground() { posts, error in
if (!error) {
for post in posts {
let user = post["user"]
println("User: \(user)")
}
} else {
// Log details of the failure
println("Error: \(error), \(error.userInfo)")
}
}
In Parse you use a PFQuery to query the database..
In a callback (asynchronusly) you get a PFObject or an array of PFObjects.
How to do this is written in their guide
Here's a little example:
You can get all properties/fields whatever by calling the array function on the PFObject.
var pfObject = PFObject()
pfObject["yourcolumn"] as? String //Whatever you want
In your case a PFUser would be the solution
pfObject["yourusercolumn"] as? PFUser
To query you use a PFQuery
Asynchronusly (preffered):
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
Synchronusly:
var query = PFQuery(className:"GameScore")
var objects = query.findObjects()
for object in objects {
// Do whatever you want with your pfobject
}
Asynchronus queries are more likely because they don't run on the GUI thread what makes your app way more faster (on the UI).