You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中Eureka列表选择:选中最后一项返回后自动取消选中问题

Fixing the Unselected Korean Language Issue in Eureka Form

Hey there! Let's figure out why your Korean language selection keeps getting unselected when you leave the view controller, and fix this properly without that temporary hardcode in viewWillAppear.

Let's Break Down the Problems in Your Code

  1. Incorrect row setup in viewDidLoad

    • You’re calling form.setValues([language : language]) inside the loop for every language option. This overwrites the form’s selection state every time the loop runs, so only the last iteration’s setting sticks (and it’s not even the right way to set row selection).
    • You’re hardcoding lrow.value = nil for every row, which means none of them start selected even if there’s a saved value in UserDefaults.
  2. Limited viewWillAppear logic

    • Your current code only handles the Korean language case, so other saved languages won’t restore correctly. Plus, it doesn’t check if there’s actually a saved value before forcing the selection.
  3. Redundant saving in viewDidAppear

    • You’re saving languageSelected again here, but you already do this in valueHasBeenChanged. This can lead to inconsistent state if the two values ever get out of sync.

Here's the Fixed Code

import Eureka

class ListSectionsController: FormViewController {
    let defaults = UserDefaults.standard
    var languageSelected = "English (default)"
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // Restore the saved language selection correctly for all options
        if let savedLanguage = defaults.string(forKey: "LanguageSelection") {
            languageSelected = savedLanguage
            // Update the form to reflect the saved selection
            if let section = form.first as? SelectableSection<ImageCheckRow<String>> {
                section.selectedRow()?.deselect() // Deselect any currently selected row
                if let rowToSelect = section.rows.first(where: { $0.selectableValue == savedLanguage }) {
                    rowToSelect.select()
                }
            }
        } else {
            // If no saved value, default to English
            languageSelected = "English (default)"
            if let section = form.first as? SelectableSection<ImageCheckRow<String>> {
                section.selectedRow()?.deselect()
                if let rowToSelect = section.rows.first(where: { $0.selectableValue == languageSelected }) {
                    rowToSelect.select()
                }
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let languageSelections = ["English (default)", "Spanish", "Japanese 日本語", "Chinese Mandarin 普通话", "Indonesian", "Dutch - het Nederlands", "Korean 한국어"]
        // Get saved language once, before setting up rows
        let savedLanguage = defaults.string(forKey: "LanguageSelection") ?? languageSelected
        
        form +++ SelectableSection<ImageCheckRow<String>>() { section in
            section.header = HeaderFooterView(title: "Language Selection")
            section.onSelectSelectableRow = { _, selectedRow in
                // Optional: Auto-deselect other rows (Eureka does this by default for single-select, but explicit is safe)
                selectedRow.section?.rows.forEach { row in
                    if row !== selectedRow {
                        row.deselect()
                    }
                }
            }
        }
        
        for option in languageSelections {
            form.last! <<< ImageCheckRow<String>(option) { lrow in
                lrow.title = option
                lrow.selectableValue = option
                // Set row's selected state based on saved value
                lrow.value = option == savedLanguage ? option : nil
            }
        }
    }
    
    override func valueHasBeenChanged(for row: BaseRow, oldValue: Any?, newValue: Any?) {
        guard let section = row.section as? SelectableSection<ImageCheckRow<String>>,
              section === form[0],
              let selectedValue = section.selectedRow()?.baseValue as? String else {
            return
        }
        print("Selected: \(selectedValue)")
        languageSelected = selectedValue
        defaults.set(languageSelected, forKey: "LanguageSelection")
    }
    
    // Remove the redundant viewDidAppear save
    // override func viewDidAppear(_ animated: Bool) {
    //     defaults.set(languageSelected, forKey: "LanguageSelection")
    // }
}

Key Changes Explained

  1. Proper row initialization in viewDidLoad

    • We fetch the saved language once before building the rows, then set each row’s value to match whether it’s the saved option. This ensures the correct row starts selected when the view loads.
    • Removed the loop-internal form.setValues calls, which were causing unexpected overwrites.
  2. Robust viewWillAppear restoration

    • Now handles all language options, not just Korean. It deselects any existing selection first, then finds and selects the saved language row. If there’s no saved value, it defaults to English correctly.
  3. Removed redundant save

    • Got rid of the viewDidAppear save since valueHasBeenChanged already saves the selection when the user picks an option. This prevents conflicting saves.
  4. Explicit single-select handling

    • Added onSelectSelectableRow to the section to ensure only one row is selected at a time (Eureka’s default for SelectableSection, but making it explicit helps avoid edge cases).

Test It Out

Now when you select Korean (or any other language) and navigate away, come back to the view controller—your selection should stay intact. No more random unselection, and the logic works for all options without hardcoding!

内容的提问来源于stack exchange,提问作者grm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:57:51