特定の API が呼び出されると設定される配列があります。ただし、後でこの配列にアクセスしようとすると、再び空になります。
問題のクラスは次のようになります。
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)
}
}
私が注目している変数は、sourceList 変数です。
ここで、このオブジェクトが作成されるクラスで、次のように SearchableLoginFormField を宣言します。
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
}()
次に、次のデリゲート メソッドを使用して sourceList を設定します。
func airportsSet() {
iata.sourceList = CoreDataObjectsManager.shared.airportsList
}
これは、空港リストが API 呼び出しから取得されるときに呼び出されます。
ブレーク ポイントは、sourceList が正しく設定されていることを証明します。
- airportsSet() デリゲート メソッドがヒットし、正しい空港リストが含まれている
- SearchableLoginFormField の didSet メソッドが起動され、sourceList が Airports リストに正常に設定されます
- フィールドの編集時に textField デリゲート メソッドをヒットすると、sourceList が空です。configureFormField() メソッドを sourceList の didSet に移動しようとしましたが、同じ結果になりました。
これがどのように設定されているように見えるが、再び空になるのか、私は本当に混乱しています。私は didSet にブレークポイントを保持していますが、他のものによって空に設定されることはありません。
スーパークラスには次の変数が含まれています。
public var textDidChangeAction: (() -> Void)?
および次の textFieldDelegate メソッド:
open func textFieldDidChangeSelection(_ textField: UITextField) {
didChangeSelectionAction?()
}
したがって、configureFormField メソッドでは、トリガーされるこのデリゲート メソッドのアクションを適宜設定しています。この時点で、sourceList は空です。
フィールド自体は、次のようにメイン ディスプレイ viewController の viewDidLoad に追加されます。
stackView.add(arrangedSubviews: [number, reg, iata, submitButton, errorLabel])