I have an array which is set once a specific API is called. However when I then try to access this array at a later point it is empty again.
The class in question looks like this:
class SearchableLoginFormField: LoginFormField {
weak var delegate: PopoverPresentableDelegate?
var selectedObject: Selectable?
let popoverType: PopoverType
var sourceList = [Selectable]() {
didSet {
// Field set
}
}
private lazy var selectionPopover: ContainerPopover = {
let popover = LoginFormPopover(objectSelected: { object in
self.selectedObject = object
self.text = object.selectionName
self.selectionPopover.dismiss(animated: true)
}, popoverType: self.popoverType)
return popover
}()
init(popoverType: PopoverType, fieldTitle: String, fieldIcon: UIImage?,
colorScheme: UIColor?, returnAction: (() -> Void)?) {
self.popoverType = popoverType
super.init(fieldTitle: fieldTitle, fieldIcon: fieldIcon, colorScheme: colorScheme, returnAction: returnAction)
configureFormField()
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureFormField() {
textDidChangeAction = { [weak self] in
/// We clear the selectedAirport each time user searches in field so that we know whether we need to trigger shouldEndEditingAction or not
/// (which we only trigger if user ends action and selectedAirport is nil)
self?.selectedObject = nil
self?.configureField(with: I6TextInputKeyboardSettings(
capitalization: .allCharacters,
spellCheck: .no
))
guard let self = self else { return }
self.searchObjects(
field: self,
popover: self.selectionPopover,
sourceList: self.sourceList,
dataPopover: self.selectionPopover)
}
self.shouldEndEditingAction = { [weak self] in
if self?.selectedObject == nil {
let filteredText = self?.text.replacingOccurrences(of: "-", with: "") // We remove the "-" if user has entered it so that reg can still be validated
self?.text = filteredText ?? ""
self?.verifyFieldInput()
}
}
}
private func searchObjects<T>(field: I6TextField, popover: ContainerPopover, sourceList: [T], dataPopover: ContainerPopover) {
if field.text.isEmpty {
dataPopover.dismiss(animated: true, completion: nil)
} else {
let filterCompletion: (Int) -> () = { count in
dataPopover.sourceView = field
// Present if needed
let isPopoverPresented = dataPopover.isVisiblyPresented
if (!dataPopover.isBeingPresented && !isPopoverPresented && count > 0) {
self.delegate?.presentPopover(popover: dataPopover)
}
if (isPopoverPresented || dataPopover.isBeingPresented) && count == 0 {
dataPopover.dismiss(animated: false, completion: nil)
}
}
dataPopover.filterToSearchTerm(field.text.replacingOccurrences(of: "-", with: ""), objects: sourceList, completion:filterCompletion)
}
}
private func verifyFieldInput() {
let matchingList = sourceList.filter {
$0.selectionName.lowercased() == self.text.lowercased()
}
if matchingList.count == 1 {
self.text = matchingList[0].selectionName
self.selectedObject = matchingList[0]
self.hasError = false
} else if matchingList.count > 1 {
self.errorAlert(errorText: Strings.EHandshake.FlightLookupCustomisable.mulitpleMatches.localizedFormat(""))
} else if matchingList.isEmpty {
self.errorAlert(errorText: Strings.EHandshake.FlightLookupCustomisable.noSelectionMatches.localizedFormat(""))
}
delegate?.textInputValidated(popover: selectionPopover)
}
}
The variable I am focussed on is the sourceList var.
Now, in the class where this object is created we declare the SearchableLoginFormField as follows:
lazy var iata: SearchableLoginFormField = {
let field = SearchableLoginFormField(
popoverType: .airport,
fieldTitle: FlightLookupStrings.originAiportCode.localized,
fieldIcon: UIImage.Login.origin,
colorScheme: fieldColor,
returnAction: nil)
field.delegate = self
validator.registerField(field, rules: [RequiredRule(message: ValidationStrings.aircraftRegistrationRequired.localized)])
return field
}()
And then we set the sourceList with the following delegate method:
func airportsSet() {
iata.sourceList = CoreDataObjectsManager.shared.airportsList
}
This is called when the airports list is retrieved from an API call.
Break points prove that the sourceList is being set correctly:
- airportsSet() delegate method is hit and contains the correct airport list
- didSet method on the SearchableLoginFormField is fired and the sourceList is successfully set to the Airports list
- when we hit the textField delegate method upon editing the field, the sourceList is empty I tried moving the configureFormField() method into the didSet on the sourceList but I have the same result.
I'm really confused how this seems to be set but then empty again. I'm keeping the breakpoint on the didSet and at no point is it being set to empty by anything else.
The superclass contains the following var:
public var textDidChangeAction: (() -> Void)?
and the following textFieldDelegate method:
open func textFieldDidChangeSelection(_ textField: UITextField) {
didChangeSelectionAction?()
}
So in the configureFormField method we are setting the action of this delegate method accordingly which gets triggered. It is at this point that the sourceList is empty.
The field itself is added in viewDidLoad of the main display viewController as follows:
stackView.add(arrangedSubviews: [number, reg, iata, submitButton, errorLabel])