0

After spending days searching for a solution, reading developer documentation and threads such as Passing Data between View Controllers attempting to pass data through a number of views I am at a loss.

My application is a PC Bundle builder and currently utilises three tableViewControllers. The first loads PCs, the second Monitors and the third Accessories. When a cell is tapped the next view TableView loads. The application currently loads data into all three, which is great! However, I would like to create a summary page to display the selected PC, Monitor and Accessory information (image, name and description).

Using PCs (the first view controller) as an example:

Data is initialised in a PCs.swift

class Pc {

//SI. MARK: pc properties
//SI. variables because they will change for each cell.
var image: UIImage?
var name: String
var graphics: String
var cpu: String
var hdd: Int
var ssd: Int?
var ram: Int
var sku: Int
var price: String

//SI. set the initial value of each variable
init?(image: UIImage?, name: String, graphics: String, cpu: String, hdd: Int, ssd: Int?, ram: Int, sku: Int, price: String) {
    self.image = image
    self.name = name
    self.graphics = graphics
    self.cpu = cpu
    self.hdd = 1
    self.ssd = nil
    self.ram = ram
    self.sku = 12345
    self.price = price

    //SI. for validation an if statement has been 
        if name.isEmpty || graphics.isEmpty || cpu.isEmpty || hdd < 0 || ram < 0 || sku < 0 || price.isEmpty {
        return nil
        }
    }
}

Test objects are created in PcTableViewController and placed in an array. loadTestPcs is placed in viewDidLoad():

    //SI. Initialises pcs with an empty array of objects from the Monitors() to store PC details.
var pcs = [Pc]()

//SI. Creates data in a function "loadTestPcs".
func loadTestPcs()
{
    let pic1 = UIImage(named: "PC1")
    let pc1 = Pc(image: pic1, name: "PC1", graphics: "Radeon R7", cpu: "A6", hdd: 1, ssd:  0, ram:  8, sku: 111110, price: "499.99")

    let pic2 = UIImage(named: "PC2")
    let pc2 = Pc(image: pic2, name: "PC2", graphics: "Radeon R7", cpu: "A6", hdd: 1, ssd:  0, ram:  8, sku: 111112, price: "549.99")

    let pic3 = UIImage(named: "PC3")
    let pc3 = Pc(image: pic3, name: "PC3", graphics: "Radeon R7", cpu: "A6", hdd: 1, ssd:  0, ram:  8, sku: 111113, price: "599.99")

    //SI. adds details stored in pc1,2 and 3 to pcs array.
    //
    pcs += [pc1!, pc2!, pc3!]

}

Then I have used the following to retrieve desired data from tapped cell:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    //SI. created a constant for pcTableViewCell which was set earlier as the reuse identifier for the prototype cell in the table view controller.
    //SI. type of cell needs to be downcast to custom cell subclass (pcTableViewCell).
    let cellIdentifier = "pcTableViewCell"
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! pcTableViewCell

    var currentPC = []
    let pc = pcs[indexPath.row]

    cell.picImageView.image = pc.image
    cell.nameLabel.text = pc.name
    cell.priceLabel.text = pc.price

    currentPC = [cell.picImageView.image!, cell.nameLabel.text!, cell.priceLabel.text!]

    print(currentPC)
}

My problem now is how to pass currentPC to the next TableViewController (where currentMonitors will be used to store the selected Monitor. This will be passed on (collecting the selected Accessory) and finally, the data will be passed to a Summary View where labels used as outlets will display the selected options.

Community
  • 1
  • 1
worc
  • 7
  • 4

1 Answers1

0

The question to ask yourself is how to get a handle on the next tableViewController from within the first tableViewController. The answer is that it depends on how you're instantiating the second tvc -- are you using storyboards, or are you initializing in code and pushing it manually?

Storyboard case:

var pcToDisplay: Array<AnyObject>?

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    (...)
    self.pcForNextTableView = currentPC
    performSegueWithIdentifier("nextTableView", sender: nil)
}

override public func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "nextTableView", let nextTableView = segue.destinationViewController as? PCTableViewController {
    nextTableView.pcToDisplay = self.pcForNextTableView
}

Manual case:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    (...)
    let nextTableView = PCTableViewController()
    nextTableView.pcToDisplay = currentPC
    self.navigationController?.pushViewController(nextTableView, animated: true)
}
Community
  • 1
  • 1
jefflovejapan
  • 2,047
  • 3
  • 20
  • 34
  • Also, you should be using some kind of type to represent your PC rather than an array of AnyObject. Take a look at Swift's structs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html – jefflovejapan Mar 26 '16 at 13:07
  • Thank you for your help with this but pcForNextTableView outputs nil when it is passed to the next viewController (no doubt I'm doing something wrong here still)... I've declared var pcForNextTableView: Array? in pcTableViewController and var pcToDisplay: Array? in monitorTableViewController. print(pcForNextTableView), placed at the end of the prepareForSegue override shows the correct values but still cannot get pick up the values in the next view controller?? – worc Mar 28 '16 at 17:39
  • Thank you for the link too... I will read through this and try to structure the application better after getting a prototype functional. Thanks again for the help :) – worc Mar 28 '16 at 17:40