如何在1个TableView Swift 4

时间:2018-02-06 08:34:12

标签: ios swift xcode uitableview swift4

我想显示2种类型的cell.Both类型的单元格是来自2个不同API调用的显示数据。所以结构基本上是这样的:

enter image description here

类型A 仅出现1次,来自 API方法A ,这是TableView的第一个单元格,其余的都是< strong> B类,来自 API方法B

为了实现这一点,我做了以下工作:

1)在StoryBoard中,我设置了TableView的结构,如下所示:

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

2)两个Cell都有TableViewCell类。

3)两个Cell都有自己的模型类来初始化来自API的JSON

最后在我的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
}

到目前为止我得到了什么:

现在使用上面的设置和代码,index out of range部分出现if indexPath == 0错误,TableView中没有任何数据显示。

所以我的问题是:

如何使2种类型的tableViewCell出现在1个单独的TableView中哪个数据来自2个不同的API方法调用?

4 个答案:

答案 0 :(得分:2)

采用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
}

答案 1 :(得分:1)

好的,这是怎么回事。您的numberOfRowsInSection会返回数组A和B中元素的总数。假设typeBArray的加载速度超过typeAArray,您的项目总数将等于typeBArray。在cellForRowAt中,您假设第0行的项目属于第一个数据模型,因此您在typeAArray[0]仍然为空并且不包含任何数据时会尝试访问该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 } 。这会导致崩溃。您需要考虑偏移量:

RewriteEngine On
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
RewriteRule ^(.*)$ public/$1 [L]

但老实说,只需改用部分。

答案 2 :(得分:0)

显然它会给你一个错误,因为你的indexPath.row在TypeBTableCell的数据源中以1开头,而你的数组元素索引从typeBArray的0开始。所以它不会相互匹配。

您需要降低indexPath.row 1步的值。还要确保两个数组都包含元素。

试试这个,看看:

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......
    }
}

答案 3 :(得分:0)

首先有一个数组,存储从API方法A和B 返回的所有数据,而不是有2个单独的数组,这可能会使事情变得更复杂,但要确保你的类型A是第一个数组中的项目。

然后是这样的:

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()
}

注意:这是在Playground完成的,但希望能让你更好地了解该怎么做。您还应熟悉GCD并按顺序或同时执行异步操作(请参阅RayWenderlich的这些教程:part 1part 2