Нажимаем кнопку перехода от UITableViewCell к ViewController в Swift

У меня проблемы с UITableViewCells. Я подключил свой UITableView к API для заполнения моих ячеек.

Затем я создал функцию, которая захватывает indexPath.row, чтобы определить, какой JSON-объект внутри массива должен быть отправлен в RestaurantViewController.

Ссылка на мой проект Xcode для упрощения отладки и решения проблем

Вот как мой маленький фрагмент ищет установку "щелчков строк" ​​для глобальной переменной.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
     i = indexPath.row
}

И вот моя функция prepareForSegue(), которая должна подключить мой push-segue к RestaurantViewController.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
    let navigationController = segue.destinationViewController as UINavigationController
    let vc = navigationController.topViewController as RestaurantViewController
    vc.data = currentResponse[i] as NSArray
 }
}

И вот как я настроил свой сеанс из UITableViewCell

Здесь мой результат, я попытался щелкнуть каждую из этих ячеек, но я не буду перенаправлен на другой viewController... Я также не получаю сообщение об ошибке. Что здесь не так?

Пробовал решения, которые не будут работать

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if segue.identifier == "toRestaurant"{
            let vc = segue.destinationViewController as RestaurantViewController
            //let vc = navigationController.topViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSArray
        }
    }

Ответ 1

Проблема в том, что вы неправильно обрабатываете свои данные. Если вы посмотрите в свой массив currentResponse, вы увидите, что он содержит NSDictionaries, но в вашем prepareForSegue вы пытаетесь наложить NSDictionary на NSArray, что приведет к сбою приложения.

Измените переменную data в RestaurantViewController на NSDictionary и измените свой prepareForSegue, чтобы передать NSDictionary

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if let cell = sender as? UITableViewCell {
        let i = redditListTableView.indexPathForCell(cell)!.row
        if segue.identifier == "toRestaurant" {
            let vc = segue.destinationViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSDictionary
        }
    }
}

Ответ 2

Следующие шаги должны устранить вашу проблему. Если нет, сообщите мне.

  • Удалите реализацию tableView(tableView, didSelectRowAtIndexPath:).

  • Сделать data на RestaurantViewController иметь тип NSDictionary!

  • Определите выбранную строку в prepareForSegue:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if let cell = sender as? UITableViewCell {
            let i = tableView.indexPathForCell(cell)!.row
            if segue.identifier == "toRestaurant" {
                let vc = segue.destinationViewController as RestaurantViewController
                vc.data = currentResponse[i] as NSDictionary
            }
        }
    }
    

Ответ 3

ссылка Dropbox в каталог stack3

  • Мне сложно понять, почему ваше программное обеспечение сильно отличается от стандартной структуры таблиц 2 уровня. Поэтому я закодировал короткий пример, к которому вы можете получить доступ по этой ссылке. Я также включил код источника ниже.

  • Программа имитирует то, что у вас есть (насколько я понял). Контроллер таблицы 1 отбирается в Table Controller 2 из ячейки tableview. У меня не было проблем с segue-ing. Обратите внимание, что мне не нужно и не нужно увеличивать Историю, чтобы инициировать сеанс.

  • Я включил оба контроллера в навигационных контроллерах. Мой опыт в том, что он экономит много усилий для настройки навигации.

  • В качестве альтернативы я мог бы перетащить управление из первого символа TableViewController поверх экрана во второй контроллер и настроить сеанс.

  • Я использовал глобальную переменную (selectedRow), хотя это не рекомендуется. Но вы так же легко можете использовать prepareForSegue для установки переменной в RestaurantTableViewController (я показываю пример)

    1. Наконец, я рекомендую проверить Инспектор подключений (для ячейки представления таблицы в первом контроллере), чтобы подтвердить, что во второй контроллер есть сегмент. Если вы управляете перетаскиванием должным образом, должно быть приглашение подтверждения, а также запись в Инспекторе соединений.

К сожалению, я просто не могу получить корректный формат текста

import UIKit

var selectedRow = -1

class TableViewController: UITableViewController {

var firstArray = ["Item1","Item2","Item3","Item4"]

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

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

return 1
}

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

return firstArray.count

}


let nameOfCell = "RestaurantCell"

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

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

return cell

}

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

selectedRow = indexPath.row

}

// MARK: - Navigation

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

let vc = segue.destinationViewController as RestaurantTableViewController

// can write to variables in RestaurantTableViewController if required

vc.someVariable = selectedRow

}


}


import UIKit

class RestaurantTableViewController: UITableViewController {

var secondArray = ["Item 2.1", "Item 2.2", "Item 2.3", "Item 2.4"]

var someVariable = -1

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

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

return 1

}

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

return secondArray.count

}

let nameOfCell = "RestaurantCell"

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

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

if indexPath.row == selectedRow {

cell.textLabel!.text = cell.textLabel!.text! + " SELECTED"

}

return cell

}

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

selectedRow = indexPath.row

}

}

Ответ 4

Я заметил, что на скриншоте вашей раскадровки segue соединяет первую ячейку прототипа с RestaurantViewController. Эта прототипная ячейка выглядит как "основной" стиль ячейки с аксессуаром индикатора раскрытия справа. Но посмотрите на скриншот вашего приложения. Таблица заполняется ячейками, которые, как представляется, являются стилем "Subtitle", без аксессуара индикатора раскрытия справа.

Причина, по которой ваш segue никогда не срабатывает, независимо от того, что вы делаете, заключается в том, что segue настроен только для работы в определенной ячейке прототипа, но эта ячейка прототипа никогда не используется, когда вы заполняете таблицу. Что бы вы ни делали в tableView:cellForRowAtIndexPath:, вы не используете ячейку прототипа, которую хотите.

@Starscream имеет правильную идею, деактивирующую правую ячейку с правильным идентификатором и сопоставляя ее с идентификатором ячейки прототипа в Interface Builder. Сбой, который вы получаете даже после этого, может быть из-за предыдущей проблемы, упомянутой в комментариях выше. Ваш segue в раскадровке явно указывает на UITableViewController. Ваш код в prepareForSegue:sender: должен быть let vc = segue.destinationViewController as RestaurantViewController, если RestaurantViewController является подклассом UITableViewController. Вы потерпите крах, если попытаетесь применить его как UINavigationController. Также убедитесь, что класс для назначения UITableViewController в раскадровке указан как RestaurantController на панели "Проверка идентификатора". Вы потерпите крах, если ваша программа компилирует, думая, что раскадровка просто содержит общий UITableViewController.

Возвращаясь к исходной проблеме больше, я не знаю, как вы реализовали tableView:cellForRowAtIndexPath:, что может иметь решающее значение. Может быть, это не так просто. Возможно, вы планируете обрабатывать многие прототипные ячейки или создавать пользовательские ячейки во время выполнения. В этом случае один из способов сделать это простым для вас - программно выполнить сеанс, когда пользователь нажимает на ячейку. Вместо использования определенной ячейки прототипа сделайте segue соединение, происходящее из "Restauranger nära mig" UITableViewController, идущее к RestaurantViewController. (Подключитесь в Interface Builder, перетаскивая элемент управления с помощью значка контроллера таблиц в верхней части первой, в тело второго). Вы должны дать этому segue идентификатор в панели Attributes Inspector, чтобы сделать это полезным. Скажем, это "toRestaurant". Затем в конце вашего метода tableView:didSelectRowAtIndexPath: поместите эту строку кода: self.performSegueWithIdentifier("toRestaurant", sender: self). Теперь, независимо от того, какая ячейка выбрана в таблице, этот отступ всегда будет срабатывать для вас.

Ответ 5

Попробуйте создать такие ячейки в своем методе cellForRow:

let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath)

Ответ 6

Мне нравится прихоть здесь, так как я сейчас быстро ввязываюсь, но способ, которым я это делаю в своем prepareForSegue(), выглядит примерно так:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
        let navigationController = segue.destinationViewController as UINavigationController
        let vc = navigationController.topViewController as RestaurantViewController
        //notice I changed [i] to [index!.row]
        vc.data = currentResponse[index!.row] as NSArray
     }
    }

Мне кажется, что вы вызываете переменную i, которая похожа на частную переменную внутри метода вашего класса. Вы можете сделать что-то вроде @Syed Tariq с переменной selectRow и установить ее над вашим class SomeController: UIViewController /*, maybe some more here? */ {, а затем подписать переменную внутри

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

    selectedRow = indexPath.row

}

как описано выше, но оба пути должны работать достаточно хорошо.

Ответ 7

У меня была та же проблема, и я нашел решение таким:

performSegueWithIdentifier ( "toViewDetails", отправитель: self)

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    var cellnumber = procMgr.processos[indexPath.row].numero
    println("You selected cell #\(indexPath.row)")
    println(cellnumber)
    performSegueWithIdentifier("toViewDetails", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "toViewDetails" {
         let DestViewController : ViewDetails = segue.destinationViewController as! ViewDetails
    }
}

Ответ 8

Вам может потребоваться получить выбранный индекс ячейки UItableview. Ниже код использовал выделенный индекс ячейки (UItableview.indexPathForSelectedRow), чтобы получить правильный элемент массива.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "seguaVisitCardDetial" {
        let viewController = segue.destinationViewController as! VCVisitCardDetial
        viewController.dataThisCard =   self.listOfVisitCards[(tblCardList.indexPathForSelectedRow?.row)!]
    }
}