Im trying to query my Parse User database in order to create a friend request between two users. The user inputs a user name that they want to add as a friend. However, when I try to query the database, I get a "EXC_BAD_ACCESS" error on the line where I am adding the condition. Not sure why Im getting this error, as its my understanding it has to do with trying to access memory already freed. Anything that you can do to help would be very appreciated!
var friendship = PFObject(className: "Friends")
var findUser:PFQuery = PFUser.query()
findUser.whereKey("username",equalTo:username2) //program crashes here for some reason
findUser.getFirstObjectInBackgroundWithBlock {
(user2, error: NSError!) -> Void in
if user2 == nil {
println("Failure")
} else {
println("Successfully retrieved the object.")
friendship["user1"] = PFUser.currentUser().objectId
friendship["user2"] = user2.objectId
friendship["pending"] = true
friendship.save()
}
}
Set a breakpoint in the compiler and navigate the steps until you hit the crash so you can understand exactly at which point it crashes a troubleshoot further from there with the better understanding.
Also once it has crashed use LLDB print out po ivar to check if any of your ivars got instantiated and which ones are empty or execute dubious functions with exp func.
So... It works today. Not sure what happened. Co-Developer and I reorganized frameworks and everything works fine now. Thank you for your help everyone. I appreciate the responses :)
Related
So my goal is to get rid of these bugs completely. I am in a dilemma where each decision leads to a bug.
The first thing I can do that eventually becomes an issue is use a String-interpolated collection path in all my query functions like so:
func getEventName() {
listener = db.collection("school_users/\(user?.uid)/events").order(by: "time_created", descending: true).addSnapshotListener(includeMetadataChanges: true) { (querySnapshot, error) in
if let error = error {
print("There was an error fetching the data: \(error)")
} else {
self.events = querySnapshot!.documents.map { document in
return EventName(eventName: (document.get("event_name") as! String))
}
self.tableView.reloadData()
}
}
}
The thing with this is, when I run the app on the simulator, I am restricted from pressing buttons and then sometimes I can press them and then sometimes they get restricted again. This bug is so confusing because it makes no sense where it springs from.
The other issue is I can use a Constants value in all the query functions in my collections path.
static let schoolCollectionName = "school_users/\(user?.uid)/events"
This is nested in a Firebase struct within the Constants struct. In order to keep Xcode from giving errors I create a let users = Auth.auth().currentUser variable outside the Constants struct. The issue with this value is that when I put that in all of my query functions collection paths, all the buttons are accessible and selectable all the time, but when a user logs out and I log in as a new user, the previous user's data shows up in the new user's tableview.
It would obviously make more sense to use the Constants value because you prevent typos in the future, but I can't figure out how to get rid of the bug where the old user's data shows up in the new user's tableview. Thanks in advance.
The user id should definitely not be a constant. What it sounds like is that right now, you have no reliable way to change users -- your setup probably depends on which user is logged in at app startup, since that's where your variable gets set.
I would do something more like this:
func getEventName() {
guard let user = Auth.auth().currentUser else {
//handle the fact that you don't have a user here -- don't go on to the next query
return
}
listener = db.collection("school_users/\(user.uid)/events").order(by: "time_created", descending: true).addSnapshotListener(includeMetadataChanges: true) { (querySnapshot, error) in
Note that now, user.uid in the interpolated path doesn't have the ? for optionally unwrapping it (which Xcode is giving you a warning for right now). It will also guarantee that the correct query is always made with the currently-logged-in user.
Regarding being able to press the buttons, that sounds like an unrelated issue. You could run your app in Instruments and check the Time Profiler to see if you have long-running tasks that are gumming up the main/UI thread.
The way I currently have my code arranged, the following line will run for various managed-object-contexts. Some of the fetched entities will have "complededDate" and others will not have a "completedDate" attribute.
let task = retrieved_MgObjCntxt[(indexPath as NSIndexPath).row]
if let itemFinDate = task.value(forKey: "completedDate") {
...
I thought by using if-let, that if this failed then it'd be okay... but I'm getting an "lldb" crash. I've been playing with trying to solve it using do/catch and throw but I'm not super familiar with how those work.
Is there a way to safely check so that if "completedDate" doesn't exist, it just skips the code within the if-closure??
let task = retrieved_MgObjCntxt[(indexPath as NSIndexPath).row]
if task.entity.propertiesByName.keys.contains("completeDate") {
...
}
You can find all the keys for you objects entity type by using:
managedObject.entity.attributesByName
And then see if that dictionary's keys contains "completedDate"
I'm new to this forum, and – more importantly – I'm also new to the Swift (2) language – and actually in coding at all.
So at the moment I'm trying to work with Parse in Xcode 7 (Swift 2). To be more specific: I'm working with a PFQueryTableView to display the data, I set up in the Parse class, in the app. But my problem is that when I update this data on the Parse website and I run the app in the simulator, the tableview with data isn't up-to-date with my new data from the Parse-website.
After going through other topic-related posts, this is the code I came up with:
let query = PFQuery(className: "myClass")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
print("Successfully retrieved: \(objects)")
} else {
print("Error: \(error)")
}
}
Now, when I run the app I can see the right data in the Target Output, but in the simulator it's still the old data. So I guess there must be a line of code in the "if error == nil { }"-section. I already tried several lines of codes which I got from other threads, but they all didn't work. And like I said before: I'm still a beginner in coding, so I just can't figure out myself how to do this.
Hopefully one of you guys can help me out. And if I need to be more specific or something, just ask!
Thanks in advance!
I'm using a Parse Cloud function to get a list of movies. This was all working very well till today. The app crashes and I can't seem to fix it.
Weird (and highly problematic) thing is that it did work yesterday and the days before. (This app is in production in the App store)
This is the function causing the error:
PFCloud.callFunctionInBackground(function, withParameters: parameters) { (movies, error) -> Void in
if error != nil { return block(success: false, movies: []) }
PFObject.pinAllInBackground(movies as! [PFObject])
let foundMovies = ParseMovie.arrayFromPFObjects(movies as! [PFObject])
return block(success: true, movies: foundMovies)
}
If I comment the 4 lines inside the block, it still crashes. If I comment the entire function, it doesn't. So it seems as soon as I call "PFCloud.callFunction" the app crashes.
Any idea what can go wrong? The Parse cloud function does work, because calling it with the parse rest API gives me the movies as expected.
Any help is appreciated, thanks!
Ok, got it. Apparently I'm using an old version of the Parse SDK (1.5) and since today, this version is not working anymore.. I'm not using pods so I was not aware of this out-dated version. A bit disappointed, but probably my fault?
I have created an iOS app using Swift and everything is working fine and dandy on the simulator. I get no errors or crashes at all, but when I submit my app to put up on the app store Apple rejects it and lets me know that it crashes when the user makes a selection. I cannot recreate this error/crash. I took the crash logs and symbolicated them. This line of code came up as the culprit for the crashes:
linksToPass = getLinks(season) as [String:[String]]
This line is trying to store the resulting Dictionary from the getLinks() function I created. It for sure is getting a dictionary and if there is no dictionary to send back I create a dictionary which has error information in it, so it is for sure returning a dictionary in that format no matter what. Seeing as I cannot recreate the crash, I am just trying to error check this line of code in any way possible so it does't crash when I resubmit to Apple.
I tried checking if the resulting dictionary was nil like so:
if(getLinks(seasons) != nil){
linksToPass = getLinks(season) as [String:[String]]
}
This is not valid though, and XCode lets me know that UInt8 is not compatible with NSDictionary or something of that nature.
I then fixed that line and changed it to this:
if(getLinks(seasons) != ["":[""]]){
linksToPass = getLinks(season) as [String:[String]]
}
I am just not sure if this is even a good way to check for errors. I was wondering if there were any suggestions on how I may go about making sure this line does not fail and result in a crash. Thank you very much.
EDIT:
Here is my getLinks() function if that helps add more info to the problem:
var season = ""
let hymn_links = Hymn_Links()
func getLinks (nameofseason:String) -> NSDictionary
{
switch (nameofseason)
{
default:
return ["Maps Not Found": []]
}
}
EDIT #2:
This is my updated getLinks() function with the use of optionals.
func getLinks (nameofseason:String) -> NSDictionary?
{
switch (nameofseason)
{
default:
return nil
}
}
Also in my statement of linksToPass I changed it to:
if let links = getLinks(season) as? [String:[String]]
{
linksToPass = links
hymnnames = [String] (linksToPass.keys)
}
There are some known issues with the Swift optimiser. Some people have resorted to shipping with debug builds.
My suggestion would be to test with an optimised build to see if you can reproduce it. You can then try shipping a debug build to the App store.
General Code Comments
Why are you returning an NSDictionary rather than a Swift dictionary anyway? Without knowing the contents and creation method for your hymn_links object I can't be sure how good it is.
I would avoid as casts until Swift 1.2 and stick to using as? and then handling the nil case. At least in your "Edit 2" a nil will cause a crash as nil cannot be cast to [String:[String]] although [String:[String]]? should be possible.
Can you guarantee that all of the items returned by the switch statement will never under any circumstances be nil? If not getLinks should return an Optional.
Note that is is virtually impossible for getLinks to know that one of the items will never be nil and in Swift un-handed nils are a crash waiting to happen. Unless all these methods correctly handle nil.
Return an Optional and handle that in the statement that calls getLinks.
Languages handle nils differently, Objective-C handles them rather well, Java and Swift by crashing. But Swift has a mechanism to handle nils without crashing: Optionals, use it.