Передача данных между TableView и другим ViewController в Swift

Я пытаюсь представить список событий в tableView, и когда пользователь нажимает одно из событий, он открывает другой viewController с дополнительной информацией об этом конкретном выборе.

Это tableView, у которого есть параметры, которые можно выбрать:

import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase

class NewsfeedViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var ref:DatabaseReference!,
        posts = [eventStruct]()
    @IBOutlet weak var tableview: UITableView!
    var propertStruct : (Any)? = nil


    override func viewDidLoad() {
        super.viewDidLoad()
        loadNews()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func loadNews() {
        ref = Database.database().reference()
        ref.child("events").queryOrderedByKey().observe(.childAdded, with: { (snapshot) in

            if let valueDictionary = snapshot.value as? [AnyHashable:String]
            {
                let title = valueDictionary["Title"]
                let location = valueDictionary["Location"]
                let date = valueDictionary["Date"]
                let description = valueDictionary["Description"]
                self.posts.insert(eventStruct(title: title, date: date, location: location, description: description), at: 0)
                self.tableview.reloadData()
            }
        })

    }

    /////////////////////////     Table View Content     \\\\\\\\\\\\\\\\\\\\\\\\\\
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return posts.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let label1 = cell.viewWithTag(1) as! UILabel
        label1.text = posts[indexPath.row].title
        let label2 = cell.viewWithTag(2) as! UILabel
        label2.text = posts[indexPath.row].location
        let label3 = cell.viewWithTag(3) as! UILabel
        label3.text = posts[indexPath.row].date
        return cell
    }

    func prepareForSegue(segue: UIStoryboardSegue, sender: eventStruct) {
        let secondViewController = segue.destination as? EventViewController
        secondViewController?.data = sender
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performSegue(withIdentifier: "showDetails", sender: posts[indexPath.row])
    }
    /////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
}

struct eventStruct {
    let title: String!
    let date: String!
    let location: String!
    let description: String!


}

Вот DetailsViewController, который должен отображать название другого параметра, выбранного в предыдущем tableView:

import UIKit

class EventViewController: UIViewController {

    var data: eventStruct?
    @IBOutlet weak var titleLabel: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()
        print (data?.title as Any)
        self.titleLabel.text = self.data?.title

        // Do any additional setup after loading the view.
    }

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


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}

Проблема в том, что вместо отображения заголовка, который должен храниться внутри переменной структуры, все время возвращается значение nil.

Может ли кто-нибудь сказать мне, что я делаю неправильно? Я пытался следовать всем предложениям, которые были сделаны, но ничего не работает.


person Victor Mihaita    schedule 15.06.2017    source источник
comment
см. это: teamtreehouse.com/community/   -  person KKRocks    schedule 15.06.2017
comment
Я также инициализировал параметры в своей структуре. Все еще не могу получить данные   -  person Victor Mihaita    schedule 15.06.2017
comment
можете ли вы убедиться, что let secondViewController = segue.destination as? EventViewController выполняется успешно, ваш переход showDetails верен и действительно указывает на назначенный EventViewController на раскадровке?   -  person Justin Oroz    schedule 15.06.2017
comment
Совсем не выполняет функцию prepareForSegue. Выполняет только эту команду: func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { performSegue(withIdentifier: "showDetails", sender: indexPath) }   -  person Victor Mihaita    schedule 15.06.2017
comment
ваша prepareForSegue функция должна быть override func prepare(for segue: UIStoryboardSegue, sender: Any?), чтобы соответствовать протоколу. Затем вы можете ввести отправителя в eventStruct внутри функции   -  person Justin Oroz    schedule 15.06.2017


Ответы (4)


Ваш prepareForSegue должен переопределить метод UIViewController, который

func prepare(for segue: UIStoryboardSegue, sender: Any?)

Поэтому ваш метод в NewsfeedViewController должен быть

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let secondViewController = segue.destination as? EventViewController
    secondViewController?.data = sender as? eventStruct
}

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

person Justin Oroz    schedule 15.06.2017
comment
теперь, если я распечатаю данные, полученные вторым контроллером представления, я получу это сообщение: nil Optional(RUC_App_1_0.eventStruct(title: Study group, date: 2017-06-12, location: House1, description: sudho ifoisjfoij owuh owunoiun oiwn ovin oiwn ioeunwofini)) 2017-06-15 21:03:44.385 RUC-App 1.0[48189:5741258] Warning: Attempt to present <RUC_App_1_0.EventViewController: 0x7f874c129dd0> on <RUC_App_1_0.NewsfeedViewController: 0x7f874a529420> whose view is not in the window hierarchy! - person Victor Mihaita; 15.06.2017
comment
Предупреждение об иерархии окон может зависеть от того, используете ли вы NavigationControllers или различную другую информацию. Это может иметь значение или this, или вы можете задать отдельный вопрос, так как передача данных была темой этого вопроса. - person Justin Oroz; 15.06.2017

Измените свойство в EventViewCotntroller с AnyData на eventStruct, например:

var data: eventStruct?

а затем в контроллере таблицы:

func prepareForSegue(segue: UIStoryboardSegue, sender: eventStruct?) {

    let secondViewController = segue.destination as? EventViewController
    secondViewController?.data = sender

}

имейте в виду, что eventStruct должен быть вне области вашего класса TableViewControlle:

class TableViewController {
// controller logic 
}

struct eventStruct {
// struct body
}
person Robert    schedule 15.06.2017
comment
Я не могу объявить свойство eventStruct?, потому что оно не определено. - person Victor Mihaita; 15.06.2017
comment
переместить eventStruct из области действия контроллера табличного представления - person Robert; 15.06.2017
comment
Я приложил весь код, который я использую в двух классах. Я пробовал ваше решение, но все еще не работает. Видите ли вы какие-либо проблемы в коде? Спасибо. - person Victor Mihaita; 15.06.2017
comment
Вторая часть не правильная. Метод «prepareForSegue» должен переопределить вызываемый метод UIViewController. Тип «отправитель» должен оставаться «Любой?» - person Justin Oroz; 16.06.2017
comment
Я пропустил это. - person Robert; 16.06.2017

Попробуйте подписаться

В EventViewController

var propertStruct : (Any)? = nil

При передаче данных

secondViewController.propertStruct =   eventStruct(title : "", date : "", location: "", description: "")

Вывод

введите здесь описание изображения

Консоль во время назначения

введите здесь описание изображения

В SecondViewController

введите здесь описание изображения

ИЛИ

вам нужно передать indexpath в prepareforSegue

 performSegue(withIdentifier: "showDetails", sender: indexPath)

func prepareForSegue(segue: UIStoryboardSegue, sender: Any) {
            let indexPath = sender as! IndexPath
            let eventStruct =  post[indexPath.row]
            let secondViewController = segue.destination as? EventViewController
            secondViewController?.data = sender as AnyObject

        }
person KKRocks    schedule 15.06.2017
comment
свойство propertyStruct становится равным нулю? - person KKRocks; 15.06.2017
comment
Да. Я печатаю его непосредственно перед отправкой с помощью PerformSegue и печатаю «ноль». - person Victor Mihaita; 15.06.2017
comment
Я приложил весь свой код для двух классов. Я действительно не вижу проблемы. И я не получаю никакой ошибки. - person Victor Mihaita; 15.06.2017
comment
почему вы объявили конструктор init(title: String!, date:String!, location:String!, description:String!){ self.title = title? - person KKRocks; 15.06.2017
comment
это был только один пример, который я нашел в Интернете.. и без этого он не работает. - person Victor Mihaita; 15.06.2017
comment
не тебе не надо. вы можете обойтись без этого конструктора... прокомментируйте это или удалите это. - person KKRocks; 15.06.2017
comment
посмотрите мои скриншоты, которые я упомянул - person KKRocks; 15.06.2017

Контроллер первого представления

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            if indexPath.row == 0
            {
                let objstory = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
            objstory.strd = imageView.image
            _ = self.navigationController?.pushViewController(objstory, animated: true)

            }
        }

SecondViewController

 var strd:UIImage!
@IBOutlet weak var imgprof: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imgprof.image = strd


        // Do any additional setup after loading the view.
    }
person Amul4608    schedule 16.06.2017