How to avoid duplicate tap on button on Tableview with RxDataSources
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
add a comment |
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
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 disposingcellDisposeBagin the cell'sprepareForReusemethod? 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
add a comment |
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
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
ios swift rx-swift rxdatasources
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 disposingcellDisposeBagin the cell'sprepareForReusemethod? 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
add a comment |
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 disposingcellDisposeBagin the cell'sprepareForReusemethod? 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
add a comment |
1 Answer
1
active
oldest
votes
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()
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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()
}
add a comment |
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()
}
add a comment |
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()
}
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()
}
answered Jan 3 at 9:15
PaulPaul
6671618
6671618
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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
cellDisposeBagin the cell'sprepareForReusemethod? 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