How to Access a variable inside the function and then use it? - swift

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!)")}
}
}

Related

From server Class into an array Swift

I want to display my data I parse from server into my view collection, so I used PFQuery as the following
func LoadData(){
let query = PFQuery(className: "AntStore")
query.findObjectsInBackground {(returned, error) -> Void in
if error != nil {
print(error!)
} else {
if let data = returned {
for object in data {
self.TitlesArray.append(object.object(forKey: "Title") as! String)
print(self.TitlesArray)
}
}
}
}
}
I can't put it in a single array to send it to the view collection variable!! Any help ?
You are printing inside the loop, move the print statement outside the loop as follows:
func LoadData(){
let query = PFQuery(className: "AntStore")
query.findObjectsInBackground {(returned, error) -> Void in
if error != nil {
print(error!)
} else {
if let data = returned {
for object in data {
self.TitlesArray.append(object.object(forKey: "Title") as! String)
}
print(self.TitlesArray) //Moved print outside the loop
}
}
}
}

Get data from User table without current user

I'm trying to get all the user's from the _User table and get their images and put them into an array. The below code works when I am logged in (current user != nil)
but when I'm not logged in (current user = nil) I get no images at all
How can i achive this query without being a current user ???
I have the following function
let chefUserQuery = PFQuery(className: "_User")
chefUserQuery .whereKey("chef", equalTo: true)
chefUserQuery .findObjectsInBackgroundWithBlock{
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFUser] {
var ai = 0
for object in objects {
print("kati")
let imageChef = object["avatar"] as! PFFile
imageChef.getDataInBackgroundWithBlock({ (data, error) -> Void in
if error == nil {
if let imageData = data {
let imagatzaki = UIImage(data: imageData)
let idChef = object.objectId
self.imagesOfChef[ai] = chefImages(objidChef: idChef, imageChef: imagatzaki)
ai += 1
print(self.imagesOfChef)
} } })
}
completion(.Success())
}
}
else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
Thanks

Having trouble with nil optional using parse

I'm trying to download a file from Parse but I'm getting a fatal error: crash, it seems as if the message variable is nil. I've tried to troubleshoot, and I know there is an easy miss I'm just not seeing. Hoping the community can help as I am new to swift.
class InboxViewController: UITableViewController {
var messages: [PFObject] = []
var selectedMessage: PFObject?
var moviePlayer: MPMoviePlayerController?
override func viewDidLoad() {
super.viewDidLoad()
self.moviePlayer = MPMoviePlayerController()
let currentUser = PFUser.currentUser()
if currentUser != nil {
// Do stuff with the user
print("Current user: \(currentUser!.username)")
} else {
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let query = PFQuery(className: "Messages")
query.whereKey("recipientIds", equalTo: PFUser.currentUser()!.objectId!)
query.findObjectsInBackgroundWithBlock {
(objects : [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
let messages = object["file"] as! PFFile
self.tableView.reloadData()
print("Retreived \(self.messages.count) messages")
}
}
}
}
The crash breakpoint is at the beginning of the query.
Thank you community, another set of experienced eyes always helps.
you can safely unwrap the objects using if let construct
if let objects = objects {
for object in objects
let messages = object["file"] as? PFFile
print(messages)
// or you can also safely unwarp here
// if let messages = object["file"] as? PFFile {
// print(message)
// }
self.tableView.reloadData()
print("Retreived \(self.messages.count) messages")
}
}

fatal error: unexpectedly found nil while unwrapping an Optional value. Swift

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.

How to convert AnyObject to PFObject/PFUser in swift?

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)
}
}