首页 > 解决方案 > Swift:数组已设置,但在访问时为空

问题描述

我有一个数组,一旦调用特定的 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 设置正确:

我真的很困惑这似乎是如何设置的,但又是空的。我将断点保留在 didSet 上,并且在任何时候它都不会被其他任何东西设置为空。

超类包含以下变量:

public var textDidChangeAction: (() -> Void)?

和以下 textFieldDelegate 方法:

 open func textFieldDidChangeSelection(_ textField: UITextField) {
        didChangeSelectionAction?()
    }

因此,在 configureFormField 方法中,我们相应地设置了此委托方法的操作,该操作会被触发。正是在这一点上,sourceList 是空的。

该字段本身在主显示viewController的viewDidLoad中添加如下:

stackView.add(arrangedSubviews: [number, reg, iata, submitButton, errorLabel])

标签: swiftdelegatesuitextfielddelegatedidset

解决方案


推荐阅读