简体   繁体   English

如何在1个TableView Swift 4中显示两种类型的单元格

[英]How to display 2 types of cell in 1 TableView Swift 4

I want to display 2 types of cell.Both types of cell is display data from 2 different API call.So the structure is basically like this: 我想显示两种类型的单元格,两种类型的单元格都是显示来自2个不同API调用的数据,因此结构基本上是这样的:

在此处输入图片说明

Type A is only appears 1 times which is from API method A ,which is the first cell of the TableView ,the rest of all are Type B which is from API method B . 类型A仅出现1次,是API方法A中的一种 ,它是TableView的第一个单元格,其余全部是类型B ,它是API方法B中的

In order to make this works,I done the following: 为了使它起作用,我做了以下工作:

1) In StoryBoard,I set the structure of TableView like so : 1)在StoryBoard中,我像这样设置TableView的结构:

MyTableView
-Type A Cell
--My others view..
-Type B Cell
--My others view..

2) Both Cell have their TableViewCell class. 2)两个Cell都有其TableViewCell类。

3) Both Cell have their own model class to initialize the JSON come from API 3)两个Cell都有自己的模型类来初始化来自API的JSON

And then finally in my ViewController have all this code: 最后在我的ViewController中拥有所有以下代码:

All the basic code here

//The NSObject class for both type of cell
var typeAArray = [TypeA]()
var typeBAarray = [TypeB]()


override func viewDidLoad() {
   super.viewDidLoad()

   self.tableView.delegate = self
   self.tableView.dataSource = self

   self.getTypeAData()
   self.getTypeBData()
}

func getTypeAData(){
    //code to call API,parse JSON and also append to `typeAArray`
    //and reload TableView
}

func getTypeBData(){
    //code to call API,parse JSON and also append to `typeBArray`
    //and reload TableView
}

The code for TableView

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

    return typeAArray.count + typeBArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == 0 {
        let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell   
        typeACell.data = self.typeAArray[indexPath.row] //Here I get index or of range error
        return typeACell
    }

    let  typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
    typeBCell.data = self.typeBArray[indexPath.row]
    return typeBCell
}

What I get so far: 到目前为止,我得到的是:

Now with the setting and the code above,I get index out of range error in the part of if indexPath == 0 ,and no any data display in the TableView . 现在有了上面的设置和代码, if indexPath == 0 ,我得到index out of range错误,并且TableView没有任何数据显示。

So my question is: 所以我的问题是:

How to make 2 types of tableViewCell appear in 1 single TableView which the data from 2 different API method call? 如何使2种类型的tableViewCell出现在1个单个TableView中,其中2个不同的API方法调用的数据?

Take numberOfSections method and do following: 使用numberOfSections方法并执行以下操作:

func numberOfSections(in tableView: UITableView) -> Int {
    return 2
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return typeAArray.count
    } else {
        return typeBArray.count
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.section == 0 {
        let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
        typeACell.data = self.typeAArray[indexPath.row] //Here I get index or of range error
        return typeACell
    }

    let  typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
    typeBCell.data = self.typeBArray[indexPath.row]
    return typeBCell
}

Okay here's what's going on. 好的,这是怎么回事。 Your numberOfRowsInSection returns total number of elements from both arrays A and B. Assuming that typeBArray has loaded faster than typeAArray , you'll get the total number of items equal to size of typeBArray . 您的numberOfRowsInSection返回数组A和B中元素的总数。假设typeBArray加载速度快于typeAArray ,则得到的项目总数等于typeBArray大小。 In cellForRowAt you assume that item at the row 0 belongs to the first data model, hence you're trying to access typeAArray[0] while it's still empty and contains no data. cellForRowAt您假定第0行的项目属于第一个数据模型,因此,您尝试在typeAArray[0]仍然为空且不包含任何数据的情况下对其进行访问。 This leads to crash. 这导致崩溃。 You need to take the offset into consideration: 您需要考虑偏移量:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row < self.typeAArray.count {
        let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
        typeACell.data = self.typeAArray[indexPath.row]
        return typeACell
    }

    let  typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
    typeBCell.data = self.typeBArray[indexPath.row - self.typeAArray.count]
    return typeBCell
}

But honestly, just use sections instead. 但老实说,只是使用部分。

Obvious it should give you an error as your indexPath.row starts with 1 in your data source for TypeBTableCell and your array elements index starts with 0 for typeBArray . 显然,它应该给您一个错误,因为在TypeBTableCell的数据源中TypeBTableCell以1开头,而TypeBTableCell的数组元素索引以0 typeBArray So it won't match with each other. 因此,它们将彼此不匹配。

You need to reduce value for indexPath.row 1 step. 您需要减少indexPath.row 1步骤的值。 Also ensure both arrays have elements in it. 还要确保两个数组都包含元素。

Try this and see: 试试看,看看:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let numberOfRows = typeAArray.count + typeBArray.count
    print("typeAArray.count = \(typeAArray.count)\n")
    print("typeBArray.count = \(typeBArray.count)\n")
    print("numberOfRows = \(numberOfRows)\n")
    return numberOfRows
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


    var indexPathRowForB = max(0, indexPath.row - 1) 

    if indexPath.row == 0 && self.typeAArray.count > 0 {
        let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell   
        typeACell.data = self.typeAArray[indexPath.row]
        return typeACell
    } else {
      print("self.typeAArray.count is zero")
      indexPathRowForB = indexPath.row
    }

    if self.typeBArray.count > 0 { 
      let  typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell

      typeBCell.data = self.typeBArray[indexPathRowForB]
      return typeBCell

    } else {
       print("self.typeBArray.count is zero")
       // return UITableviewCell instance from here......
    }
}

Firstly have an array that stores all the data returned from API method A and B , instead of having 2 separate arrays which can make things a bit more complex but make sure your type A is the first item in in the array. 首先有一个数组,数组存储从API方法A和B返回的所有数据 ,而不是拥有2个单独的数组,这可能会使事情复杂一些,但要确保类型A是数组中的第一项。

Then something like this: 然后是这样的:

var tableViewDataArray = [Array]()

var typeAArray = [Array]()
var typeBArray = [Array]()

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.delegate = self
    self.tableView.dataSource = self

    self.getTableViewData()
}

func getTableViewData() {

    let queue = DispatchQueue(label: "com.company.app.queue")
    let group = DispatchGroup()

    group.enter()
    queue.async(group: group) {
        getTypeAData()
        group.leave()
    }

    queue.async(group: group) {
        getTypeBData()
        group.leave()
    }

    group.notify(queue: queue) {
        group.wait()

        tableViewDataArray.append(typeAArray)
        tableViewDataArray.append(typeBArray)

        self.tableView.reloadData()
    }
}

func getTypeAData() {

    let urlRequest: NSURLRequest = ...

    let task = self.session?.dataTaskWithRequest(urlRequest, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in

        // parse your response and append to array
        self.typeAArray.append(response)
    })
}

func getTypeBData() {

    let urlRequest: NSURLRequest = ...

    let task = self.session?.dataTaskWithRequest(urlRequest, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in

        // parse your response and append to array
        self.typeBArray.append(response)
    })
}

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

    return tableViewDataArray.count
}

public final func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let customObject = tableViewDataArray[indexPath.section]

    if indexPath.row == 0 &&
         customObject is TypeAObject {

        if let typeACell = tableView.dequeueReusableCell(withIdentifier: TypeACell.identifier, for: indexPath) as? TypeACell {

            // do any databinding here
            typeACell.customObject = customObject
            return typeACell
        }

    } else if customObject is TypeBObject {

        if let typeBcell = tableView.dequeueReusableCell(withIdentifier: TypeBCell.identifier, for: indexPath) as? TypeBCell {

            // do any databinding here
            typeBcell.customObject = customObject
            return typeBcell
        }
    }

    return UITableViewCell()
}

Note: This was done is Playground but should hopefully give you a better idea of what to do. 注意:这是在Playground完成的,但希望可以为您提供一个更好的方法。 You should also become familiar with GCD and executing async taks sequentially or concurrently (refer to these tutorials from RayWenderlich: part 1 and part 2 ) 您还应该熟悉GCD并依次或同时执行异步任务(请参阅RayWenderlich的这些教程: 第1 部分第2部分

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Swift 4 - 以随机顺序排列的多个tableview单元格类型 - Swift 4 - Multiple tableview cell types in a random order 如何从 URL 加载图像并将其显示在 tableView 单元格中 (Swift 3) - How to load an image from URL and display it in tableView cell (Swift 3) 如何在Swift的tableview自定义单元格上显示JSON图像? - How to display JSON image on custom cell of tableview in Swift? 如何快速显示来自数组数组的tableview单元格中的数据 - How to display the data in the tableview cell from the array of array in swift iOS Swift Tableview:-如何根据内容显示单元格? - IOS Swift Tableview:- How Display cell based on content? 如何快速冻结tableView单元格? - How to freeze a tableView cell in swift? 如何在Swift iOS的自定义TableView单元格中向多个标签显示多个字符串值? - How can I display multiple string values to multiple labels in a custom TableView Cell in swift ios? 如何在带有数组的快速字典中使用定义(Dictionary <String, [String]> )显示在tableview单元格上? - How to use a definitions in a swift dictionary with an array (Dictionary<String, [String]>) to display on tableview cell? 如何在Swift iOS的单个tableview单元格中显示多个字典或数组数据 - how to display mulitple dictionary or array data in single tableview cell in swift ios 如何快速查看tableview单元格是行还是节? - How to check tableview cell is row or section in swift?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM