使用Autolayout的NSInternalInconsistencyException

时间:2014-07-27 10:34:55

标签: ios uitableview swift autolayout

我正在尝试在表视图控制器中使用标头的自定义标题视图。 我已经为我的自定义uitableviewheaderfooterview创建了一个类。

我的自定义标题视图中有什么内容?它为默认标题视图添加了一个按钮。

我可以使用这个自定义标题视图和几个uitableviewcontrollers ..但似乎我根本无法将它用于某些控制器。 导航控制器的第一个表视图控制器;使用我的自定义视图是好的。 但如果我推到下一个观点,我会遇到问题。

我不是在这里发布我的自定义类,因为它的长度是因为这可以用更简单的变化来模拟。我使用故事板,在故事板中我有一个导航控制器和tableview控制器,我在那里使用我的自定义视图。一个单元格推送到另一个tableview控制器。这也使用自定义类,但在推送时会立即挂起:

 2014-07-27 13:10:04.365 Hours[41029:3941001] *** Terminating app due
 to uncaught exception 'NSInternalInconsistencyException', reason:
 'Modifications to the layout engine must not be performed from a
 background thread.'
 *** First throw call stack: (  0   CoreFoundation                      0x0000000108beec35 __exceptionPreprocess + 165  1   libobjc.A.dylib   
 0x000000010ab76a1c objc_exception_throw + 45   2   CoreFoundation      
 0x0000000108beeb6d +[NSException raise:format:] + 205  3   Foundation 
 0x000000010924decc -[NSISEngine withBehaviors:performModifications:] +
 89     4   UIKit                               0x0000000109f8a2d9
 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452   5   UIKit                               0x0000000109f8a0ec -[UIView(AdditionalLayoutSupport)
 _switchToLayoutEngine:] + 197  6   UIKit                               0x0000000109f89d88 -[UIView(AdditionalLayoutSupport)
 _initializeHostedLayoutEngine] + 404   7   UIKit                               0x0000000109f8a881 -[UIView(AdditionalLayoutSupport)
 _layoutEngineCreateIfNecessary] + 53   8   UIKit                               0x0000000109f7f53f -[UIView(UIConstraintBasedLayout)
 _withAutomaticEngineOptimizationDisabled:] + 22    9   UIKit                               0x0000000109f7ff20 -[UIView(UIConstraintBasedLayout) addConstraints:]
 + 263  10  Hours                               0x0000000108282db4 _TFC5Hours16EventTypesEditor9tableViewfS0_FTGSQCSo11UITableView_22viewForHeaderInSectionSi_GSQCSo6UIView_
 + 7012     11  Hours                               0x0000000108283e56 _TToFC5Hours16EventTypesEditor9tableViewfS0_FTGSQCSo11UITableView_22viewForHeaderInSectionSi_GSQCSo6UIView_
 + 70   12  UIKit                               0x0000000109a0bb7e -[UITableView _delegateViewForHeaderInSection:] + 45     13  UIKit                               0x0000000109a0f124 __96-[UITableView
 _sectionHeaderView:withFrame:forSection:floating:reuseViewIfPossible:willDisplay:]_block_invoke
 + 97   14  UIKit                               0x000000010998ab9e +[UIView(Animation) performWithoutAnimation:] + 65   15  UIKit                               0x0000000109a0efcf -[UITableView
 _sectionHeaderView:withFrame:forSection:floating:reuseViewIfPossible:willDisplay:]
 + 511  16  UIKit                               0x0000000109a0f8c0 -[UITableView _sectionHeaderViewWithFrame:forSection:floating:reuseViewIfPossible:willDisplay:]
 + 85   17  UIKit                               0x00000001099ef030 -[UITableView _updateVisibleHeadersAndFootersNow:] + 2582    18  UIKit                               0x00000001099f06a5 -[UITableView _updateVisibleCellsNow:isRecursive:]
 + 3714     19  UIKit                               0x0000000109a05fea -[UITableView layoutSubviews] + 213  20  UIKit                               0x0000000109992d25 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
 + 519  21  QuartzCore                          0x00000001097a9058 -[CALayer layoutSublayers] + 150     22  QuartzCore                          0x000000010979dc7e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE +
 380    23  QuartzCore                          0x000000010979daee
 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24     24  QuartzCore                          0x000000010970c8e6
 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242    25  QuartzCore                          0x000000010970d9f2
 _ZN2CA11Transaction6commitEv + 390     26  QuartzCore                          0x000000010970dc27 _ZN2CA11Transaction14release_threadEPv + 199     27 
 libsystem_pthread.dylib             0x000000010b45f54f
 _pthread_tsd_cleanup + 86  28  libsystem_pthread.dylib             0x000000010b45c479 _pthread_exit + 111  29  libsystem_pthread.dylib   
 0x000000010b45c3e9 pthread_exit + 30   30  Foundation                  
 0x0000000109282e51 __NSFinalizeThreadData + 0  31  Foundation         
 0x0000000109262e41 __NSThread__main__ + 1214   32 
 libsystem_pthread.dylib             0x000000010b45b899 _pthread_body +
 138    33  libsystem_pthread.dylib             0x000000010b45b72a
 _pthread_struct_init + 0   34  libsystem_pthread.dylib             0x000000010b45ffc9 thread_start + 13 ) libc++abi.dylib: terminating
 with uncaught exception of type NSException

以下是导致此问题的自定义视图的变体:

    let customSection = 0

    override func tableView(tableView: UITableView!, viewForHeaderInSection section: Int) -> UIView! {
        switch section {
        case customSection:
            var h = UITableViewHeaderFooterView()
//          var h = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier("Header") as UITableViewHeaderFooterView // This also caused trouble

            h.contentView.autoresizingMask = .FlexibleWidth | .FlexibleHeight
            h.contentView.setTranslatesAutoresizingMaskIntoConstraints(true)

            var t = UILabel(frame: CGRectZero)
            t.text = "Hello"
//          t.sizeToFit()
            t.setTranslatesAutoresizingMaskIntoConstraints(false)
            h.contentView.addSubview(t)

            h.layoutSubviews()

            var views = NSMutableDictionary()
            views.setValue(h.contentView, forKey: "|")
            views.setValue(t, forKey: "label")

            h.contentView.addConstraints([
                NSLayoutConstraint.constraintsWithVisualFormat("H:[label]-|", options: nil, metrics: nil, views: views)
                ])

            h.contentView.addConstraints([
                NSLayoutConstraint.constraintsWithVisualFormat("V:|-[label]", options: nil, metrics: nil, views: views)
                ])


            return h
        default:
            return super.tableView(tableView, viewForHeaderInSection: section)
        }
    }

可能......但不确定。不熟悉线程.. 魔术是如何发生的?这是如何..当你用推动动作点击单元格.. didselectrowatindexpath被激活,它执行以下操作:

override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        let cell = tableView.cellForRowAtIndexPath(indexPath)
        cell!.selectCell()
    }

现在,选择细胞..

override func selectCell() {

        UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)

        if self.buttonSelector != nil {
            let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))
            dispatch_after(time, dispatch_get_main_queue(), {
                NSThread.detachNewThreadSelector(self.buttonSelector, toTarget:self.buttonTarget, withObject: self)
                })
        }

    }

selectCell作为uitableviewcell扩展中的空函数包含在内。 最后,什么设置为buttonSelector?在uitableviewcontroller中执行推送的功能..就在这里:

func eventTypeDetails(cell:UIMenuItemCell){     NSLog(“详细信息为%@”,(eventTypes.objectAtIndex(cell.tag)为NSArray).objectAtIndex(1)为String)

let cell = self.tableView.dequeueReusableCellWithIdentifier("eventTypeCell") as SettingsActionCell
cell.eventTypesButton!.sendActionsForControlEvents(UIControlEvents.TouchUpInside)

}

我开始看到它是我的覆盖功能selectCell()导致这个,但如何解决这个问题.. ???简单的修复可能是改变didselectrowatindexpath以相应地推动索引路径..但​​我想知道这是否可以修复,所以我可以保持我原来的做事方式?毕竟,我有很多基于uitableviewcell的自定义类来帮助制作像视图和东西一样的形式..所有都使用自动布局和所有使用相同的方法(其中一些有按钮或其他类型的操作)

1 个答案:

答案 0 :(得分:1)

好吧,我不完全确定你的代码是做什么的,但我认为你的内容过于复杂。

如果你只是想推动一个视图控制器那么这肯定是这样的。在tableView:didSelectRowAtIndexPath:方法中,您应该能够直接调用导航视图的推送方法,无需直接在单元格上调用任何内容。

如果你想保持代码的方式没问题,那么你的selectCell函数就是问题所在,因为它似乎主要是启动后台线程来完成工作。在后台线程中进行任何类型的UI工作都是iOS中的一个禁忌。

尝试将其更改为

if self.buttonSelector != nil {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))
    dispatch_after(time, dispatch_get_main_queue(), {
        UIApplication.sharedApplication().sendAction(self.buttonSelector, to: self.buttonTarget, from: self, forEvent: nil)
    })
}

对于目标,您很可能需要使用NSInvocation,但只需确保它在主线程上