How to avoid duplicate tap on button on Tableview with RxDataSources












0















I have a table view with RxDataSources on which cell items got a remove icon. when cells get dequeued and click on that remove icon, all the previous click events get triggered, thus duplicate tap.
Item cell :



 removeImageView.rx.tap().map { _ in indexPath } 
.bind(to: viewModel.onRemoveItem).disposed(by: cellDisposeBag)


Cell viewmodel:



let onRemoveItem = PublishSubject<IndexPath>()


View controller view model where the cell and ViewModel get bound:



 let vm = ItemViewModel(with: item)
vm.onRemoveItem.bind(to: self.onRemoveItem).disposed(by: self.rx.disposeBag)

return SectionItem.item(viewModel: vm)


View Controller:



let dataSource = RxTableViewSectionedReloadDataSource<SectionItem>(configureCell: { dataSource, tableView, indexPath, item in
switch item {
case .item(let viewModel):
let cell = (tableView.dequeueReusableCell(withIdentifier: itemtIdentifier, for: indexPath) as? ItemCell)!
cell.bind(to: viewModel, at: indexPath)
return cell
}
}, titleForHeaderInSection: { dataSource, index in
let section = dataSource[index]
return section.title
} )

output?.items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)

output?.onRemoveCartIemTapped.distinctUntilChanged()
.skip(1)
.distinctUntilChanged().drive(onNext: { [weak self] (indexPath) in
print("onRemoveCartIemTapped" + String(indexPath.item))
}).disposed(by: rx.disposeBag)


Console debug:



onRemoveCartIemTapped0
onRemoveCartIemTapped3
onRemoveCartIemTapped1
onRemoveCartIemTapped4









share|improve this question























  • Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

    – Glenn
    Jan 2 at 14:19











  • Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

    – Paul
    Jan 2 at 15:20











  • no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

    – Mohamed ALOUANE
    Jan 2 at 15:25






  • 1





    @Paul I fixed it, thank you :). post your comment as an answer.

    – Mohamed ALOUANE
    Jan 2 at 16:45
















0















I have a table view with RxDataSources on which cell items got a remove icon. when cells get dequeued and click on that remove icon, all the previous click events get triggered, thus duplicate tap.
Item cell :



 removeImageView.rx.tap().map { _ in indexPath } 
.bind(to: viewModel.onRemoveItem).disposed(by: cellDisposeBag)


Cell viewmodel:



let onRemoveItem = PublishSubject<IndexPath>()


View controller view model where the cell and ViewModel get bound:



 let vm = ItemViewModel(with: item)
vm.onRemoveItem.bind(to: self.onRemoveItem).disposed(by: self.rx.disposeBag)

return SectionItem.item(viewModel: vm)


View Controller:



let dataSource = RxTableViewSectionedReloadDataSource<SectionItem>(configureCell: { dataSource, tableView, indexPath, item in
switch item {
case .item(let viewModel):
let cell = (tableView.dequeueReusableCell(withIdentifier: itemtIdentifier, for: indexPath) as? ItemCell)!
cell.bind(to: viewModel, at: indexPath)
return cell
}
}, titleForHeaderInSection: { dataSource, index in
let section = dataSource[index]
return section.title
} )

output?.items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)

output?.onRemoveCartIemTapped.distinctUntilChanged()
.skip(1)
.distinctUntilChanged().drive(onNext: { [weak self] (indexPath) in
print("onRemoveCartIemTapped" + String(indexPath.item))
}).disposed(by: rx.disposeBag)


Console debug:



onRemoveCartIemTapped0
onRemoveCartIemTapped3
onRemoveCartIemTapped1
onRemoveCartIemTapped4









share|improve this question























  • Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

    – Glenn
    Jan 2 at 14:19











  • Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

    – Paul
    Jan 2 at 15:20











  • no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

    – Mohamed ALOUANE
    Jan 2 at 15:25






  • 1





    @Paul I fixed it, thank you :). post your comment as an answer.

    – Mohamed ALOUANE
    Jan 2 at 16:45














0












0








0








I have a table view with RxDataSources on which cell items got a remove icon. when cells get dequeued and click on that remove icon, all the previous click events get triggered, thus duplicate tap.
Item cell :



 removeImageView.rx.tap().map { _ in indexPath } 
.bind(to: viewModel.onRemoveItem).disposed(by: cellDisposeBag)


Cell viewmodel:



let onRemoveItem = PublishSubject<IndexPath>()


View controller view model where the cell and ViewModel get bound:



 let vm = ItemViewModel(with: item)
vm.onRemoveItem.bind(to: self.onRemoveItem).disposed(by: self.rx.disposeBag)

return SectionItem.item(viewModel: vm)


View Controller:



let dataSource = RxTableViewSectionedReloadDataSource<SectionItem>(configureCell: { dataSource, tableView, indexPath, item in
switch item {
case .item(let viewModel):
let cell = (tableView.dequeueReusableCell(withIdentifier: itemtIdentifier, for: indexPath) as? ItemCell)!
cell.bind(to: viewModel, at: indexPath)
return cell
}
}, titleForHeaderInSection: { dataSource, index in
let section = dataSource[index]
return section.title
} )

output?.items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)

output?.onRemoveCartIemTapped.distinctUntilChanged()
.skip(1)
.distinctUntilChanged().drive(onNext: { [weak self] (indexPath) in
print("onRemoveCartIemTapped" + String(indexPath.item))
}).disposed(by: rx.disposeBag)


Console debug:



onRemoveCartIemTapped0
onRemoveCartIemTapped3
onRemoveCartIemTapped1
onRemoveCartIemTapped4









share|improve this question














I have a table view with RxDataSources on which cell items got a remove icon. when cells get dequeued and click on that remove icon, all the previous click events get triggered, thus duplicate tap.
Item cell :



 removeImageView.rx.tap().map { _ in indexPath } 
.bind(to: viewModel.onRemoveItem).disposed(by: cellDisposeBag)


Cell viewmodel:



let onRemoveItem = PublishSubject<IndexPath>()


View controller view model where the cell and ViewModel get bound:



 let vm = ItemViewModel(with: item)
vm.onRemoveItem.bind(to: self.onRemoveItem).disposed(by: self.rx.disposeBag)

return SectionItem.item(viewModel: vm)


View Controller:



let dataSource = RxTableViewSectionedReloadDataSource<SectionItem>(configureCell: { dataSource, tableView, indexPath, item in
switch item {
case .item(let viewModel):
let cell = (tableView.dequeueReusableCell(withIdentifier: itemtIdentifier, for: indexPath) as? ItemCell)!
cell.bind(to: viewModel, at: indexPath)
return cell
}
}, titleForHeaderInSection: { dataSource, index in
let section = dataSource[index]
return section.title
} )

output?.items
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)

output?.onRemoveCartIemTapped.distinctUntilChanged()
.skip(1)
.distinctUntilChanged().drive(onNext: { [weak self] (indexPath) in
print("onRemoveCartIemTapped" + String(indexPath.item))
}).disposed(by: rx.disposeBag)


Console debug:



onRemoveCartIemTapped0
onRemoveCartIemTapped3
onRemoveCartIemTapped1
onRemoveCartIemTapped4






ios swift rx-swift rxdatasources






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 2 at 13:21









Mohamed ALOUANEMohamed ALOUANE

2,53721742




2,53721742













  • Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

    – Glenn
    Jan 2 at 14:19











  • Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

    – Paul
    Jan 2 at 15:20











  • no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

    – Mohamed ALOUANE
    Jan 2 at 15:25






  • 1





    @Paul I fixed it, thank you :). post your comment as an answer.

    – Mohamed ALOUANE
    Jan 2 at 16:45



















  • Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

    – Glenn
    Jan 2 at 14:19











  • Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

    – Paul
    Jan 2 at 15:20











  • no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

    – Mohamed ALOUANE
    Jan 2 at 15:25






  • 1





    @Paul I fixed it, thank you :). post your comment as an answer.

    – Mohamed ALOUANE
    Jan 2 at 16:45

















Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

– Glenn
Jan 2 at 14:19





Do you happen to have a sample project for this? I'd like to help you out on this. This should be pretty easy but I usually use the normal implementation of delegates and datasource methods of tableView in my ViewModel without using RxSwift's extensions (but using RxSwift in the entire project, not just in tableViews).

– Glenn
Jan 2 at 14:19













Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

– Paul
Jan 2 at 15:20





Are you disposing cellDisposeBag in the cell's prepareForReuse method? If the cells are being reused without the subscriptions being disposed then it could cause this kind of behaviour.

– Paul
Jan 2 at 15:20













no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

– Mohamed ALOUANE
Jan 2 at 15:25





no i don't use prepareForReuse at all. how can i do that even though i have cell dispose when button tapped

– Mohamed ALOUANE
Jan 2 at 15:25




1




1





@Paul I fixed it, thank you :). post your comment as an answer.

– Mohamed ALOUANE
Jan 2 at 16:45





@Paul I fixed it, thank you :). post your comment as an answer.

– Mohamed ALOUANE
Jan 2 at 16:45












1 Answer
1






active

oldest

votes


















0














This is caused by the UITableView reusing the cell. To avoid that you can override the cell's prepareForReuse() method and ensure any existing subscriptions are disposed.



I usually declare the DisposeBag as a var and then assign a new DisposeBag to it in prepareForReuse(). When the DisposeBag is deinited it will dispose all of the subscriptions it contains. Something like:



override func prepareForReuse() {
super.prepareForReuse()

cellDisposeBag = DisposeBag()
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54007149%2fhow-to-avoid-duplicate-tap-on-button-on-tableview-with-rxdatasources%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    This is caused by the UITableView reusing the cell. To avoid that you can override the cell's prepareForReuse() method and ensure any existing subscriptions are disposed.



    I usually declare the DisposeBag as a var and then assign a new DisposeBag to it in prepareForReuse(). When the DisposeBag is deinited it will dispose all of the subscriptions it contains. Something like:



    override func prepareForReuse() {
    super.prepareForReuse()

    cellDisposeBag = DisposeBag()
    }





    share|improve this answer




























      0














      This is caused by the UITableView reusing the cell. To avoid that you can override the cell's prepareForReuse() method and ensure any existing subscriptions are disposed.



      I usually declare the DisposeBag as a var and then assign a new DisposeBag to it in prepareForReuse(). When the DisposeBag is deinited it will dispose all of the subscriptions it contains. Something like:



      override func prepareForReuse() {
      super.prepareForReuse()

      cellDisposeBag = DisposeBag()
      }





      share|improve this answer


























        0












        0








        0







        This is caused by the UITableView reusing the cell. To avoid that you can override the cell's prepareForReuse() method and ensure any existing subscriptions are disposed.



        I usually declare the DisposeBag as a var and then assign a new DisposeBag to it in prepareForReuse(). When the DisposeBag is deinited it will dispose all of the subscriptions it contains. Something like:



        override func prepareForReuse() {
        super.prepareForReuse()

        cellDisposeBag = DisposeBag()
        }





        share|improve this answer













        This is caused by the UITableView reusing the cell. To avoid that you can override the cell's prepareForReuse() method and ensure any existing subscriptions are disposed.



        I usually declare the DisposeBag as a var and then assign a new DisposeBag to it in prepareForReuse(). When the DisposeBag is deinited it will dispose all of the subscriptions it contains. Something like:



        override func prepareForReuse() {
        super.prepareForReuse()

        cellDisposeBag = DisposeBag()
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 3 at 9:15









        PaulPaul

        6671618




        6671618
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54007149%2fhow-to-avoid-duplicate-tap-on-button-on-tableview-with-rxdatasources%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Mossoró

            Error while reading .h5 file using the rhdf5 package in R

            Pushsharp Apns notification error: 'InvalidToken'