1

I have set up a small test database in Parse which you can see below:

enter image description here There is a country 'name', country 'code' and country 'currency'

So the main context of the app is this:

  1. On the first screen, there is a textfield, which if they press, it takes them to a tableview controller and populates with the list of countries from Parse (the 6 you see above - this all works fine)
  2. When they select a country, it takes them back to the first VC and saves the country to a variable, of type String. Called 'countryChosen' (this works fine)
  3. When they press the Confirm button, it takes them to a ResultsVC. It has 3 labels on it, one for the name of the country they chose in the tableView, and then one for the 'code', and one for the 'currency' of that selected country. See the layout below:

enter image description here

On this screen, currently, i have updated the top label with the country name no problem. I used this code:

import UIKit
import Parse

class ResultsViewController: UIViewController {

@IBOutlet weak var countryChosenLabel: UILabel!

@IBOutlet weak var countryCodeLabel: UILabel!

@IBOutlet weak var countryCurrencyLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    countryChosenLabel.text = countryChosen

}

What I'm struggling with

I need to populate the other 2 labels with the correct data from Parse. So for example, if the user selected the country United Kingdom, then when they get to the ResultsVC, it could show: United Kingdom, GB, GBP.

I don't know how to make the query to Parse to ask for this information. I'm very new to using Parse so any help would really help!

Thanks very much.

UPDATED Code from my TableViewController.swift

import UIKit
import Parse

class TableViewController: UITableViewController {

var country = [String]()

var pickedCountry: String?

override func viewDidLoad() {
    super.viewDidLoad()

    var countryQuery = PFQuery(className: "country")
    countryQuery.orderByAscending("name")
    countryQuery.findObjectsInBackgroundWithBlock {
        (countryName:[AnyObject]?, error: NSError?) -> Void in

        if error == nil {

            for name in countryName! {

                self.country.append(name["name"] as! String)

            }

            self.tableView.reloadData()


        } else {

            print(error)

        }

    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}


override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return country.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

    cell.textLabel!.text = country[indexPath.row]

    return cell
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "pickedCountry" {

        let cell = sender as! UITableViewCell
        let index = tableView.indexPathForCell(cell)

        if let indexPath = index?.row {

            pickedCountry = country[indexPath]

        }
    }

}
}

First ViewController.swift

import UIKit
import Parse

var countryChosen: String!

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var textfield: UITextField!

@IBOutlet weak var button: UIButton!

@IBAction func TFPressed(sender: AnyObject) {

    performSegueWithIdentifier("toTable", sender: self)

}

@IBAction func buttonPressed(sender: AnyObject) {

    if textfield.text != nil {

        performSegueWithIdentifier("done", sender: self)

    }

    countryChosen = textfield.text!

    print(countryChosen)

}

@IBAction func selectedCountry (segue: UIStoryboardSegue) {

    let countryTableViewController = segue.sourceViewController as! TableViewController

    if let selectedCountry = countryTableViewController.pickedCountry {

        textfield.text = selectedCountry

    }

}
}
4
  • You don't need to query Parse again as you already have the data from Parse. Instead of returning a string variable just return the whole PFObject. Then you can access the columns whenever you need a value Commented Sep 29, 2015 at 21:36
  • @Paulw11 Hi Paul, So after the user has selected their country from the TableViewVC, and it's passed back to the first VC, i assign the textField text to the 'chosenCountry' variable. And that's how i'm currently populating the first label on the ResultsVC. I'm not sure on how to return the whole Object as you mentioned - this is what i'm struggling with. Could you show me in some code how to do it please? Commented Sep 30, 2015 at 21:48
  • Can you update your question to show the code where you pass back the string and I will show you how to pass back the object Commented Sep 30, 2015 at 21:59
  • @Paulw11 Code added, thanks very much! Commented Sep 30, 2015 at 22:03

1 Answer 1

2

The first step is to keep the PFObjects that you have retrieved rather than simply extracting the country name and throwing the object away, as you will need it later.

import UIKit
import Parse

class TableViewController: UITableViewController {

var country = [PFObject]()

var pickedCountry: PFObject?

override func viewDidLoad() {
    super.viewDidLoad()

    var countryQuery = PFQuery(className: "country")
    countryQuery.orderByAscending("name")
    countryQuery.findObjectsInBackgroundWithBlock {
        (countries:[AnyObject]?, error: NSError?) -> Void in

        if error == nil {
            self.country=countries as! [PFObject]
            self.tableView.reloadData()
        } else {
            print(error)
        }
    }
}

This means that you will need to change your methods that access the data - cellForRowAtIndexPath

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    let rowCountry = country[indexPath.row]
    cell.textLabel!.text = rowCountry["name"]

    return cell
}

Now in your original view controller when you access pickedCountry it will be a PFObject and you can access the various fields -

import UIKit
import Parse

class ResultsViewController: UIViewController {

@IBOutlet weak var countryChosenLabel: UILabel!

@IBOutlet weak var countryCodeLabel: UILabel!

@IBOutlet weak var countryCurrencyLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    countryChosenLabel.text = countryChosen["name"]
    countryCodeLabel.text = countryChosen["code"]
    countryCurrencyLabel.text = countryChosen["currency"]

}

You will need to make similar changes in the first view controller - Change the string variable to a PFObject and access the country name field

import UIKit
import Parse

var countryChosen: PFObject!

@IBAction func buttonPressed(sender: AnyObject) {

    if textfield.text != nil {
        performSegueWithIdentifier("done", sender: self)   
    }

    // countryChosen = textfield.text!  // You can't do this any more because you need a PFObject, not text.  I am not sure you would want to anyway, because they may have typed an invalid country.  Probably use a label instead of a text field
     print(countryChosen)
}

@IBAction func selectedCountry (segue: UIStoryboardSegue) {

    let countryTableViewController = segue.sourceViewController as! TableViewController

    if let selectedCountry = countryTableViewController.pickedCountry {
        textfield.text = selectedCountry["name"]
    }
}
Sign up to request clarification or add additional context in comments.

9 Comments

@Paulw11 Thanks Paul, i added the first VC code in the question.
@Paulw11 Hi Paul, i'm getting an error on a line of text in the cellForRowAtIndexPath method. It's against the line: cell.textLabel!.text = rowCountry["name"] and the error is: Cannot assign a value of type 'AnyObject?' to a value of type 'String'. Any ideas?
You need to downcast add as! string to the end
@Paulw11 Thanks Paul, i've added that in, and it removes the error. However, when i run the app, when i press in the textfield, and it loads the tableview, the app crashes and shows EXC_BAD_INSTRUCTION against that line, cell.textLabel!.text = rowCountry["name"] and in the logs it says: fatal error: unexpectedly found nil while unwrapping an Optional value.
Ok, I gave you the basic solution, but you need to make it more,robust. If there is a chance that something could be nil,then you need to conditionally unwrap it rather than force unwrapping it as I did.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.