0

So I want to create a IOS application that generates a group of students, adds them to a course and then shows students. I can show students in a list in a table view but now I want to let the user touch a student's name and be taken to a page with information about that student (name highest grade etc). The student class is flawless, the course works and the only problem I have is that I can't get a student from one view to the other.

Here's what I have so far:

//
//  DataTableViewController.swift
//  assignment8
//

import Foundation
import UIKit


class DataTableViewController: UITableViewController {

  var delegate:StudentSelectionDelegate! = nil
  var students = [Student]();
  var course = Course();

  // MARK: - UITableViewDataSource

  override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

  }

  func didSelectStudent(controller:UITableViewController, student:Student!) {

    controller.navigationController?.popViewControllerAnimated(true)

  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    self.course = courseStorage.getCourse();
    self.students = course.getArrayOfStudentSortedByLastName();
    return course.count;
  }


  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let row = indexPath.row
    let currentStudent = students[row];
    if (delegate != nil) {
      delegate.didSelectStudent(self,student:currentStudent)
    }
    else {
      print ("delegate is nil :(");
    }
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
  }

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

    cell.textLabel?.text = students[indexPath.row].lastName + ", " +
      students[indexPath.row].firstName;
    return cell
  }

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    print("ping");
    if segue.identifier == "studentSegue" {
      let nextScene =  segue.destinationViewController as! studentViewController
      // Pass the selected object to the new view controller.
      if let indexPath = self.tableView.indexPathForSelectedRow {
        let selectedStudent = students[indexPath.row]
        print (selectedStudent.firstName);
        nextScene.student = selectedStudent;
      }
    }
  }
}

and

//
//  DataViewController.swift
//  assignment8
//

import UIKit



class DataViewController: UIViewController {

  @IBOutlet weak var dataLabel: UILabel!
  var dataObject: String = ""
  let tableData = ["One","Two","Three"];



  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.dataLabel!.text = dataObject
  }

  func tableView(tableView: UITableView!, numberOfRowsInSection section: Int)
    -> Int {
    return self.tableData.count;
  }
}

and

//
//  studentViewController.swift
//  assignment8
//

import UIKit

protocol StudentSelectionDelegate {
  func didSelectStudent(controller: UITableViewController, student:Student)
}

class studentViewController: UIViewController {

  var delegate = StudentSelectionDelegate.self;

  var name = String();
  var student = Student();


  @IBOutlet weak var StudentName: UILabel!
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }

  func didSelectStudent(controller:UITableViewController, student:Student!) {
    student.description;
    print ("pong")
    StudentName.text = student.firstName + " " + student.lastName;

    controller.navigationController?.popViewControllerAnimated(true);
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }
  //  override func viewWillAppear(animated: Bool) {
  //    StudentName.text = name
  //  }

}

my storyboard This is my storyboard so far.

So, any time I try clicking a student it will print the message that I've decided to use if the delegate is nil. So far I've tried looking at all the other answers on SO but none of them have fixed my issue.

Digits
  • 2,634
  • 2
  • 14
  • 23
  • How are you creating the segues from one view controller to another?Are you liking your segue from the table view? I don't think it's a good idea to call the tableview.didselectrowatindexpath inside itself maybe what you want to do is a performseguewithidentifier? – Joel García Verástica Dec 08 '15 at 06:34
  • It's how it was done in several tutorials I followed, here for example. http://makeapppie.com/2015/02/17/swift-swift-tutorials-introducing-table-views/ – Digits Dec 08 '15 at 06:40

1 Answers1

1

To be able to send information from one view controller to another you should use segues. It seems like that's what you're doing according to the image. If you don't know how to use a segue, you can find a good answer here: Sending data with Segue with Swift

With segues you'll be able to set the delegate of the next view controller:

protocol MyDelegate {
     func myFunction()
}

class FirstViewController: UIViewController, MyDelegate {

    func myFunction() {
        // do what the function does
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if let secondVC = segue.destinationViewController as? SecondViewController {
            secondVC.delegate = self
        }
    }
}


class SecondViewController: UIViewController {
    var delegate: MyDelegate!
}

Before you segue to the second view controller (you're preparing for the segue), you set the delegate variable of SecondViewController to self, because FirstViewController conforms to MyDelegate protocol so it can be used there. Now, in SecondViewController you can use delegate.myFunction() and it will do whatever is written inside the FirstVC's function, because the FirstVC is SecondVC's delegate.

Community
  • 1
  • 1
Aleksi Sjöberg
  • 1,454
  • 1
  • 12
  • 34
  • Thank you for telling me that delegates are only for sending data back from another view and that segues are what's required to send the data in the first place! I thought adding a segue in my storyboard would make my delegate trigger the segue but that's not the case! Now I don't need a delegate at all. – Digits Dec 08 '15 at 16:48