我有一个数组,一旦调用特定的 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 var。
现在,在创建此对象的类中,我们声明 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])