I am setting up a PFRelation for the user variable and I'd like to add the text in a textfield as a PFRelation. First I query to see if the input username exists, then I make the returned object a PFUser. Then i attempt to add the PFUser to PFRelation and that's where it crashes, because AnyObject cannot be downcasted to PFUser/PFObject. How would I go about doing that?
var userQuery = PFUser.query()
userQuery.whereKey("username", equalTo: newUsername.text)
userQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
for object in objects{
if objects.count > 0 {
var PFRelation = PFUser.currentUser().relationForKey("friends")
var addRelation = object["username"] as PFUser
PFRelation.addObject(addRelation)
PFUser.currentUser().saveInBackgroundWithBlock{
(succeeded: Bool!, error: NSError!) in
if error == nil {
println("newuser added")
}
else {
println(error.userInfo)
}
Thanks!!
From my understanding it couldn't be done because PFObject/PFUser is like an array. Thus I couldn't cast just an object into an array. I also used getFirstObjectInBackgroundWithBlock() instead because it returns a PFObject instead of AnyObject, not sure if that made a difference. Below is my working code.
var userQuery = PFUser.query()
userQuery.whereKey("username", equalTo: newUsername.text)
userQuery.getFirstObjectInBackgroundWithBlock{ (object, error) -> Void in
if error == nil {
println(object)
var PFRelation = PFUser.currentUser().relationForKey("friends")
var addRelation = object
if addRelation != nil {
PFRelation.addObject(addRelation)
println("new relation added")
}
PFUser.currentUser().saveInBackgroundWithBlock{
(succeeded: Bool!, error: NSError!) in
if error == nil {
println("newuser saved")
}
else {
println(error.userInfo)
}
}
}
else {
println(error)
}
}
Related
I have been trying to change the content in an array called testArray in the class Collabs and then save it back to the parse server.
#IBAction func addToArray(_ sender: AnyObject) {
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
I've seen quite a few posts that talk about access rights however, to the best of my knowledge, the class Collabs has public read and write enabled
sorry I didnt check it that deeply before, try this
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else {
if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
}
When I try to compile this code:
func lookupPlayers() {
print("Looking up \(match?.players.count)")
// Loading ID from players connected in the match
var idsArray = NSMutableArray()
if (match != nil) {
for players in match!.players {
if let player = players as? GKPlayer {
idsArray.addObject(player.playerID!)
}
}
}
GKPlayer.loadPlayersForIdentifiers(idsArray as [AnyObject] as [AnyObject], withCompletionHandler: { (players, error) -> Void in
if (error != nil) {
// Handle error here
// if we fail to retrieve player info return and end the match
print("Error retrieving player info: \(error.localizedDescription)")
self.matchStarted = false
self.delegate?.matchEnded?()
}
else {
// Get info from all players and start the match
self.playersDict = NSMutableDictionary(capacity: players.count)
for player1 in players {
if let player = player1 as? GKPlayer {
print("Found player: \(player.alias)")
self.playersDict.setObject(player, forKey: player.playerID)
}
}
self.playersDict.setObject(self.localPlayer, forKey: self.localPlayer.playerID)
self.matchStarted = true
self.delegate?.matchStarted?()
}
})
}
I'm getting this error:
Cannot convert value of type '[AnyObject]' to expected argument type '[String]' in this line:
GKPlayer.loadPlayersForIdentifiers(idsArray as [AnyObject] as [AnyObject], withCompletionHandler: { (players, error) -> Void in
What am I doing wrong?
Very similar to this issue:
Problems with code when updating to Swift 2.0. “Cannot convert value..”
As you know, you need to pass [String] fo the first parameter of loadPlayersForIdentifiers(_:withCompletionHandler:). And also playerId! definitely is a String. Why do you you NSMutableArray knowing that?
Change the declaration of idsArray as:
var idsArray: [String] = []
And the line causing error to:
GKPlayer.loadPlayersForIdentifiers(idsArray, withCompletionHandler: { (players, error) -> Void in
Try the following:
Replace var idsArray = NSMutableArray() with var idsArray = [String](). This way you use Swift arrays, not Obj-C NSArrays.
Then replace:
GKPlayer.loadPlayersForIdentifiers(idsArray as [AnyObject] as [AnyObject], withCompletionHandler: { (players, error) -> Void in
if (error != nil) {
With:
GKPlayer.loadPlayersForIdentifiers(idsArray as [String], withCompletionHandler: { (players, error) -> Void in
if (error != nil) {
Try to declare idArray as Array<String>() instead of NSMutableArray().
Like this:
// Loading ID from players connected in the match
var idsArray = Array<String>()
if (match != nil) {
for players in match!.players {
if let player = players as? GKPlayer {
idsArray.append(player.playerID!)
}
}
}
GKPlayer.loadPlayersForIdentifiers(idsArray, withCompletionHandler: { (players, error) -> Void in
if (error != nil) {
// Handle error here
...
}
})
Within my user object I added a column to add a users favorite team. The column is identified as favTeam and is a pointer to a teams class
Here is my code. I have populated my user with a favorite team however the logic is always showing that "favteam nil"
if let object = PFUser.currentUser()!["favTeam"] as? [PFObject]{
print("favteam not nil")
print(object)
let favTeam = PFUser.currentUser()!["favTeam"]
favTeamText.text = favTeam["Name"] as? String
if let favTeamImageView = favTeam["teamLogo"] as? PFFile {
favTeamImageView.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
self.teamLogo.image = UIImage(data: imageData)
}
}
}
}
}
else {
print("favteam nil")
}
I can accomplish this by using a PFUser.query() as follows...
func fetchFavoriteTeam() {
let userQuery: PFQuery = PFUser.query()!
userQuery.whereKey("username", equalTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var favTeam = users!
if error == nil {
if favTeam != nil {
favTeamContainer = favTeam.valueForKey("favTeam") as! PFObject
}
} else {
print(error)
}
})
}
I am new in Swift. My question is I am not sure how to unwrapping the optional value. When I print the object.objectForKey("profile_picture"), I can see Optional(<PFFile: 0x7fb3fd8344d0>).
let userQuery = PFUser.query()
//first_name is unique in Parse. So, I expect there is only 1 object I can find.
userQuery?.whereKey("first_name", equalTo: currentUser)
userQuery?.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error != nil {
}
for object in objects! {
if object.objectForKey("profile_picture") != nil {
print(object.objectForKey("profile_picture"))
self.userProfilePicture.image = UIImage(data: object.objectForKey("profile_pricture")! as! NSData)
}
}
})
You'd use if let to perform "optional binding", only performing the block if the result in question is not nil (and binding the variable profilePicture to the unwrapped value in the process).
It would be something like:
userQuery?.findObjectsInBackgroundWithBlock { objects, error in
guard error == nil && objects != nil else {
print(error)
return
}
for object in objects! {
if let profilePicture = object.objectForKey("profile_picture") as? PFFile {
print(profilePicture)
do {
let data = try profilePicture.getData()
self.userProfilePicture.image = UIImage(data: data)
} catch let imageDataError {
print(imageDataError)
}
}
}
}
Or, if you want to get data asynchronously, perhaps:
userQuery?.findObjectsInBackgroundWithBlock { objects, error in
guard error == nil && objects != nil else {
print(error)
return
}
for object in objects! {
if let profilePicture = object.objectForKey("profile_picture") as? PFFile {
profilePicture.getDataInBackgroundWithBlock { data, error in
guard data != nil && error == nil else {
print(error)
return
}
self.userProfilePicture.image = UIImage(data: data!)
}
}
}
}
It would be something along those lines, using if let to unwrap that optional. And you then have to get the NSData associated with that the PFFile object (from the getData method or getDataInBackgroundWithBlock, presumably).
See Optional Binding discussion in The Swift Programming Language.
I am trying to access a variable i that is inside the function checkUser(). The next thing is the if statement, if i == 0 that should println("Displaying Picture of Someone else")
The code at the bottom does not work, because the function checkUser does not return i value and I get an error:use of unresolved identifier 'i', however after poking around and adjusting the code to:
func checkUser() -> (Int?) {
var i = 0
return (i)
}
var (i) = checkUser()
if i == 0{
println("Value is set")
}
and implementing it, I get an error int is not convertible to void. What are my options to make it work?
func checkUser(){
var reqest = PFUser.query()
reqest.whereKey("username", equalTo: self.user.username)
reqest.whereKey("check", equalTo: true)
reqest.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!)-> Void in
if error == nil {
println("Successfully retrieved \(objects.count) item.")
var i = objects.count // variable that holds objects.count
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
if object["check"] as Bool == true{
println("Displaying Picture of You")
}
}
}
} else {
// Log details of the failure
println("Error: \(error) \(error.userInfo!)")
}
}
if i == 0{
println("Displaying Picture of Someone else")
}
}
If u want to display someone else's picture based on the result count of request, you can call a function instead of creating and checking for condition:
func checkUser(){
var reqest = PFUser.query()
reqest.whereKey("username", equalTo: self.user.username)
reqest.whereKey("check", equalTo: true)
reqest.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!)-> Void in
if error == nil {
println("Successfully retrieved \(objects.count) item.")
if (objects.count == 0) {
displayPicture()
}
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
if object["check"] as Bool == true{
println("Displaying Picture of You")
}
}
}
} else {
// Log details of the failure
println("Error: \(error) \(error.userInfo!)")
}
}
displayPicture() {
println("Displaying Picture of someone else")
}
}
From your code :
func checkUser(){
var reqest = PFUser.query()
reqest.whereKey("username", equalTo: self.user.username)
reqest.whereKey("check", equalTo: true)
reqest.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!)-> Void in
if error == nil {
println("Successfully retrieved \(objects.count) item.")
var i = objects.count // variable that holds objects.count
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
if object["check"] as Bool == true{
println("Displaying Picture of You")
}
}
}
} else {
// Log details of the failure
println("Error: \(error) \(error.userInfo!)")
}
}
if i == 0{
println("Displaying Picture of Someone else")
}
}
I would say that you defined variable inside the block but tried to use it outside. That won't work.
Try to set var i : Int = 0 below var request = PFUser.query()
Also, #Frank Schmitt has the point. remove the bracelets.
In the second bit of code you simply need to move that code inside the completion block where i is defined.
It is a matter of understanding the nature async code execution.
Inside your completion block you can call methods to let the UI or other parts of the code know that you're done. You are correct that you cannot return values like you would normally for in-line code.
It helps to think of async code as you asking for something to be done "when you get around to it". You need to decide how that code should let you know that it got around to it.
The definition of the variable i (var i = objects.count) is defined in a different scope from the place where you check its value. Specifically it is defined in the anonymous closure you pass to reqest.findObjectsInBackgroundWithBlock
You could fix the compile time error by defining i above the call to reqest.findObjectsInBackgroundWithBlock. However that would just give you a runtime error.
What's happening here is that the code inside {} directly after reqest.findObjectsInBackgroundWithBlock is run after the call completes which means that it'll be run after your test if i == 0{...
More that code up inside the previous block.
Thanks you guys for all the replies. Does indeed make sense; I created a function and moved it inside the completion block and It worked.
func checkUser(){
func displayPicture() {
println("Displaying Picture of someone else")
}
var reqest = PFUser.query()
//reqest.whereKey("college", equalTo: self.user.valueForKey("college"))
reqest.whereKey("username", equalTo: self.user.username)
reqest.whereKey("check", equalTo: true)
reqest.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!)-> Void in
if error == nil {
println("Successfully retrieved \(objects.count) item.")
if(objects.count == 0){
displayPicture()
}
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
if object["check"] as Bool == true{
println("Displaying Picture of You")
self.textFieldName.hidden = true
self.checkCommand.hidden = true
let userName = PFUser.currentUser().valueForKey("name")as String
//self.firstName.text = userName // Displays current username
self.personName = userName
let userPicture = PFUser.currentUser().valueForKey("profilePic") as PFFile
userPicture.getDataInBackgroundWithBlock{
(imageData:NSData!,error:NSError!) -> Void in
if error == nil{
let image:UIImage! = UIImage(data: imageData)
self.profilePic.image = image //displays current user picture
}
else {
// Log details of the failure
println("Picture not downloaded: \(error) \(error.userInfo!)")
}
}
}
}}} else {
// Log details of the failure
println("Error: \(error) \(error.userInfo!)")}
}
}