Как нажать новый контроллер представления при нажатии на ячейку таблицы?

Я создал эту таблицу с 3 разделами и 7 строками. Код показан ниже

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet var subjectTabelView: UITableView!

var slSubject = ["English Lang&Lit", "Chinese Lang&Lit", "Economics"]
var hlSubject = ["Mathematics", "Chemistry", "Biology"]
var tokSubject = ["Theory of Knowledge"]

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

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

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 3
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0{
        return hlSubject.count
    }else if section == 1{
        return slSubject.count
    }else {
        return tokSubject.count
    }

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let subjectCell = tableView.dequeueReusableCellWithIdentifier("idSubjectCell", forIndexPath: indexPath) as! UITableViewCell

    if indexPath.section == 0 {
        subjectCell.textLabel?.text = hlSubject[indexPath.row]
    } else if indexPath.section == 1{
        subjectCell.textLabel?.text = slSubject[indexPath.row]
    } else {
        subjectCell.textLabel?.text = tokSubject[indexPath.row]
    }

    return subjectCell
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if section == 0 {
        return "HL"
    } else if section == 1{
        return "SL"
    } else {
        return "ToK"
    }
}



}

Что мне нужно сделать, чтобы каждая ячейка в этой таблице подталкивала новый контроллер представления при касании? Изображение моей раскадровки показано ниже. В моей раскадровке, моем контроллере представления, я уже создал контроллер навигации и сделал контроллер представления с таблицей rootViewController. И на данный момент мой tableView имеет только одну ячейку-прототип и один идентификатор ячейки.

Благодарю вас!


person Shawn Clarke    schedule 14.08.2015    source источник
comment
изображение вашей раскадровки не отображается.   -  person Hugo Alonso    schedule 14.08.2015
comment
@HugoAlonso Привет, извините, stackOverflow не позволяет мне публиковать фото, потому что моя репутация недостаточно высока.   -  person Shawn Clarke    schedule 15.08.2015


Ответы (3)


Предположим, что ваш «locationVC»:

class LocationVC: UIViewController {

    @IBOutlet weak var fromWhereLabel: UILabel!
    //This can be changed when creating this UIViewController
    var textToShow : String?

    override func viewWillAppear(animated: Bool) {
        if let textToShow = textToShow {
            fromWhereLabel.text = textToShow
        }
    }
}

затем, просто добавив функцию ниже в свой код в ViewController с именем UIViewController (у которого должно быть лучшее имя ;-)), вы можете достичь своей цели .

 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
      //if such cell exists and destination controller (the one to show) exists too..
        if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier("locationVC") as? LocationVC{
            //This is a bonus, I will be showing at destionation controller the same text of the cell from where it comes...
            if let text = subjectCell.textLabel?.text {
                destinationViewController.textToShow = text
            } else {
                destinationViewController.textToShow = "Tapped Cell's textLabel is empty"
            }
          //Then just push the controller into the view hierarchy
          navigationController?.pushViewController(destinationViewController, animated: true)
        }
     }

Вы сможете запускать LocationVC UIViewController каждый раз, когда нажимаете на ячейку, и это будет иметь некоторую ценность, чтобы доказать ее правильность. :)

Надеюсь, поможет!

ОБНОВЛЕНИЕ: приведенный ниже код и инструкции позволяют запускать разные UIViewController после нажатия на ячейки.

1.- Давайте создадим класс, который будет родителем для каждого из наших новых UIViewController (тех, которые мы хотим перейти от крана нашей ячейки таблицы):

public class CommonDataViewController: UIViewController {
//Here we are going to be putting any data we want to share with this view
  var data: AnyObject?
}

2.- Давайте создадим какие-то правила навигации, просто для порядка ;-)

enum Navigation: Int {
    case vc1 = 0, vc2 = 1, vc3 = 2, vc4 = 3
    //How many rules we have (for not to exceed this number)
    static let definedNavigations = 4
    //This must return the identifier for this view on the Storyboard
    func storyboardIdentifier() -> String {
        //for this example's sake, we have a common prefix for every new view controller, if it's not the case, you can use a switch(self) here
        return "locationVC_\(self.rawValue + 1)"
    }
}

Теперь давайте опираться на предыдущий код:

3.- Для ясности давайте немного изменим наш предыдущий LocationVC (который для этого примера будет иметь идентификатор раскадровки с текстом "locationVC_1")

class LocationVC: CommonDataViewController {

    @IBOutlet weak var fromWhereLabel: UILabel!

    //This is optional, but improves clarity..here we take our AnyObject? variable data and transforms it into the type of data this view is excepting 
    var thisVCReceivedData: String? {
        return data as? String
    }

    override func viewWillAppear(animated: Bool) {
        if let textToShow = thisVCReceivedData {
            fromWhereLabel.text = textToShow
        }
    }
}

4.- Теперь мы запускаем все это в нашей функции didSelectRowAtIndexPath.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //Just to avoid tapping on a cell that doesn't have an UIViewController asociated
    if Navigation.definedNavigations > indexPath.row {
        //The view's instance on our Navigation enum to which we most go after tapping this cell
        let nextView = Navigation(rawValue: indexPath.row)!
        //The identifier of the destination CommonDataViewController's son in our Storyboard
        let identifier = nextView.storyboardIdentifier()
        //If everything exists...
        if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier(identifier) as? CommonDataViewController {

            //here you can use a switch around "nextView" for passing different data to every View Controller..for this example, we just pass same String to everyone
            if let text = subjectCell.textLabel?.text {
                destinationViewController.data = text
            } else {
                destinationViewController.data = "Tapped Cell's textLabel is empty"
            }
            navigationController?.pushViewController(destinationViewController, animated: true)
        }
    }
}

Обратите внимание, что вы можете достичь тех же результатов, используя протоколы и подход делегирования, просто это проще объяснить

person Hugo Alonso    schedule 14.08.2015
comment
Привет! У меня есть вопрос, будет ли это показывать содержимое ячейки в viewController? Например, в твиттере, когда вы нажимаете на твит, он открывает твит в другом viewController, но показывает только твит и позволяет вам комментировать его. - person Bruno Recillas; 15.08.2015
comment
@HugoAlonso, так мне создать новый файл LocationVCViewController.swift? позволит ли это решение мне создать 7 разных контроллеров представления для моих 7 разных ячеек? Спасибо - person Shawn Clarke; 15.08.2015
comment
@BrunoRecillas да, вы можете сделать что-то подобное с этим подходом, вы просто передаете экземпляр своего твита, данных и т. Д. Вместо простого текста в .textToShow, и вы готовы к работе. - person Hugo Alonso; 17.08.2015
comment
@ShawnClarke Было бы здорово узнать об этом заранее, извините, что не заметил этого раньше ;-) (просто для того, чтобы вы знали, даже если вы не можете публиковать изображения, вы можете ссылаться на них) .. так что, чтобы ответьте на свой вопрос: недостаточно просто создать LocationVCViewController или LocationVC. Если уж на то пошло, поясните мне кое-что: вы заранее знаете, какая строка (indexPath.row) будет на месте для каждого нового ViewController, который вы хотите показать? другими словами, ваши ячейки всегда находятся в то же самое место? ..ex: тот, который ведет к newVC_3, всегда находится в строке 3, newVC_2 в строке 2 и т. д..? - person Hugo Alonso; 17.08.2015
comment
Не могли бы вы быть немного более конкретным? Пожалуйста? @ХьюгоАлонсо - person Bruno Recillas; 18.08.2015
comment
@BrunoRecillas предположим, что у вас есть представление A и представление B, A представляет B. B имеет переменную-заполнитель, в данном примере это .textToShow типа String, но может быть любого типа. Затем, прежде чем представить B и после создания его экземпляра. Вы можете передать любое значение в эту переменную. И, как когда вы представляете свой UIViewController B, вы можете реализовать свое обновление для таких данных в viewWillAppear из B. Таким образом показаны данные, соответствующие тому, что было выбрано на A. - person Hugo Alonso; 18.08.2015
comment
Итак, поскольку я использую textView, в новом ViewController в viewWillAppear я просто вызываю класс UITableView и выбираю textView.textToShow? - person Bruno Recillas; 18.08.2015
comment
@BrunoRecillas, пожалуйста, продолжайте и закодируйте его, вы заметите, что есть только один способ добиться этого, не полагаясь на делегаты, я обновлю свой комментарий только для дополнительной детали, которая может вас сбить с толку. - person Hugo Alonso; 18.08.2015
comment
Я не могу редактировать, кроме своего последнего комментария, поэтому я отредактирую здесь исключение из моего предыдущего комментария: ¨... Вы можете передать любое значение в эту переменную из внутренней функции tableView didSelectRowAtIndexPath A (как показано в этом ответе ).**Затем**, когда вы представляете свой UIViewController B, вы можете реализовать свое обновление для таких данных в представленииWillAppear of B (например, окрашивание другим цветом, обновление некоторого текста и т. д.). Таким образом показаны данные, соответствующие ячейке, которая была выбрана в A.¨ - person Hugo Alonso; 18.08.2015
comment
Итак, я работаю над этим, и сначала я не добавлял никаких данных, просто попытался посмотреть, будет ли после нажатия на ячейку отображаться viewController, и он это делает. Теперь я создал textView в новом ViewController, чтобы текст отображался там. У меня просто небольшая проблема с destinationViewController, это новый ViewController? или новый класс ViewController? под новым ViewController я имею в виду идентификатор раскадровки ViewController? - person Bruno Recillas; 18.08.2015
comment
Итак, я понял это. Я заставил его работать, исправил ошибки, которые я получил, но теперь он вылетает. Это потому, что я использую textView вместо метки? Или это потому, что я использую базу данных Parse.com и не передал данные? - person Bruno Recillas; 18.08.2015
comment
@HugoAlonso, привет, да, теперь мои клетки всегда будут в одном и том же месте. - person Shawn Clarke; 19.08.2015
comment
Хорошо, я скоро обновлю решение для вашего случая. - person Hugo Alonso; 19.08.2015

Что ж, чтобы нажать контроллер представления в UINavigationController, вы просто используете этот код:

ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"locationVC"];
[self.navigationController pushViewController:viewController animated:YES];

Метод, который вы ищете, это один:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"locationVC"];
    [self.navigationController pushViewController:viewController animated:YES];
}
person MSU_Bulldog    schedule 14.08.2015
comment
этот код находится в Objective-C, вопрос в том, как добиться этого быстро - person Hugo Alonso; 14.08.2015
comment
@Hugo В его вопросе говорится, что он уже создал навигационный контроллер. - person dmarsi; 14.08.2015
comment
@MSU_Bulldog Привет, спасибо за предложение, но что, если я хочу, чтобы разные ячейки отображали разные представления, а это значит, что будет больше множественных идентификаторов? Спасибо - person Shawn Clarke; 15.08.2015
comment
Что я хочу сделать с приложением, так это то, что мне нужен другой контроллер представления для всех предметов, и приложение позволит пользователям вводить свои оценки по каждому предмету, и приложение будет отображать введенные значения в виде графика. - person Shawn Clarke; 15.08.2015

Вы можете использовать метод prepareForSegue. Вам просто нужно настроить вид назначения. или код didselectrowatindexpath prepareForSegue выглядит следующим образом:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "nameofTheSegue"
{
    if let destinationVC = segue.destinationViewController as? OtherViewController{
        // do whatever you want with the data you want to pass.
    }
}
}
person Lamour    schedule 14.08.2015