0

我将我的 iOS 应用程序的 7.6 版推送到 App Store 并注意到该应用程序突然包含许多在调试期间没有出现的错误(奇怪的行为)。

由于该应用程序在 xCode 9.x 中运行良好,我强烈怀疑这些问题是从 Xcode 10.3 开始发生的。

我正在使用 Swift 4.2(Swift 5 的转换用于下一次更新)

经过几个小时的调查,我找到了问题:当编译模式=“ whole module”时出现错误,当设置为“ incremental”时消失。在调试模式下(当应用程序用完 Xcode 时),编译模式设置为“ incremental”以释放其“ whole module”(这是您在 Xcode 10.x 中创建新项目时的标准配置,我怀疑)这解释了我们为什么这样做在调试测试期间看不到问题。

另请注意,更改为旧版构建系统并不能解决问题。只有设置编译模式=“ incremental”才能解决问题。

分析:

  • 我跟踪问题是因为我的所有 TableViews 都没有调用委托。 
  • 我有以下简单的层次结构:在此处输入图像描述

    • ViewTableRoot 的代码:

class ViewTableRoot : UITableView, UITableViewDelegate, UITableViewDataSource  {


    var didScrollToOffset : ( (CGFloat) -> Void )?
    var didEndScrolling   : ( (CGFloat) -> Void )?
    var didChangeEditing  : ( (       ) -> Void )?


    //MARK: lifecycle


    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override init(frame: CGRect, style: UITableView.Style) {
        super.init(frame: frame, style: style)
        setup();
    }

    func setup() {
        //set the corner radius of the layer so that the sliding of the cells underneath the rounded headers does not show up
        layer.cornerRadius = 5
        //setup myself as delegate and data source
        delegate = self
        dataSource = self
    }

    deinit {
        let className = String(describing: self)
        log.debug("**********\(className)")
    }

    //MARK: - public API


    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        didChangeEditing?()
    }


    //MARK: - scrollview delegate


    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //because we are also getting events when swiping on the cells, we need to see the difference between
        //swipig on the cell and swiping in the "actual" table => we do this by checking the frame size
        guard scrollView.frame == frame else { return }
        didScrollToOffset?(scrollView.contentOffset.y)
    }

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        //because we are also getting events when swiping on the cells, we need to see the difference between
        //swipig on the cell and swiping in the "actual" table => we do this by checking the frame size
        guard scrollView.frame == frame else { return }        
        if !decelerate {
            didEndScrolling?(scrollView.contentOffset.y)
        }
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        //because we are also getting events when swiping on the cells, we need to see the difference between
        //swipig on the cell and swiping in the "actual" table => we do this by checking the frame size
        guard scrollView.frame == frame else { return }
        didEndScrolling?(contentOffset.y)
    }


    //MARK: - UITableViewDataSource


    func numberOfSections(in tableView: UITableView) -> Int {
        preconditionFailure("Must be implemented by derrived class")
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        preconditionFailure("Must be implemented by derrived class")
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        preconditionFailure("Must be implemented by derrived class")
    }


    //MARK: - UITableViewDelegate

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    }

}

  • ViewTableSettings 的代码:


class ViewTableSettings : ViewTableRoot {

    var settings : [[Setting]]? {
        didSet {
            reloadData()
        }
    }

    var didPressSetting  : ((Setting, CGRect) -> (Void))?

    //MARK: lifecycle


    override func setup() {
        super.setup()
        log.debug("delegate : \(delegate)")
        //register xibs
        register(CellTableSetting.nib, forCellReuseIdentifier: CellTableSetting.reuseIdentifier)
    }


    //MARK: - UITableView


    override func numberOfSections(in tableView: UITableView) -> Int {
        let count = settings?.count ?? 0
        log.debug("count: \(count)")
        log.debug("delegate : \(delegate)")
        return count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let count = settings?[section].count ?? 0
        log.debug("count: \(count)")
        log.debug("delegate : \(delegate)")
        return count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        log.debug("delegate : \(delegate)")
        //ask for a new cell
        let cell = tableView.dequeueReusableCell(withIdentifier: CellTableSetting.reuseIdentifier, for: indexPath) as! CellTableSetting
        guard let setting = settings?[indexPath.section][indexPath.row] else {
            preconditionFailure("Asking CellTableSetting but no Setting model defined")
        }
        //load up!
        cell.setting = setting
        cell.lastCell = indexPath.section != numberOfSections - 1 ? false : indexPath.row == (numberOfRows(inSection:indexPath.section) - 1)
        //return cell to use
        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        log.debug("-")
        return CellTableSetting.height
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        log.debug("-")
        tableView.deselectRow(at:indexPath, animated: true)
        guard let setting = settings?[indexPath.section][indexPath.row] else {
            return
        }
        didPressSetting?(setting,rectForRow(at: indexPath))
    }

    func tableView(_: UITableView, viewForFooterInSection: Int) -> UIView? {
        log.debug("-")
        guard viewForFooterInSection < (numberOfSections-1) else {
            let version = UILabel()
            version.text = UIApplication.AppVersionAndBuildPrettyPrint
            version.font = UIFont.defaultBoldFont(size: 12)
            version.textColor = PaintCode.mainLightGray_a50
            version.textAlignment = .center
            return version
        }
        let v = UIView()
        v.backgroundColor = PaintCode.mainLightGray_a50
        return v
    }

    func tableView(_: UITableView, heightForFooterInSection: Int) -> CGFloat {
        log.debug("-")
        return heightForFooterInSection < (numberOfSections-1) ? 5 : 40
    }

}
  • 如您所见,ViewTableRoot声明符合UITableViewDelegate(也符合,UITableViewDataSource但目前还不是问题)
  • 委托实际上是在 中分配self的,ViewTableRoot但实际的委托函数是在派生中实现的ViewTableSettings(这同样在 Xcode 9.x 中完美运行)
  • 当编译模式=“ Whole Module”这些委托函数没有被调用=>这是错误
  • 当设置为“ incremental”时,这些委托函数被调用就好了!

我为更深入地了解该问题所做的其他测试:

  • 切换到“旧版构建系统”(通过 Xcode/file/project 设置)不能解决问题;只要Whole Module启用,问题仍然存在
  • 当我在 ViewTableRoot 中创建空委托函数并在 ViewTableSettings 中覆盖它们时,它确实有效:-o
  • 我确实验证ViewTableSettings了委托确实设置为 ViewTableRoot 的实例ViewTableSettings而不是 ViewTableRoot (在这种情况下,不会实现任何委托功能)

我的想法

  • 我觉得我偶然发现了(新的?)构建系统中的一个错误?
  • 还有其他人遇到类似的问题吗?
4

2 回答 2

0

是的,我和你有同样的问题。当编译模式为“Whole Module”时,Collectionview 控制器会混乱,但 Tableview 控制器不会。模拟器设备上的结果。也许您可以尝试直接使用 UITableViewController 而不是遵循 TableView 协议。

于 2019-09-17T00:50:11.417 回答
0

安装了最新的 Xcode 11.4 (11E146) 和问题接缝在这个版本中解决。我重新启用了整个模块优化,并且所有接缝都按预期工作。所以......原来这是一个错误XCdoe!

于 2020-03-25T18:20:01.777 回答