xmartlabs / Eureka

Elegant iOS form builder in Swift
https://eurekacommunity.github.io
MIT License
11.78k stars 1.33k forks source link

Evaluating `row.hidden` within `cellUpdate` results in a crash. #980

Closed pouriaalmassi closed 7 years ago

pouriaalmassi commented 7 years ago

I am trying to evaluate the hidden property of a SwitchRow cell after dismissing a modally presented view controller. Upon first presentation of the view controller that contains the SwitchRow cell the cell is hidden.

The scenario I'm attempting to create is as follows:

Attempted Solutions

  1. I have tried calling tableView?.reloadData() in viewWillAppear(_ :) which does result in calling the cellUpdate closure. However, setting row.hidden within cellUpdate results in a tableview internal inconsistency exception (stack trace below).
  2. I have tried putting the form setup code in viewWillAppear(_ :) but this just re-adds the form upon each presentation.

Ideally I'd like to evaluate any hidden values within viewWillAppear(_ :)

Current implementation.


var isPasscodeSet = false

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        tableView?.reloadData()
}

override func viewDidLoad() {
super.viewDidLoad()

 form +++

            SwitchRow("x")
            .cellUpdate { cell, row in
                print("cellUpdate x")
            }

            <<< SwitchRow("y")
                .cellUpdate { cell, row in
                    print("cellUpdate y")
                    self.tableView?.beginUpdates()
                    row.hidden = Condition(booleanLiteral: !self.isPasscodeSet)
                    row.evaluateHidden()
                    self.tableView?.endUpdates()
        }
}

// Action that modally presents view controller B
// Within view controller B the isPasscodeSet boolean is toggled before dismissal

Suggestions?

isPasscodeSet? false
2017-04-02 23:52:39.225 EurekaPlayground[13888:942079] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.7.47/UITableView.m:1442
2017-04-02 23:52:39.234 EurekaPlayground[13888:942079] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 1 from section 0 which only contains 1 rows before the update'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001064ebb0b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x0000000103d3f141 objc_exception_throw + 48
    2   CoreFoundation                      0x00000001064efcf2 +[NSException raise:format:arguments:] + 98
    3   Foundation                          0x00000001038d93b6 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
    4   UIKit                               0x000000010434d0b5 -[UITableView _endCellAnimationsWithContext:] + 6071
    5   EurekaPlayground                    0x0000000103440c04 _TFFC16EurekaPlayground14ViewControllerP33_3710AB4C8CBF53A03AB5A5E19871BB2713configureFormFT_T_U0_FTC6Eureka10SwitchCellCS1_9SwitchRow_T_ + 516
    6   Eureka                              0x000000010359dbac _TPA__TFFe6EurekaRxCS_7BaseRowxS_7RowTyperS1_9cellSetupFFTwx4Cellx_T_xU_FwxS2_T_ + 92
    7   Eureka                              0x000000010359dc48 _TPA__TTRGRxC6Eureka7BaseRowxS_7RowTyperXFo_owx4Cell__XFo_iwxS2__iT__ + 56
    8   Eureka                              0x00000001035e39e5 _TFC6Eureka3RowWP33_03FF383D1ACB40A8AF766EB442538E745_cellGSQx_ + 1781
    9   Eureka                              0x00000001035e3b9e _TFFFC6Eureka3Rowg4cellGSQx_u_KzT_GSqx_U_FT_GSqx_ + 302
    10  Eureka                              0x00000001035d85b7 _TFC6Eureka3Rowg8baseCellCS_8BaseCell + 55
    11  Eureka                              0x00000001035593e9 _TTSf4g_g_n___TFC6Eureka18FormViewController9tableViewfTCSo11UITableView14heightForRowAtV10Foundation9IndexPath_V12CoreGraphics7CGFloat_merged + 329
    12  Eureka                              0x0000000103554207 _TToFC6Eureka18FormViewController9tableViewfTCSo11UITableView14heightForRowAtV10Foundation9IndexPath_V12CoreGraphics7CGFloat_merged + 71
    13  UIKit                               0x00000001043877bc -[UITableView _estimatedHeightForRowAtIndexPath:] + 100
    14  UIKit                               0x00000001045bdbaa __66-[UISectionRowData refreshWithSection:tableView:tableViewRowData:]_block_invoke + 367
    15  UIKit                               0x00000001045bd1ae -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 3248
    16  UIKit                               0x00000001045c2453 -[UITableViewRowData rectForSection:] + 510
    17  UIKit                               0x00000001045c3764 -[UITableViewRowData indexPathsForRowsInRect:extraHitSpaceBetweenRows:] + 112
    18  UIKit                               0x00000001045c3f39 -[UITableViewRowData indexPathsForRowsInRect:] + 68
    19  UIKit                               0x000000010436483f -[UITableView indexPathsForRowsInRect:] + 67
    20  UIKit                               0x0000000115c7880a -[UITableViewAccessibility indexPathsForRowsInRect:] + 98
    21  UIKit                               0x0000000104364bdd -[UITableView indexPathsForVisibleRows] + 128
    22  UIKit                               0x0000000104362bb7 -[UITableView reloadData] + 476
    23  UIKit                               0x0000000115c7ae27 -[UITableViewAccessibility reloadData] + 44
    24  EurekaPlayground                    0x000000010343efca _TFC16EurekaPlayground14ViewController14viewWillAppearfSbT_ + 570
    25  EurekaPlayground                    0x000000010343f021 _TToFC16EurekaPlayground14ViewController14viewWillAppearfSbT_ + 49
    26  UIKit                               0x00000001043b985d -[UIViewController _setViewAppearState:isAnimating:] + 447
    27  UIKit                               0x00000001043ba073 -[UIViewController __viewWillAppear:] + 147
    28  UIKit                               0x00000001043f3801 -[UINavigationController _startTransition:fromViewController:toViewController:] + 789
    29  UIKit                               0x00000001043f46b3 -[UINavigationController _startDeferredTransitionIfNeeded:] + 843
    30  UIKit                               0x00000001043f57f1 -[UINavigationController __viewWillLayoutSubviews] + 58
    31  UIKit                               0x00000001045e72bc -[UILayoutContainerView layoutSubviews] + 231
    32  UIKit                               0x0000000115cda3ef -[UILayoutContainerViewAccessibility layoutSubviews] + 42
    33  UIKit                               0x00000001042d420b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
    34  QuartzCore                          0x000000010a7f7904 -[CALayer layoutSublayers] + 146
    35  QuartzCore                          0x000000010a7eb526 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 370
    36  QuartzCore                          0x000000010a7eb3a0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
    37  QuartzCore                          0x000000010a77ae92 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
    38  QuartzCore                          0x000000010a7a7130 _ZN2CA11Transaction6commitEv + 468
    39  QuartzCore                          0x000000010a7a7b37 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 115
    40  CoreFoundation                      0x0000000106491717 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    41  CoreFoundation                      0x0000000106491687 __CFRunLoopDoObservers + 391
    42  CoreFoundation                      0x0000000106476038 CFRunLoopRunSpecific + 440
    43  UIKit                               0x000000010420b02f -[UIApplication _run] + 468
    44  UIKit                               0x00000001042110d4 UIApplicationMain + 159
    45  EurekaPlayground                    0x0000000103444927 main + 55
    46  libdyld.dylib                       0x00000001081af65d start + 1
    47  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 
mats-claassen commented 7 years ago

Could you try with the current master version? It should work in Xcode 8.3.

Also I would try setting row.hidden in viewWillAppear and then reloading the table (if necessary)

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let yRow = ...
        yRow.hidden = Condition(booleanLiteral: !self.isPasscodeSet)
        yRow.evaluateHidden()
        tableView?.reloadData()
}

I would definitely not call beginUpdates and endUpdates inside cellUpdate

m-revetria commented 7 years ago

Closing this due to lack of response