Как можно реализовать протокол DataSource ?

ios

#1

Как можно реализовать UITableViewDataSource в виде протокола, на который можно подписать другой класс? Дело в том, что у меня на одном View Controller находится 3 UITableView, которые получают данные от разных классов.

import UIKit
class MainViewController: UIViewController, UITableViewDataSource,                                    
AddCableDelegate, AddLoadDelegate, AddReleDelegate {
@IBOutlet var VoltageTextField : UITextField!
@IBOutlet var CurrentTextField : UITextField!
@IBOutlet var KoTextField : UITextField!

@IBOutlet var CableTable: UITableView!
@IBOutlet var LoadTable: UITableView!
@IBOutlet var ReleTable: UITableView!

let IndentifierOfCabel = "CableCellIdentifier"
let IndetifierOfLoad = "LoadCellIdentifier"
let IndentifierOfRele = "ReleCellIdentifier"

var cables = [Cable] ()
var loads = [Load] ()
var reles = [Rele] ()

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

func sendDataCable(_ sendCable: AddCableViewController, didAddCable cable: Cable) {
    cables.append(cable)
    CableTable.reloadData()
}

func sendLoad(_ addLoadViewController: AddLoadViewController, didAddLoad load: Load) {
    loads.append(load)
    LoadTable.reloadData()
}

func sendRele(_ addReleViewController: AddReleViewController, didAddRele rele: Rele) {
    reles.append(rele)
    ReleTable.reloadData()
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let CellOfCabel = tableView.dequeueReusableCell(withIdentifier: IndentifierOfCabel, for: indexPath)
    let cable = cables[indexPath.row]
    CellOfCabel.textLabel?.text = cable.NameOfCable
    CellOfCabel.detailTextLabel?.text = cable.LengthOfCable
    return CellOfCabel
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let navigationControllerOfCable = segue.destination as! UINavigationController
    let addCableViewController = navigationControllerOfCable.topViewController as! AddCableViewController
    addCableViewController.delegateCable = self
}
}

#2

UITableView по умолчанию уже подписан на протокол UITableViewDataSource.

Для чего в данном случае используются эти таблицы - для показа данных или для их ввода?


#3

Они нужны для показа данных, но получают данные от разных классов


#4

Так в чем собственно проблема? На одном VC можно легко использовать несколько TableView, которые будут использовать один DataSource. Вся логика сводится к проверке tableView внутри DatASrouce.


#5

А по какому условию их проверять ?


#6
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableView == CableTable {
        
    }
}


#7

Уже нагуглил, спасибо!


#8
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     if tableView == CableTable { 

     }
}

С таким еще не сталкивался, поэтому хотелось бы уточнить - здесь должны быть три условия или одно каскадное с else if? И cell возвращается внутри каждого if?


#9

У меня там if --> else if --> else и cell возвращается в каждом


#10

и оно работает? Я почему спрашиваю, если есть три условия if, то по идее должно выполняться только первое, если оно соответствует, а остальные два уже не должны проверяться. А тут получается, что выполняются все три блока кода. Непонятно, почему оно так происходит.


#11

Почему не понятно ? В первом if я проверяю одну таблицу, если не она, то else if следующая таблица, если тоже не она, то else и уже третья таблица


#12

Ок, а теперь другой случай - если в первом if у вас именно та таблица, которая нужна, то условие соблюдается и код внутри данного условия выполняется. После чего проверка двух остальных условий уже производиться не должна. Но она, тем не менее, все равно производится.


#13

Вы похоже не осознаете как работают таблицы.


#14

я могу предположить, что внутри метода tableView(cellForRowAt) условие if работает как-то специфически, но что именно здесь происходит?


#15

Нормально if работает в этом методе) просто в каждом ифе надо создавать и возвращать ячейку своего типа (для конкретной таблицы свою).

if table1 {
let cell = …

return cell}
Else {
let cell = …
return cell}


#16

тут дело не в if’ax. каждая таблица будет вызывать этот метод столько раз, сколько в каждой таблице будет указано кол-во ячеек. и при каждом вызове туда будет передаваться ссылка на соответствующую таблицу.


#17

т.е. таблица будет вызывать этот метод, сколько указано в предыдущем методе
tableView(_ tableView: UITableView, numberOfRowsInSection section: Int), так? Это я на всякий случай уточняю.

Вот здесь не очень понятно, куда будет передаваться ссылка на соответствующую таблицу? Ведь данные и так передаются в таблицу.

Но это все опять же не отменяет странного поведения if. Пусть вызов метода повторяется по количеству ячеек таблицы. И при каждом вызове проверяется первое условие if. Если оно выдает true, то выполняется код внутри этого первого условия. Если этот код выполнен, то остальные условия не должны проверяться. А здесь получается, что независимо от того, что происходит с первым условием, выполняются два следующих. Почему?


#18

Есть 3 таблицы

  • table1 - 1 ячейка
  • table2 - 2 ячейки
  • table3 - 3 ячейки

каждая таблица вызывает метод делегата DataSource tableView(tableView:cellForRowAt) и первым параметром она передает указатель на саму себя.
а в реализации этого метода в нашем VC мы уже будем проверять какая таблица на данный момент вызова у нас есть

if tableView == table1 {

} else if tableView == table2 {

} ...

В итоге у вас будет 6 вызовов этого метода. В одном случае там будет table1, в 2х случаях table2 и т.д.

и еще стоит не забывать, то же самое нужно сделать и в методе numberOfRowsInSection, что бы аналогичным способом задать каждой таблице кол-во ячеек.

Самое простое что бы это понять на практике, сделайте экран с несколькими таблицами и заполните их.


#19

вот с этой фразы я и прозрел)) В принципе уже и сам начал думать в этом направлении, но не хватало триггера. Действительно, инциатор действия - это таблица. Каждая из них вызывает метод tableView(tableView:cellForRowAt). По идее это то же самое, что записать три метода для трех таблиц, но мы пишем один с идентификаторами таблиц (также как одна и та же функция может быть приписана нескольким разным кнопкам). И потом для каждой таблицы метод еще вызывается по количеству ячеек, ну и конечно второй метод с указанием количества ячеек.

И следующий момент, что каскадное if, которое и сбивало с толку, здесь не обязательно. Если записать просто три отдельных if, то тоже будет работать. А каскадное if больше подходит, если нужно в одну и ту же таблицу передавать данные из разных источников по разным тригерам, например, через pickerView, у которого есть несколько компонентов.

Спасибо!