2

I am trying to attach data to a UITableView. I have download the project form here and am using the code where data is attached to the tableView: http://yannickloriot.com/2016/01/make-uitableview-reactive-with-rxswift/:

Firstly I have created the following variable:

let currentQuestion: Variable<Taxi?>   = Variable(nil)

I then try to do the following:

 currentQuestion
        .asObservable()
        .bindTo(tableView.rx_itemsWithCellIdentifier("ChoiceCell", cellType: ChoiceCell.self)) { (row, element, cell) in
            cell.choiceModel = element
        }
        .addDisposableTo(disposeBag)

But I am getting the following warning: 'Extra argument in call' on the line .bindTo. I have tried adding a new cell and get the same result. Not sure if it is relevant, but I have registered the cell.

I have read here that you can get this warning if the types of the arguments don't match: Swift - Extra Argument in call . However it looks like the arguments match fine.

I am new to Rx and was hope someone could help me understand what might be going wrong here. Thanks.

======

Edit

Here is my new code. I have tried rx_itemsWithCellIdentifier("ChoiceCell") alone and rx_itemsWithCellIdentifier("ChoiceCell", cellType: ChoiceCell.self):

let currentQuestion = Variable<[Taxi]>(taxis)

    currentQuestion.asObservable()
        .bindTo(tableView.rx_itemsWithCellIdentifier("ChoiceCell")) {(row, element, cell) in
        cell.choiceModel = element
        }.addDisposableTo(disposeBag)

Where I have used (taxis), it is an array of taxi items. See picture below:

enter image description here

Also once I have called .asObservable(), I have the following:

enter image description here

I managed to print these out by removing the line .bindTo. If I add that line back I get the same error as before.

IMPORTANT: I played around with code base from article I linked to earlier. If I remove from ChoiceCell I can replicate the same error:

//  var choiceModel: ChoiceModel? {
//    didSet {
//          layoutCell()
//    }
//  }
Community
  • 1
  • 1
pls
  • 1,522
  • 2
  • 21
  • 41

3 Answers3

4

From experience the extra argument in call message is most often given when you are trying to bind a variable with the wrong expected data type. The first issue is that you are trying to bind a single instance of Taxi to the tableview which is expecting a sequence of observables.

/**
Binds sequences of elements to table view rows.

- parameter cellIdentifier: Identifier used to dequeue cells.
- parameter source: Observable sequence of items.
- parameter configureCell: Transform between sequence elements and view cells.
- parameter cellType: Type of table view cell.
- returns: Disposable object that can be used to unbind.
*/
public func rx_itemsWithCellIdentifier<S : SequenceType, Cell : UITableViewCell, O : ObservableType where O.E == S>(cellIdentifier: String, cellType: Cell.Type = default) -> (source: O) -> (configureCell: (Int, S.Generator.Element, Cell) -> Void) -> Disposable

It doesn't seem like the issue is caused by the optional object but I don't see why you would want to bind optional objects to the tableview, so I would advice you to avoid that too. Here is an example which would work.

let currentQuestion = Variable<[Taxi]>([Taxi()])
currentQuestion.asObservable().bindTo(tableView.rx_itemsWithCellIdentifier("ChoiceCell")) {(row, element, cell) in
  cell.choiceModel = element
}.addDisposableTo(disposeBag)
Philip Laine
  • 458
  • 3
  • 17
  • Thanks for the response and advice. I realised in the other code it is an array which makes more sense :-). I have updated my code to your suggestion, but I am still having the same issue. I have edited my question to give more details. – pls Apr 10 '16 at 23:22
2

Thanks to Philip Laine answer above: https://stackoverflow.com/a/36536320/2126233

That helped me see that I was making a mistake in regards to what I was observing. It helped me to see the problem I was having in my code.

If you just want to bind to a normal tableViewCell then you need to use tableView.rx_itemsWithCellFactory:

currentQuestion.asObservable()
        .bindTo(tableView.rx_itemsWithCellFactory) {(tableView, row, item) in
            let cell = UITableViewCell()
            cell.textLabel?.text = item.distance

            return cell

        }.addDisposableTo(disposeBag)

If you are using a custom cell then you can use tableView.rx_itemsWithCellIdentifier("ChoiceCell", cellType: ChoiceCell.self). Here is an example:

 currentQuestion
     .asObservable()
     .filter { $0 != nil }
     .map { $0!.choices }
  .bindTo(tableView.rx_itemsWithCellIdentifier("ChoiceCell", cellType: ChoiceCell.self)) { (row, element, cell) in
   cell.choiceModel = element
 }
 .addDisposableTo(disposeBag)

For me I was still getting this same error unless I had a property inside the tableView cell that matched the element that was coming out of the array I was binding the tableView to.

So if you have an array of [Taxis] like so then inside the tableViewCell I required a variable that stored a Taxis. Then I was able to compile my project.

So in ChoiceCell I have a var like so:

var taxi: Taxi? {
    didSet {
        layoutCell()
    }

}

I hope this helps anyone else having issues binding a tableViewCell to an array.

Community
  • 1
  • 1
pls
  • 1,522
  • 2
  • 21
  • 41
  • Ok please mark an answer as the correct one if possible – Philip Laine Apr 21 '16 at 09:31
  • I have marked my answer correct as it was the fix for the error being displayed. Your answer was a big help in getting into a position where I could find the buy so I have up voted it. I hope that makes sense and thanks again :-). – pls Apr 21 '16 at 16:31
0

Well, this is a late answer but here is your problem. If this can help others to understand it.

  • You have an array of Taxi elements
  • when rx_itemsWithCellIdentifier() is called, element is a Taxi (of course, it is an element of the array)

But in your code you do:

cell.choiceModel = element
// Where
var choiceModel: ChoiceModel? {
    didSet {
        layoutCell()
    }
}

So, you are trying to assign a Taxi to a ChoiceModel. This is why your are getting this error. Swift type inference determines that the types mismatch. You can try to comment the line inside the block and the error should disappear.

chrilith
  • 260
  • 3
  • 8