Recently we came across a rather peculiar crash on our swift app.
0 OurApp 0x000000010005c0d0 generic specialization <Swift.String with Swift.String : Swift.Hashable in Swift> of Swift._VariantSetStorage.nativeRemoveObjectForKey <A : Swift.Hashable>(inout Swift._VariantSetStorage<A>)(A) -> Swift.Optional<A> (ProductFilterTableViewModel.swift)
1 OurApp 0x00000001000570d4 function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed> of OurApp.ProductFilterTableViewModel.toggleSelectionStateForCellAtIndexPath (OurApp.ProductFilterTableViewModel)(ObjectiveC.NSIndexPath) -> () (ProductFilterTableViewModel.swift:511)
2 OurApp 0x000000010004ef44 @objc OurApp.ProductFilterTableViewModel.handleRadioButtonPressedChanged (OurApp.ProductFilterTableViewModel)(ObjectiveC.UIButton) -> () (ProductFilterTableViewModel.swift:629)
This crash could only be reproduced in release mode and happened when toggling a radio button on and off rapidly.
Eventually we came across the following function that updates a dictionary of selected values keyed by a section into a set:
var selectedElementIDSet: Set<String>
if let storedIDs = selectedElementIDsForSectionType(section.sectionType) {
selectedElementIDSet = storedIDs//this triggers a copy
} else {
selectedElementIDSet = []
}
selectedElementIDSet.insert(elementID)
selectedElementIDsByFilterSection.updateValue(selectedElementIDSet, forKey: section.sectionType)
Above we are retrieving the set of storedIDs and copying it over to a new variable. Then we insert the elementID into this set and updated our dictionary with this new instance of the Set. It looks like there is some kind of bug in the Swift compiler causing the Set to release its values while the dictionary is updated.
If we naively change the above code to not copy the set and instead update the original the crash no longer occurs
if var storedIDs = selectedElementIDsForSectionType(section.sectionType) {
storedIDs.insert(elementID)//no more copying
selectedElementIDsByFilterSection.updateValue(storedIDs, forKey: section.sectionType)
} else {
var selectedElementIDSet: Set<String> = [elementID]
selectedElementIDsByFilterSection.updateValue(selectedElementIDSet, forKey: section.sectionType)
}
Am I doing something wrong here or should this be reported as a bug?
Sidenote: This crash has also come up on a different issue here as well but the fix doesnt apply in this scenario