簡體   English   中英

numberOfRowsInSection 已調用但 cellForRowAt 未調用

[英]numberOfRowsInSection called but cellForRowAt not called

在我的應用程序中,我調用了一個 API 來獲取一些數據並從中下載文件。 下載后回調調用。 在這種情況下,表格視圖更新得很好。 但是假設用戶訪問了屏幕並且在將內容下載回前一個屏幕並再次訪問同一屏幕之前。 在這種情況下,表視圖未更新。 僅當用戶在未完成下載內容的情況下返回之前的 controller 並再次出現在同一屏幕上時,我才會遇到此問題。

保修VC.Swift

class WarrantyVC: UIViewController {
    
    // MARK: - Outlets
    ///
    @IBOutlet weak var warrantyTableView: UITableView!
    
    //Latum
    ///
    @IBOutlet weak var knowMoreButton: UIButton!
    
    // MARK: - Variables
    ///
    var warrantyDataSource: WarrantyDataSource!
    ///
    var viewModel: WarrantyViewModel?
   
    // MARK: - Controller life cycle
    ///
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
       getUserGuide()
    }
    

    ///
    deinit {
        viewModel = nil
    }
    
    // MARK: - Initializing UI methods
    ///
    func setupUI() {
        viewModel = WarrantyViewModel()
        warrantyDataSource = WarrantyDataSource(withTableView: warrantyTableView)
        warrantyDataSource.delegate = self
    }
    
    // MARK: - API methods
    ///
    func getUserGuide() {
        CommonMethods.showProgressHud(inView: self.view)
        warrantyDataSource.introVideoAndGuideArray.removeAll()
        viewModel?.getUserGuidefunc(userId: "\(DataManager.shared.user?.userId ?? 0)", motorId: selectedMotor?.MotorTypeId ?? 0,dmpModelId:selectedMotor?.dmpModelId ?? 0) { [self] (success, response) in
            CommonMethods.hideProgressHud()
            Console.log(response ?? [String: Any]())
            self.setupUI()
            if !success { /Show some message./ }
            let userGuides = UserGuideService.introVideoAndGuideArray
            if userGuides.count > 0 {
                var newUserGuideArray = [UserGuide]()
                for tempUserGuide in userGuides {
                    let userGuide = tempUserGuide
                    let userManual = userGuide.usermanual
                    let videolink = userGuide.videolink
                    if videolink.trim().count > 0 {
                        if let tempUserGuide = userGuide.copy() as? UserGuide {
                            tempUserGuide.usermanual = ""
                            tempUserGuide.videolink = videolink
                            newUserGuideArray.append(tempUserGuide)
                        }
                    }
                    if userManual.trim().count > 0 {
                        if let tempUserGuide = userGuide.copy() as? UserGuide {
                            tempUserGuide.usermanual = userManual
                            tempUserGuide.videolink = ""
                            newUserGuideArray.append(tempUserGuide)
                        }
                    }
                }
                 self.warrantyDataSource.introVideoAndGuideArray = newUserGuideArray
                DispatchQueue.main.async {
                    self.warrantyTableView.reloadData()
                }
            }
        }
    }

WarrantyDatasource.swift

protocol UserGuideDataSourceDelegate: class {
    ///
    func onOpenPDF()
    ///
    func onPlayVideo(_ videoURL: String)
}

/// This DataSource class use to show data of UserGuide in table.
class WarrantyDataSource: NSObject {
    
    // MARK: - Variables
    ///
    fileprivate let cellNibName = "warrantyCell"
    ///
    var userGuideTitle: [String] = ["Intro to ABC", “XYZ”]
    ///
    var userGuideImage: [UIImage] = [ imageLiteral(resourceName: "ic_play"),  imageLiteral(resourceName: "ic_pdf")]
    ///
    fileprivate let cellSpacingHeight: CGFloat = 12
    ///
    var introVideoAndGuideArray = [UserGuide]()
    ///
    weak var delegate: UserGuideDataSourceDelegate?
    ///
    var numberOfSections: Int = 0
    ///
    convenience init(withTableView tableView: UITableView) {
        self.init()
        tableView.delegate = self
        tableView.dataSource = self
    }
    
    ///
    @objc func onOpenPDF(_ sender: UIButton) {
        guard introVideoAndGuideArray.count > 0 else { return }
        delegate?.onOpenPDF()
    }
    
    ///
    @objc func onPlayVideo(_ sender: UIButton) {
        delegate?.onPlayVideo(introVideoAndGuideArray[sender.tag].videolink)
    }
    
    /// This function help to setup user menual cell
    ///
    /// - Parameters:
    ///   - cell: UserGuideCell
    ///   - indexPath: IndexPath
    func setUserGuidePDFCell(_ cell: WarrantyCell, _ indexPath: IndexPath) {
        cell.guideImageView.image =  imageLiteral(resourceName: "ic_default_pdf")
        guard introVideoAndGuideArray.count > 0 else { return }
        cell.guideLabel.text = introVideoAndGuideArray[indexPath.section].userGuideTitle
        cell.guideButton.setImage(userGuideImage[1], for: .normal)
        cell.guideButton.tag = indexPath.section
        cell.guideButton.addTarget(self, action: #selector(onOpenPDF(_:)), for: .touchUpInside)
    }
}

// MARK: - Extension Implementing UITableView DataSource Callbacks
///
extension WarrantyDataSource: UITableViewDataSource {
    // MARK: Extension Implementing UITableView DataSource methods
    ///
    func numberOfSections(in tableView: UITableView) -> Int {
        numberOfSections = introVideoAndGuideArray.count
        return introVideoAndGuideArray.count
    }
    ///
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    /// Set the spacing between sections
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return cellSpacingHeight
    }
    
    /// Make the background color show through
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = UIView()
        headerView.backgroundColor = UIColor.clear
        return headerView
    }
    
    ///
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellNibName, for: indexPath) as? WarrantyCell else { return WarrantyCell() }
        if NetworkManager.sharedInstance.isReachable {
            let userGuide = introVideoAndGuideArray[indexPath.section]
            if userGuide.videolink.trim().count > 0 {
                cell.guideButton.setImage(userGuideImage[0], for: .normal)
                cell.guideButton.tag = indexPath.section
                cell.guideButton.addTarget(self, action: #selector(onPlayVideo(_:)), for: .touchUpInside)
                cell.guideLabel.text = introVideoAndGuideArray[indexPath.section].videoTitle
                let videoThumbnail = introVideoAndGuideArray[indexPath.section].vehicleVideoThumbnailLink
                cell.guideImageView.kf.setImage(with: URL.init(string: videoThumbnail), placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
            } else {
                setUserGuidePDFCell(cell, indexPath)
            }
        } else {
            setUserGuidePDFCell(cell, indexPath)
        }
        return cell
    }
}

當您第一次調用 getUserGuide API 並且在獲取回調之前或在下載數據之前,您會彈出視圖 controller 並再次推送相同的 controller。 那次第二次 getUserGuide API 將調用,您將從第一次調用 API 請求中得到回調。 因此產生了這個問題。

您可以通過如下更改實現來克服此問題;

當 API 第一次調用且在下載完成之前用戶嘗試彈出視圖 controller 時暫停下載,將響應中的 resumeData 存儲在 userdefault 中。 當用戶第二次嘗試調用 API 時,檢查您已經啟動下載的相同鏈接。 如果然后通過從用戶默認值中提取恢復數據來恢復相同鏈接的下載。

我希望這種方式對你有用。 快樂編碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM