iOS Swift 3 Deleting a row from TableView Using Parse - parse-platform

I am building an iOS app and I am trying to delete a row from the UITableView. I am also using Parse as the mobile-backend of the app. Here is code for the delete method:
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
let query = PFQuery(className: "Receipts")
let currReceipt = receipts[indexPath.row]
query.whereKey("objectId", equalTo: currReceipt.objectId!)
query.findObjectsInBackground(block: { (objects, error) in
if error != nil {
self.createAlert(title: "Oops! Something went wrong number 1!", message: "We could not delete the receipt")
print("THERE WAS AN ERROR DELETING THE OBJECT")
}else{
for object in objects!{
self.receipts.remove(at: indexPath.row)
object.deleteInBackground()
self.table.reloadData()
}
}
})
}
}
Just to clarify, there will only be one receipt in the database with any given "objectId", so the query.findObjectsInBackground should only be returning a single object.
When I try to delete a row in the simulator, I get the error "Object not found" even though I can see that the object exists in the database. What am I doing wrong?
UPDATE
Found my solution after a long time looking. For anyone interested, it had to do with the default ACL values for Read and Write permissions. Here is the link to the answer: Parse weird bug in Swift that causes ACL write permissions to change to an objectId

It might be a typo, but why do you have ! in this line?
query.whereKey("objectId", equalTo: currReceipt.objectId!)

Related

Trying to load Parse PFFiles into UITableView from query

I'm a new, in training, swift programmer and have run into an issue with an app that I'm trying to put together.
I've searched through the forum and have found really helpful information but haven't been able to resolve my issue based on the results unfortunately.
I have an app set up to upload user images as PFFiles to parse but can't seem to have them download to the tableview in my table view controller.
A majority of the code I have tried to implement hasn't caused any errors but also hasn't downloaded the desired images.
I apologize if this is a very basic issue but I've exhausted my researching outlets.
I have the images uploading to a single class called Post and want to be able to pull images based on the current user's ID.
I've tried querying the information but always have an error returned that says that the system was unable to find anything for the query. I'm not sure if there is a better way to upload and classify the information on parse or if I'm not coding the call back correctly. I'm essentially wanting to be able to retrieve the user's uploaded images and descriptions and display them on an "Account" page.
I'm working in Xcode 7.2 in Swift 2.
So there are three things we have to care about:
1. structure of post
It would be better if you store the User in a pointer. A pointer is easier to save and retrieve. (Pointers is a way to present one to many Relations, but in our case this means One to One).
So in the data browser(parse.com) replace the column "userID" with "user" type: Pointer, target class: User.
Then in xCode
post["user"] = PFUser.currentUser()
2. Get All posts of a User
Add this code:
let query = PFQuery(className: "Post")
query.whereKey("user", equalTo: PFUser.currentUser()!)
query.getFirstObjectInBackgroundWithBlock { (obj: PFObject?, err: NSError?) -> Void in
if err != nil{
// DO something with the objets:
myArray = obj
}
}
3. Get the image
Lets say you have a ImageView like imageView
let file: PFFile = post["imageFile"] as! PFFile
file.getDataInBackgroundWithBlock { (data: NSData?, err: NSError?) -> Void in
if data != nil{
imageView.image = UIImage(data: data!)
}
}
Now you're done:)
But just a little thing to improve your code:
You don't need to dismiss the Alert after OK is pressed because if you set style to .Cancel this is automatically done! So change
alert.addAction((UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil) })))
to
alert.addAction((UIAlertAction(title: "OK", style: .Cancel, handler: nil)))

I cannot find the currentUser() in parse

I am making an app so whenever somebody can press the add button and then type in one of their family member's emails and it will add the email to an array in parse. This is what my code looks like:
func Save() {
PFUser.currentUser()!.addObject(memberName.text!, forKey: "Family_Emails")
}
memberName is the TextField's IBOutlet connection name
"Family_Emails" is the parse array object I have set up
Whenever I click the save button it doesn't do anything. What do I do?
You're just not calling save on the user object.
PFUser.currentUser().saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
https://parse.com/docs/ios/guide#objects-saving-objects

'queryForTable' cannot return 'nil' In Swift

I am using PFQueryTableViewController as part of ParseUI to load a table of objects based on the currentUser's geolocation. I have seen several other (older) forum posts (like here) detailing that the queryForTable function should return nil if a value like currentLocation:PFGeoPoint? is nil. Then wait on the background process in viewDidLoad to get the PFGeoPoint and loadObjects(), thus calling the queryForTable function again.
I am seeing others say that Swift's ParseUI libraries may not have a queryForTable function that allows nil returns.
var currentLocation:PFGeoPoint? = nil
override func viewDidLoad() {
if currentLocation == nil {
PFGeoPoint.geoPointForCurrentLocationInBackground {
(geoPoint: PFGeoPoint?, error: NSError?) -> Void in
if error == nil {
print("Got the user's current location!")
self.currentLocation = geoPoint
print("Reloading table using user's location")
self.loadObjects()
}
}
}
}
override func queryForTable() -> PFQuery {
if self.currentLocation != nil {
print("Generating query based on user's location!")
let query = PFQuery(className:self.parseClassName!)
query.whereKey("taskLocation", nearGeoPoint: self.currentLocation!, withinMiles: 50)
if(self.objects?.count == 0)
{
query.cachePolicy = PFCachePolicy.CacheThenNetwork
}
return query
}
print("User's current location is not known")
return nil
}
Obviously, this fails to build because the function is not (note the question mark):
override func queryForTable() -> PFQuery? {
...
}
My attempted workaround was to return PFQuery() instead of nil, but I believe it returns after the viewDidLoad self.loadObjects(). The behavior I see is a momentary flash of a table with cell results, and then an empty table.
Here is a link to the Google Group discussion about this very issue, with Hector Ramos saying that it works with Objective-C but not Swift (...yet?). I'm running the latest ParseUI as of this posting (1.1.6).
Is there an option yet to do this in Swift? If not, when?
If this isn't an option, what are some workarounds people have tried successfully?
I actually figured this issue out - nothing to do with the code itself. Apparently, when you set a fake location on the iOS Simulator, it also enforces that different location when you use a real iOS device plugged in. My results were not showing up because there legitimately wasn't an object with a PFGeoPoint near my location (because it thought I was in London!)
Anyway, moral of the story is to make sure you always know your preset location in both Simulator and physical iOS devices.
PS - The code above does work when my location is set correctly.

how to delete class in parse local database

#IBAction func unPin(sender: AnyObject) {
guestInfo.unpinInBackground()
guestInfo.deleteInBackground()
}
I add a button function to delete the guestInfo PFObject I've created.
I tried this function but it simply won't work.
I also tried delete with object names,also not working,
hoping somebody can solve this.

Parse query returning nothing from findObjectsInBackgroundWithBlock

EDIT:
I changed the question title.
and I changed the function to findObjectsInBackgroundWithBlock -
override func viewDidAppear(animated: Bool) {
let predicate = NSPredicate(format: "username != '"+userName+"'")
var query = PFQuery(className: "_User", predicate: predicate)
var objects = query.findObjectsInBackgroundWithBlock({
(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
for object in objects {
self.resultsUsernameArray.append(object.username)
self.resultsProfileNameArray.append(object.email)
self.resultsImageFiles.append(object["photo"] as PFFile)
self.resultsTable.reloadData()
}
}else{
println("error in quert execution \(error)")
}
})
}
There is one warning [variable 'objects' inferred to have type 'Void', which may be unexpected], and the code still returns nothing. I have 3 users in my Parse account for this app.
There's no error anymore, I guess that's good at least?
I'm new to xcode, and can't find how to search for this function. I'm having the same issue with Parse that others have had. My find query worked twice, and now (with no changes to the code) it stops returning anything. I want to do as suggested and 'Break on warnBlockingOperationOnMainThread() to debug,' but the only project search feature I can find (right clicking the project and doing 'Find in selected groups') doesn't bring anything up.
So, how do I find this function to add a breakpoint? Or, better yet, why did this query stop working?
override func viewDidAppear(animated: Bool) {
let predicate = NSPredicate(format: "username != '"+userName+"'")
var query = PFQuery(className: "_User", predicate: predicate)
var objects = query.findObjects()
for object in objects {
self.resultsUsernameArray.append(object.username)
self.resultsProfileNameArray.append(object.email)
self.resultsImageFiles.append(object["photo"] as PFFile)
self.resultsTable.reloadData()
}
}
Thanks!
From: https://developer.apple.com/library/mac/recipes/xcode_help-breakpoint_navigator/articles/adding_a_symbolic_breakpoint.html
In the bottom-left corner of the breakpoint navigator, click the Add button.
Choose Add Symbolic Breakpoint.
Enter the symbol name in the Symbol field.
If the symbol is declared in more than one library, enter the name of the appropriate library in the Module field.
To specify that program execution be suspended only if an expression evaluates to true, enter the expression in the Condition field.
Click Done.

Resources