Rxswift: Maybe delegate was already set in `xib` or `storyboard` and now it's being overwritten in code.

Created on 11 May 2016  路  20Comments  路  Source: ReactiveX/RxSwift

ShareTableViewController: 0x7feda58d6330>)for object ->; layer = ; contentOffset: {0, 0}; contentSize: {375, 307}>. Maybe delegate was already set inxiborstoryboard` and now it's being overwritten in code.: file /Users/apple/Documents/luoye/lawyeruser/newLuoye/Pods/RxCocoa/RxCocoa/Common/DelegateProxyType.swift, line 199

Most helpful comment

Am using latest version of rxSwift and rxDataSource ... I too face the same problem ... And I use tableView.dataSource = nil and tableView.dataSource = nil before bindTo or use rx_setDataSource. Anybody help me to fix this.

All 20 comments

Same problem here after upgrades to Cocoapods 1.0.0 and Xcode 7.3.1.

Hi, guys!

I don't think it a problem of Cocoapods

Most likely you are using bindTo(tableView. rx_itemsWithCellIdentifier) or methods from that family

What it does is trying to create data source and subscribe to subscribeProxyDataSourceForObject

You just need to remove it from xib or tableView.dataSource = nil before calling bindTo or use rx_setDataSource

@sergdort, you're right. It works setting datasource and delegate with nil in my viewDidLoad! But I still don't understand why this problem start occurring just after mentioned upgrades...

Thanks!

Hi guys,

This is an assert that fires when you have a previous data source set to warn you that you might be breaking that originally set data source.

assert(proxy.forwardToDelegate() === nil, "There is already a delegate set -> `\(proxy.forwardToDelegate()!)` for object -> `\(object)`.\nMaybe delegate was already set in `xib` or `storyboard` and now it's being overwritten in code.")

I'm kind of confused how to resolve this issue? This behavior is by design.

Hi, @kzaher . It seems to me that a lot of people don't understand what is the problem within assert message . I saw some people asked the same question in the slack channel.

May be we could somehow improve the message so it would be, more understandable. To kind of explaine why this a problem, because as far as I remember even if you creat UITableviewController manually, the dataSource and delegate set to the instance of controller, so it not only xib or storyboard.

How about this?

assert(proxy.forwardToDelegate() === nil, "This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working.\nIf you are ok with this, try to set delegate (data source) to nil in front of this operation.\n This is the source object value: \(object)\n This this the original delegate (data source) value: \(proxy.forwardToDelegate()!)\nMaybe delegate was already set in xib or storyboard and now it's being overwritten in code.\n")

This is just released. I think we can close it now.

What if i still need access to tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat but i have set the delegate to nil so the delegate func its not being called.

@Bashta you would just use rx.setDelegate:

tableView.delegate = nil
tableView.rx.setDelegate(yourDelegate).addDisposableTo(disposeBag)

Am using latest version of rxSwift and rxDataSource ... I too face the same problem ... And I use tableView.dataSource = nil and tableView.dataSource = nil before bindTo or use rx_setDataSource. Anybody help me to fix this.

I have a similar issue, the TableView has no data source before binging.

ViewModel Code is here

Assertion failed: This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working.
If you are ok with this, try to set delegate (data source) to nil in front of this operation.
This is the source object value:

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.tableFooterView = UIView(frame: CGRect.zero)

        self.startDatePickerView = UIDatePicker(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
        self.startDatePickerView.datePickerMode = .date
        self.startDatePickerView.date = Calendar.current.date(byAdding: .month, value: -1, to: Date()) ?? Date()

        self.endDatePickerView = UIDatePicker(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
        self.endDatePickerView.datePickerMode = .date

        self.startDateTextField.inputView = startDatePickerView
        self.endDateTextField.inputView = endDatePickerView

        self.viewModel = CustomerViewModel()

        (self.startDateTextField.rx.text <-> self.viewModel.startDateTime).disposed(by: rx.disposeBag)
        (self.endDateTextField.rx.text <-> self.viewModel.endDateTime).disposed(by: rx.disposeBag)

        self.viewModel.list.subscribe(onNext:{ [unowned self](event) in
            switch event {
            case .success(let response):

                response.drive(self.tableView.rx.items(cellIdentifier: "customerCell", cellType: UITableViewCell.self))
                    {data source) to `nil` in front of this operation.
                        (index, customer, cell) in
                        cell.textLabel?.text = "\(customer.UserName ?? "")\t\t\(customer.CreateTime ?? "")"
                    }
                    .disposed(by: self.rx.disposeBag)
            case .failure(let error):
                print( error )
            }

        }).disposed(by: rx.disposeBag)




        self.startDatePickerView.rx.date.map{ [weak self](date) in
            return self?.viewModel.dateFormater.string(from: date)
        }.bind(to: self.startDateTextField.rx.text).disposed(by: rx.disposeBag)

        self.endDatePickerView.rx.date.map{ [weak self](date) in
            return self?.viewModel.dateFormater.string(from: date)
            }.bind(to: self.endDateTextField.rx.text).disposed(by: rx.disposeBag)
    }
}

@ZZHHAANNGG Make sure the Table View doesn't have a delegate as well, not just a datasource attached.

@freak4pc I am sure the TableView has no delegate and datasouce. I changed the unowned self to weak self and the cell will not be created, the table is blank and has no such assertion issue.

Got to be some weird storyboard magic or UITableViewController defaults - using itself as a datasource and a delegate...

I've ran into this same issue, I too believe it's a storyboard thing. I've just set tableView.dataSource = nil and moved on.

As far as I understand you can just use a raw UIViewController or etc and dragndrop a tableview into it, which is different from using a UITableViewController which conveniently implements delegates and binds itself to the table for free. In the latter case you will need to explicitly set delegates to nil before using the Rx fun...

UITableViewController takes over the dataSource in a way that can't be disconnected (AFAIK) via Storyboard - so in that case you'll need to manually set the dataSource to nil. Option 2 which is what I do, is just use a UITableView in a UIViewController - much finer control.

I had a similar crash. Long story short: I resolved performing the cleaning before setting the delegate.

collectionView.dataSource = nil
collectionView.delegate = nil

collectionView.rx
    .setDelegate(self)
    .disposed(by: disposeBag)

Or in a do block before binding:

.do {
    self.tableView.dataSource = nil
    self.tableView.delegate = nil
}
.drive(tableView.rx.items(dataSource: self.dataSource))
.disposed(by: disposeBag)

Hope this little hint can help someone.

@Bashta you would just use rx.setDelegate:

tableView.delegate = nil
tableView.rx.setDelegate(yourDelegate).addDisposableTo(disposeBag)

which delegate u set? i add programmatically tableView and now i can't set delegate...

@Bashta you would just use rx.setDelegate:

tableView.delegate = nil
tableView.rx.setDelegate(yourDelegate).addDisposableTo(disposeBag)

which delegate u set? i add programmatically tableView and now i can't set delegate...

Thanks, man but the question was from Dec 27, 2016 XD

Was this page helpful?
0 / 5 - 0 ratings