

現在Combine、UITableViewDiffableDataSourceの使い方を学ぶためにMVVMにて構築しようとしているのですが、表題の通りUITableViewCell内ボタンの多重実行されます。

当該箇所のコードは以下の通りで、Bool値のプロパティを持つ配列を監視してCellに表示させています。  
Cellの内部にボタンisFavoriteButtonを配置しタップするとcell内部のaddActionが実行され、配列内のBool値変数にtoggleが実行され、下記Func
setBinder内で監視検知しボタンのImageが変更されます。

問題はViewのNavigationItemにいれたボタンを押すと配列からBool値trueのみを取り出して表示し、再度同じボタンを押すと全配列が表示されるのですがその際表示されたCellのうちBool値falseで再度表示されたCell内ボタンをタップすると複数回addaction内の処理が実行されてしまいます。  
具体的には再描写されたCellが後列であればあるほど何度も処理されます。(3列目3回、4列目４～５回、5列名５回～)  
まだCombineの扱いが分かっておらずストリームが適切でなく、Cell描写をコントロールできていないことで発生していると考えているのですがご教示いただけますと幸いです。  
宜しくお願い致します。

[code]

    //VC
    extension ShoppingListViewController {
        private func setupBinder() {
            // viewModelのPublishedを監視購読実行
            viewModel.$items.sink { [weak self] items in
                self?.items = items
            }.store(in: &cancellable)
    
            viewModel.$state
                .dropFirst()
                .receive(on: DispatchQueue.main)
                .sink { [weak self] state in
                    guard let state = state else { return }
                    switch state {
                    case .loaded:
                        self?.viewModel.fetchArray()
                        self?.setButtonImage()
                        self?.apply()
                        print("state = loaded")
                    case let .error(message):
                        self?.showErrorMessageIfNeeded(message)
                        print("state = error")
                    case .favorite:
                        // favorite表示
                        self?.setButtonImage()
                        self?.apply()
                        print("state = favorite")
                    case .delete:
                        // deleteモード
                        self?.setButtonImage()
                        self?.deleteButton.tintColor = .red
                        self?.apply()
                        print("state = delete")
                    }
                }.store(in: &cancellable)
            Task {
                self.viewModel.setInitialLoadedView()
                print(self.viewModel.state)
            }
        }
        private func apply() { //情報注入
            var snapShot = Snapshot()
            snapShot.appendSections([0])
            snapShot.appendItems(viewModel.items, toSection: 0)
            dataSource?.defaultRowAnimation = .fade
            if let dataSource {
                dataSource.apply(snapShot, animatingDifferences: true)
            } else {
                dataSource = DataSource(
                    tableView: shoppingListTableView,
                    cellProvider: { [weak self] tableView, indexPath, item in
                        self?.returnCell(tableView, at: indexPath, item)
                    }
                )
                dataSource?.applySnapshotUsingReloadData(snapShot)
            }
        }
     //Cell構築
        private func returnCell(_ tableView: UITableView, at indexPath: IndexPath, _: Item) -> UITableViewCell {
            let identifier = "ShoppingListCell"
            let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? ShoppingListCell
            var item = self.items[indexPath.row]
            cell?.nameLabel.text = item.itemName
            cell?.setIsBoughtImage(item.isBought)
            cell?.setIsFavoriteImage(item.isFavorited)
            
            cell?.isFavoriteButton.addAction(.init(handler: { _ in
                self.viewModel.didTapIsFavorite(indexPath.row)
                cell?.setIsFavoriteImage(self.items[indexPath.row].isFavorited)
            }), for: .touchUpInside)
            return cell!
        }
    
[/code]


CC BY-SA 4.0
2023-02-10T02:46:30.853
93786
2023-02-14T14:13:04.343
2023-02-13T01:57:10.913
3060
57027
question
swift uitableview combine
UITableViewCell内ボタンの多重実行


自己解決しました、apply内に記述していたdatasourceの位置が誤っていたこととreturnCell内でaddActionを行っていたことで各Cellにて処理が実行されていたことが原因でした。


CC BY-SA 4.0
2023-02-14T14:13:04.343
93837
2023-02-14T14:13:04.343
57027
93786
answer