0

我有一些代码加载到一些空的部分和项目中。然后,如果存在网络连接,则会对可见单元进行一些调用。我在每个部分都有一个按钮,它根据使用 indexPath 的部分类型导航到另一个视图。我的问题是,当我删除第一个部分时,cellProvider 不会更新 indexPath 并且按钮导航到错误的视图。但是,如果我滚动,问题就会消失。如何确保 indexPath 更新?编辑:看来我的 headerViews 保留了旧的 indexPath,但 cellProvider 正确更新。滚动并返回后,标题视图将设置为正确的 indexPath。

private enum RowItemType: Hashable {
    case itemTypeOne(collection: MyCollection)
    case itemTypeTwo(collection: MyCollection)
    case itemTypeThree(collection: OtherCollection)
}

private enum SectionType: Hashable {
    case sectionOne
    case sectionTwo
    case sectionThree
}

class MyCollection: Codable, Hashable, Equatable {
    var identifier = UUID()
    var foos: [Foo]
    
    init(foos: [Foo] = [Foo]()) {
        self.foos = foos
    }
    
    // MARK: Equatable

    var hash: Int {
        var hasher = Hasher()
        hasher.combine(identifier)
        return hasher.finalize()
    }

    static func == (lhs: MyCollection, rhs: MyCollection) -> Bool {
        lhs.identifier == rhs.identifier
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(identifier)
    }
}

class OtherCollection: Codable, Hashable, Equatable {
    var identifier = UUID()
    var bars: [Bar]
    
    init(bars: [Bar] = [Bar]()) {
        self.bars = bars
    }
    
    // MARK: Equatable

    var hash: Int {
        var hasher = Hasher()
        hasher.combine(identifier)
        return hasher.finalize()
    }

    static func == (lhs: OtherCollection, rhs: OtherCollection) -> Bool {
        lhs.identifier == rhs.identifier
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(identifier)
    }
}

final class SomeTableViewController: UITableVIewController {
  ...code....
RELEVENT CODE
private func makeDataSource() -> UITableViewDiffableDataSource<SectionType, RowItemType> {
        
         UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, item in
            
            guard let self = self else {
                return UITableViewCell()
            }
            
            guard let marginTableView = tableView as? AutoMarginTableView else {
                return UITableViewCell()
            }
             
             switch item {
             case .itemTypeOne(collection: let collection):
                 let carousel = self.itemOneCarouCell(from: marginTableView, withSection: .sectionOne, atIndexPath: indexPath)
                 
                 if !collection.foos.isEmpty {
                     carousel.configureCell(with: .sectionOne, fooCollection: collection)
                     self.showViewAllButtonForHeader(collection.foos.count > 3, atIndexPath: indexPath)
                 } else {
                     carousel.configureCellForLoading()
                     self.getFoosTypeOne(collection: collection)
                 }
                 
                 return carousel
             case .itemTypeTwo(let collection):
                 let carousel = self.itemTwoCarouCell(from: marginTableView, withSection: .sectionTwo, atIndexPath: indexPath)
                 
                 if !collection.foos.isEmpty {
                     carousel.configureCell(with: .sectionTwo, fooCollection: collection)
                     self.showViewAllButtonForHeader(collection.foos.count > 3, atIndexPath: indexPath)
                 } else {
                     carousel.configureCellForLoading()
                     self.getFoosTypeTwo(collection: collection)
                 }
                 
                 return carousel
             case .ttemTypeThree(let collection):
                 let carousel = self.itemThreeCarouCell(from: marginTableView, withSection: .sectionThree, atIndexPath: indexPath)
                 if !collection.bars.isEmpty {
                     carousel.configureCell(with: collection)
                     self.showViewAllButtonForHeader(true, atIndexPath: indexPath)
                 } else {
                     carousel.configureCellForLoading()
                     self.getBars(collection: collection)
                 }
                 return carousel
          
        })
    }

      private func showViewAllButtonForHeader(_ show: Bool, atIndexPath indexPath: IndexPath) {
        if let headerView = self.tableView.headerView(forSection: indexPath.section) as? MyTableHeaderView {
            UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseInOut, animations: {
                headerView.showViewAll(show)
            }, completion: nil)
        }
    }

private func getFoosTypeOne(collection: MyCollection) {
        var snapshot = dataSource.snapshot()
        if FeatureFlags.isFeatureEnabled && snapshot.sectionIdentifiers.contains(.sectionOne) {
            
            someRepositry.getfoos { result in
                if case .success(let foos) = result {
                    if !foos.isEmpty {
                        collection.foos = foos
                        snapshot.reloadItems([.itemTypeOne(collection: collection)])
                    } else {
                        if snapshot.sectionIdentifiers.contains(.sectionOne) {
                            snapshot.deleteSections([.sectionOne])
                        }
                    }
                    
                    self.dataSource.apply(snapshot, animatingDifferences: true)
                }
            }
        }
    }

private func getFoosTypeTwo(collection: MyCollection) {
        var snapshot = dataSource.snapshot()
        if FeatureFlags.isFeatureEnabled && snapshot.sectionIdentifiers.contains(.sectionTwo) {
            
            someRepositry.getDifferentFoos { result in
                if case .success(let foos) = result {
                    if !foos.isEmpty {
                        collection.foos = foos
                        snapshot.reloadItems([.itemTypeTwo(collection: collection)])
                    } else {
                        if snapshot.sectionIdentifiers.contains(.sectionTwo) {
                            snapshot.deleteSections([.sectionTwo])
                        }
                    }
                    
                    self.dataSource.apply(snapshot, animatingDifferences: true)
                }
            }
        }
    }

private func getBars(collection: OtherCollection) {
        var snapshot = dataSource.snapshot()
        someService.getSomeCollection { someColl in
            DispatchQueue.main.async {
                if let someColl = someColl {
                    if !someColl.bars.isEmpty {
                        collection.bars = someColl.bars
                        snapshot.reloadItems([.itemTypeThree(collection: collection)])
                    } else {
                        if snapshot.sectionIdentifiers.contains(.sectionThree) {
                            snapshot.deleteSections([.sectionThree])
                        }
                    }
                }
                
                self.dataSource.apply(snapshot, animatingDifferences: true)
            }
            
        }
    }
}

extension SomeTabelViewController: SomeTableHeaderViewDelegate {
    func someTableHeaderViewTappedViewAll(_ headerView: SomeTableHeaderView) {
        guard headerView.section < dataSource.numberOfSections(in: tableView) else {
            return
        }
        
        let snapshot = dataSource.snapshot()
        let section = snapshot.sectionIdentifiers[headerView.section]
        switch section {
        case .sectionOne:
            if case .itemTypeOne(let collection) = snapshot.itemIdentifiers(inSection: .sectionOne).first, !collection.foos.isEmpty {
                let vc = SomeListViewController()
                navigationController?.pushViewController(vc, animated: true)
            }
        case .sectionTwo:
            if case .itemTypeTwo(let collection) = snapshot.itemIdentifiers(inSection: .sectionTwo).first, !collection.foos.isEmpty {
                let vc = SomeListViewController()
                navigationController?.pushViewController(vc, animated: true)
            }
        case .sectionThree:
            if case .itemTypeThree(let collection) = snapshot.itemIdentifiers(inSection: .sectionThree).first, !collection.bars.isEmpty {
                let vc = OtherViewController(collecton: collection)
                navigationController?.pushViewController(vc, animated: true)
            }
    }
}
4

0 回答 0