I am doing a query and I am checking to see if the value in the column "Parent", which is a pointer, is equal to a string, newLogObjectId. I obviously cannot do this since a pointer and a string are a different value type, (returns nil). How do I compare a string to a string in a pointer?
//A string, for example, "MCeKMyxRIt"
let newLogObjectId = objectIdArray[markerIndex]
let query1 = PFQuery(className: "ComparablePhotos")
//"Parent" is a pointer referencing an objectId in another class. "newLogObjectId" is a string How do I check to see if the String of Parent is equal to newLogObjectId, a string?
query1.whereKey("Parent", equalTo:newLogObjectId)
Pointers in Parse don't point to a value, they point to a class (a PFObject). So it looks like your pointer named Parent is pointing to the Parse class NewLog. I'm assuming then the string you are wanting to check is a field in the class NewLog. Also, to include the pointer in the query, use query1.includeKey("PointerName"). Try this:
let newLogObjectId = objectIdArray[markerIndex]
let query1 = PFQuery(className: "ComparablePhotos")
query1.includeKey("Parent")
query1.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil){
if let comparablePhotos = objects as? [PFObject]{
for photo in comparablePhotos {
if let parentPointer:PFObject = photo["Parent"] as? PFObject{
if(parentPointer["columnWithString"] as! String == newLogObjectID){
// Do something
}
}
}
}
}else{
println(error)
}
})
Related
I have a chat filled with users and of course a username array. I want to get the profile picture associated with the username in order for each user in the username array. Parse, however, can only sort by ascending/descending order that I am aware of.
Therefore, I need to figure out how to sort the data once received.
I am ultimately appending a url to be used as the pic.
func getPics(_ completionHandler: #escaping () -> Void) {
let query = PFQuery(className: "_User")
var dictionary: [String : Int] = [:]
var unit = 0
for username in usernameArray {
unit += 1
dictionary[username] = unit
}
query.findObjectsInBackground(block: { (objects: [PFObject]?, error: Error?) in
if let objects = objects {
for object in objects {
if error == nil {
for user in self.usernameArray {
let pfuser = object["username"] as! String
if pfuser == user {
let imageFile = object["profilePic"] as? PFFileObject
let imageFileString = imageFile?.url as! String
if let url = URL(string: imageFileString) {
let replacedImageUrlString = imageFileString.replacingOccurrences(of: "[removed for privacy]", with: "removed for privacy")
let url = replacedImageUrlString as NSString
self.urlArray.append(url)
}
}
}
}
}
completionHandler()
}
})
}
I am not aware of Parse server, So I dont really know if there exists provision to get the response in specific order, if it exists that should be the optimal solution. But there is a generic issue with your solution, its the time complexity.
You have two nested for loops which makes its worst case complexity to be O(n^2), I guess the least you can do is to reduce its complexity to O(n)
func getPics(_ completionHandler: #escaping () -> Void) {
let query = PFQuery(className: "_User")
var dictionary: [String : Int] = [:]
var unit = 0
for username in usernameArray {
unit += 1
dictionary[username] = unit
}
query.findObjectsInBackground(block: { (objects: [PFObject]?, error: Error?) in
if let objects = objects, error == nil {
let objectsDict = Dictionary(grouping: objects, by: { $0["username"] as! String /* typically you should be accessing $0.username, but again am not aware of PFObject */})
for user in self.usernameArray {
if let pfuser = objectsDict[user]?[safe: 0] as? PFObject {
let imageFile = pfuser["profilePic"] as? PFFileObject
let imageFileString = imageFile?.url as! String
if let url = URL(string: imageFileString) {
let replacedImageUrlString = imageFileString.replacingOccurrences(of: "[removed for privacy]", with: "removed for privacy")
let url = replacedImageUrlString as NSString
self.urlArray.append(url)
}
}
}
completionHandler()
}
})
}
Once you get the array of PFObject, you can create a dictionary with username as the key and PFObject as value, once you have the dictionary you can get the PFObject for specific username in O(1), so you can run a single for loop which reduces your code's complexity to O(n)
P.S If you are wondering what [safe: 0] is you can add this handy extension to safely access object at specific index in an array
link: Safe (bounds-checked) array lookup in Swift, through optional bindings?
extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
P.P.S: My answer is completely ignoring the complexity of Dictionary(grouping: API itself, I tried to look for the info, but couldnt find. But I think its O(n) not really sure though, whatever it is if its not O(n^2) you will still be benefited
I'm trying to write a Swift query that will get the object in the Avatar table that matches the User's avatar Pointer column. The following query doesn't pull any results:
var userAvatar = self.user["avatar"]
let avatarQuery = PFQuery(className: "Avatar")
avatarQuery.whereKey("objectId", equalTo: userAvatar)
avatarQuery.limit = 1
avatarQuery.findObjectsInBackgroundWithBlock{
(results: [PFObject]?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let results = results as? [PFObject]! {
for result in results {
I think the problem is that the whereKey clauses is looking for a String, yet userAvatar is a PFObject. I tried converting the PFObject to String but that's not possible.
Am I overthinking this? How can I just get the Avatar object that matches the PFObject stored in User -> avatar(Pointer)?
Thanks!
EDIT: Thanks to Daniel, this is the working code (I think adding the includeKey might have helped too):
let userAvatar = self.user["avatar"] as! PFObject
let avatarQuery = PFQuery(className: "Avatar")
avatarQuery.whereKey("objectId", equalTo: userAvatar.objectId!)
avatarQuery.includeKey("avatar")
avatarQuery.limit = 1
avatarQuery.findObjectsInBackgroundWithBlock{
(results: [PFObject]?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let results = results as? [PFObject]! {
for result in results {
So I think your problem is that you should not be comparing a string to a PfObject the object is not a string but a price of the object may be a string so you should compare something like the object.id to a string. If that makes sense.
I'm getting objects from Parse and display it in my UI. Now I am working on saving the data in Local DataStorage of Parse. I looked at the following Parse example:
let query = PFQuery(className: "GameScore")
query.fromLocalDatastore()
query.getObjectInBackgroundWithId("xWMyZ4YE").continueWithBlock {
(task: BFTask!) -> AnyObject in
if let error = task.error {
// Something went wrong.
return task;
}
// task.result will be your game score
return task;
}
The above example if for fetching 1 object. I dont know how to do the same for multiple objects. I am fetching the objects through MY following code:
let query:PFQuery = PFQuery(className: "Events")
query.findObjectsInBackgroundWithBlock {
(object, error) -> Void in
if object != nil
{
if(object!.count != 0)
{
for messageObject in object! {
let eventName:String? = (messageObject as! PFObject)["EventName"] as? String
let createdBy:String? = (messageObject as! PFObject)["CreatedBy"] as? String
let eventDate:String? = (messageObject as! PFObject)["EventDate"] as? String
objModalClass.eveName = eventName!
objModalClass.crtedBy = createdBy!
objModalClass.eveVenue = eventVenue!
}
}
}
}
In my above code, how can I save all the fetched objects in objModalClass in Local DataStorage. Kindly explain in detail.
You should look object pinning. As long as you have enabled the local datastore, you can retrieve objects by a pin name, as well as releasing those objects from the local datastore with unpinning. From the docs:
"Asynchronously stores the object and every object it points to in the local datastore, recursively."
For single objects:
public func pinInBackgroundWithName(name: String, block:PFBooleanResultBlock?)
For many objects:
public class func pinAllInBackground(objects: [AnyObject]?, withName name: String, block: PFBooleanResultBlock?)
The complementary unpinWithName(name: String) is available for both scenarios. Pinning only works with PFObjects and its subclasses.
You can also query from a pin name like so
var query = PFQuery.queryWithClassname("PFObject_subclass")
query.fromPinWithName("Your_given_pin_name")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
//objects from pin name returned.
}
I have a pointer named "Parent" in my class, "ComparablePhotos", which points to another class, "NewLog". I am trying to get the data (Address, ObjectId, Lat) from the row in NewLog that Parent points to. How do I do this using query1.includeKey provided?
Code:
var query1 = PFQuery(className: "ComparablePhotos")
query1.includeKey("Parent")
//get NewLog[address], NewLog[lat], and NewLog[objectId] using "Parent" pointer
ComparablePhotos class:
NewLog class:
see if this helps you out at all...you probably will have to change some of the objects to exactly fit your words from the parse database.hopefully that will steer you in the right direction
var query1 = PFQuery(className:"NewLog")
query1.includeKey("Parent")
query1.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
var address = object["address"] as! String
var lat = object["lat"] as! String
var objectId = object["objectId"] as! String
this is how i query a role, which is similar to a pointer query...
var roleQuery = PFRole.query()
roleQuery!.whereKey("name", equalTo: "admin")
roleQuery!.getFirstObjectInBackgroundWithBlock() { (roleObject: PFObject?, error) -> Void in
var adminRole = roleObject as! PFRole
adminRole.users.query()!.findObjectsInBackgroundWithBlock({ (users, error:NSError?) -> Void in
if error == nil {
if let adminUsers = (users as? [PFUser]) {
I'm using Parse findObjectsInBackgroundWithBlock that returns [AnyObject]? how do I extract the column data?
You need to cast your results like so:
objects as? [PFObject], then each result will contain a PFObject dictionary with the column name as the key. for example o["id"] will return the value of the id column for a specific object
Just do
let data = objects as! [PFObject]
let firstObject = objects[0]
// firstObject["Column"]
Well it is easy like the code below,
In my case i get the score you can use your DB table column names
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
var score : Int? = object["score"] as! Int?
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}