Open jserrafindster opened 2 years ago
Hi, could you please provide exact crash error. Also, are you using a custom nib file for this row? Some code to reproduce the error would also be helpful as it does not seem to happen in the Example project.
not sure if what your asking is this message
0 Eureka 0x0000000103c65914 Swift runtime failure: Unexpectedly found nil while implicitly unwrapping an Optional value + 0 (SwitchRow.swift:0)
this is what is in the crash report
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000103c65914
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [3368]
Triggered by Thread: 0
Thread 0 name:
Thread 0 Crashed:
0 Eureka 0x0000000103c65914 Swift runtime failure: Unexpectedly found nil while implicitly unwrapping an Optional value + 0 (SwitchRow.swift:0)
1 Eureka 0x0000000103c65914 SwitchCell.valueChanged() + 204 (SwitchRow.swift:63)
2 Eureka 0x0000000103c65888 row.get + 44 (Cell.swift:0)
3 Eureka 0x0000000103c65888 SwitchCell.valueChanged() + 64 (SwitchRow.swift:63)
4 Eureka 0x0000000103c65930 @objc SwitchCell.valueChanged() + 24 (<compiler-generated>:0)
5 UIKitCore 0x00000001858f01fc -[UIApplication sendAction:to:from:forEvent:] + 96 (UIApplication.m:5361)
6 UIKitCore 0x0000000185a11774 -[UIControl sendAction:to:forEvent:] + 124 (UIControl.m:871)
7 UIKitCore 0x00000001857a46fc -[UIControl _sendActionsForEvents:withEvent:] + 348 (UIControl.m:942)
8 UIKitCore 0x0000000185dcfa04 -[UISwitchModernVisualElement sendStateChangeActions] + 80 (UISwitchModernVisualElement.m:418)
9 UIKitCore 0x0000000185dcf6dc -[UISwitchMVEGestureTrackingSession _sendStateChangeActionsIfNecessary] + 68 (UISwitchMVEGestureTrackingSession.m:123)
10 UIKitCore 0x0000000185dd0450 __88-[UISwitchModernVisualElement _handleLongPressWithGestureLocationInBounds:gestureState:]_block_invoke + 64 (UISwitchModernVisualElement.m:562)
11 UIKitCore 0x000000018576252c -[_UIAfterCACommitBlock run] + 64 (_UIAfterCACommitQueue.m:137)
12 UIKitCore 0x000000018567c690 -[_UIAfterCACommitQueue flush] + 200 (_UIAfterCACommitQueue.m:228)
13 libdispatch.dylib 0x0000000182e4a1a4 _dispatch_call_block_and_release + 24 (init.c:1517)
14 libdispatch.dylib 0x0000000182e4b1a8 _dispatch_client_callout + 16 (object.m:560)
15 libdispatch.dylib 0x0000000182e2c4b8 _dispatch_main_queue_callback_4CF$VARIANT$armv81 + 908 (inline_internal.h:2601)
16 CoreFoundation 0x000000018313a888 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 (CFRunLoop.c:1795)
17 CoreFoundation 0x00000001830f8188 __CFRunLoopRun + 2528 (CFRunLoop.c:3144)
18 CoreFoundation 0x000000018310ae1c CFRunLoopRunSpecific + 572 (CFRunLoop.c:3268)
19 GraphicsServices 0x00000001a34b59a0 GSEventRunModal + 160 (GSEvent.c:2200)
20 UIKitCore 0x000000018593eb90 -[UIApplication _run] + 1080 (UIApplication.m:3493)
21 UIKitCore 0x00000001856d416c UIApplicationMain + 332 (UIApplication.m:5047)
22 libswiftUIKit.dylib 0x00000001995fdd24 UIApplicationMain(_:_:_:_:) + 100 (UIKit.swift:530)
we do everything by code
Also I'm not able to reproduce in my iPhone XR, but I see this sort of error ocurring more often than it should, but not actually related with a SwitchRow. More as when we reload and refresh.
This is the reason why I've start limiting my refresh/reloads to smaller parts of the form rather than update the whole form.
We use realm with observers. Instead refreshing the whole form each time the collection in database changes we specifically just refresh a section in the form if a certain property in database is update
OK. So there are two variables which could be nil but shouldn't in that row. If you have been able to debug this, would you know which variable is nil? It would be easier to debug this issue with some code to reproduce it. Specifically how that SwitchRow is set up. For example, avoid accessing the cell in the row initializer
Not sure if i understood correctly, you are refering "Two variables" as switchControl
and isOn
? because I don't think thats the issue. If one of them is nil it will just assume ?? false
right?
for what I've seen I would bet more in the row
variable which is defined as
public weak var row: RowOf<T>!
-- edit --
just notice that .value
is also an optional
Right, I was referring to row
or switchControl
. I agree it looks more like the row being nil but the row should always be set (it is set immediately after creating the cell, which should happen before calling setup
and therefore you should never get into valueChanged
before that). So I can only imagine this happening because the row is deinstantiated and somehow the switch changes value after that. Please review your code to check whether that could be possible. I repeat, a code to reproduce this would be helpful.
I'm going back to talk about reload refreshing the sections cause we are also gettting this issue which may as well be related with our implementation
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)
for what i understood this issue is related with updating our form UI but having the datasource outdated or something like that ?
So I slightly change our code to share it here we update our form with reload() function
struct MySection : FormSectionProtocol {
var title: String = "Section title"
var tag : String { return title }
var vc: FormViewController
let sectionType : Sections = .sectionTypeId
init(vc : FormViewController) {
self.vc = vc
generate()
}
enum rows {
case firstRowType // image cell
case secondRowType // switch cell
var row : BaseRow {
switch self {
case .firstRowType:
return ImageRow(){ row in
row.cell.textTitle = "row title1"
row.cell.cellImage = #imageLiteral(resourceName: "image")
}
.onCellSelection({ cell,row in
row.deselect()
// navigate
})
case .secondRowType:
let row = SwitchRow(){ row in
row.cell.height = { 60 }
row.cell.imageView?.image = #imageLiteral(resourceName: "image")
row.title = "this is the second row"
row.cell.switchControl.isOn = true // TODO: fetch value
row.value = row.cell.switchControl.isOn
}.onCellSelection {
cell,row in
cell.switchControl.setOn(!cell.switchControl.isOn, animated: true)
row.value = cell.switchControl.isOn
row.deselect()
}.onChange { row in
guard let cell = row.cell else { return }
let currentValue = true // TODO: fetch value
guard currentValue != row.value else { return } // prevent rollback from triggering the api request
remoteProcedure(status: cell.switchControl.isOn) {
success in
DispatchQueue.main.async {
switch success {
case true: break // update value
case false:
cell.switchControl.setOn(!cell.switchControl.isOn, animated: true) // roll back to previous value
row.value = cell.switchControl.isOn // keeps row value consistent, switch value doesnt do it automatically
}
}
}
}
.cellUpdate { cell,row in
cell.textLabel?.textColor = UIColor.Global.Text
}
row.tag = "myRow"
return row
}
}
}
mutating func generate()
{
self.title = title
self.vc.form +++ self.section
self.populate()
}
func populate() {
if let mySection = vc.form.sectionBy(tag: tag) {
mySection <<< rows.firstRowType.row
mySection <<< rows.secondRowType.row
}
}
func reload() {
UIView.performWithoutAnimation {
vc.tableView.beginUpdates()
if let mySection = vc.form.sectionBy(tag: tag) {
mySection.removeAll()
}
populate()
vc.tableView.reloadData() // this might be causing a crash, should not be called inside the begin end (?)
vc.tableView.endUpdates()
}
}
}
Thanks for posting the code. First comment on it is that you are accessing the cell
in the row initializer which you should avoid. Use cellSetup
for everything that relates to the cell.
Example:
SwitchRow() { row in
row.title = "..."
row.value = ...
}.cellSetup { row, cell in
cell.height = { 60 }
...
}
As for the invalid number of rows in section 0.
issue: try just calling the removeAll and populate functions. Or maybe reloadData after that without the begin and end updates which should be called internally.
Just an update I'm still testing but... removing the beginUpdates and endUpdates seems to help (still not sure if it fixes it ) about using setup instead update it was not working, the style was not being applied. for instance to text color and font (not sure if cell height is being setup correctly)
Hey, it is correct to use either cellSetup or cellUpdate and for certain modifications you need cellUpdate. Just don't access the cell in the row's initializer block.
SwitchRow() { row in
row.title = "..."
row.value = ...
row.cell.... = ... // <-- Don't do this
}
Eureka (5.3.4) Xcode Version 13.2.1 (13C100) iOS 15.3.0
I'm having some crashes which I believe are related with refreshing the form/sections
This is the code from eureka:
any ideas?