【发布时间】:2020-06-02 12:59:00
【问题描述】:
我对使用 Swift 进行 iOS 开发有点陌生。所以,我可能在 Swift 中遗漏了一个我不知道的简单解决方案。 我正在开发一个 tvOS 应用程序,在其中显示用户可以从中选择的视频内容列表。该应用程序还包含一个设置选项卡,允许用户配置 5 种不同类型的设置。一旦他们选择了一个特定的类别,它就会显示一个新的表格视图,其中包含选项数组中的相应选项。这就是我需要帮助的“问题”。
我有这个结构,我将其用作单例:
struct BMUserSettings
{
internal static var shared = BMUserSettings()
var categories = [String]()
var options = [[String]]()
var currOptionsSelected: [Int] = [0,0,0,0,0] // This array corresponds to the categories array. It tells us what option within that group was selected.
init()
{
self.categories = ["Brand", "Environment","UI Language", "Playback Language", "Geo Location Permission"]
let brandOptionsGroup: [String] = ["CTV", "CTVHUB", "TSN", "Snackable", "RDS", "CP24", "BNN", "CTVNews", "Crave", "BRAVO", "E_BRAND", "SE", "VIDIQA"]
let environmentOptionsGroup: [String] = ["Staging", "Prod"]
let uiLanguageOptionsGroup: [String] = ["en", "fr"]
let playbackLanguageOptionsGroup: [String] = ["en", "fr"]
let geoLocationOptionsGroup: [String] = ["Allow", "Don't Allow"]
options.append(brandOptionsGroup)
options.append(environmentOptionsGroup)
options.append(uiLanguageOptionsGroup)
options.append(playbackLanguageOptionsGroup)
options.append(geoLocationOptionsGroup)
}
// MARK: - Custom Methods
func displayUserSettings() -> String
{
let displayText: String = "Brand=\(options[0][currOptionsSelected[0]]) Environment=\(options[1][currOptionsSelected[1]]) UI Language=\(options[2][currOptionsSelected[2]]) Playback Language=\(options[3][currOptionsSelected[3]]) Geo Location=\(options[4][currOptionsSelected[4]])"
return displayText
}
// MARK: - User Defaults
func saveToUserDefaults()
{
UserDefaults.standard.set(BMUserSettings.shared.currOptionsSelected, forKey: "currentoptions")
}
func loadFromUserDefaults(){
if let currentOptionsSelected = UserDefaults.standard.object(forKey: "currentoptions") as? [Int]{
BMUserSettings.shared.currOptionsSelected = currentOptionsSelected
}
else{
BMUserSettings.shared.currOptionsSelected = [0,0,0,0,0]
}
}
}
如您所见,“currOptionsSelected”整数数组包含用户为每个类别选择的选项。例如,如果用户选择品牌“Snackable”,则 currOptionsSelected 数组的第一个元素将保存 3 作为值。
我正在保存和加载 currOptionsSelected 到/从 UserDefaults 中,以便我知道用户的当前设置是什么。
这种方法的问题是: 1)即使我知道用户选择的特定选项的索引,我仍然需要设置 if-else 或 switch 条件,以确保我实际上可以从相应的“选项”数组中获取正确的字符串值 2)如果任何其他开发人员需要添加类别和相应的选项,那么他们需要确保他们保持一切井井有条 3) 我只是不知道这是否是处理此类问题的最佳方式
有什么更好的方法?
这是我尝试在表格视图中使用它的方式:
import UIKit
final class BMSettingsViewController: UIViewController
{
// MARK: - Instance Variables
private static let reuseIdentifier = String(describing: BMContentCell.self)
private let tableview = UITableView(backgroundColor: .white, autoResizingMask: false)
private let tabBarBannerHeight: CGFloat = 150
private var selectedCategoryIndex: Int = 0
private var settingsDetailVC: BMDetailSettingsViewController?
private var categoryNames: [String] = [String]()
private var categoryOptions: [String] = [String]()
// MARK: - View Lifecycle Methods
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
categoryNames = BMCategory.allValues
categoryOptions = BMUserSettings.shared.currOptionsSelected.map { $0.value }
self.tableview.reloadData()
}
override func viewWillDisappear(_ animated: Bool)
{
BMUserSettings.shared.saveToUserDefaults()
}
override func loadView()
{
super.loadView()
self.tableview.dataSource = self
self.tableview.delegate = self
self.tableview.register(BMUserSettingsCell.self, forCellReuseIdentifier: BMSettingsViewController.reuseIdentifier)
displayContent()
}
// MARK: - Custom Methods
private func displayContent()
{
view.addSubview(tableview)
tableview.anchor(
top: self.view.topAnchor,
leading: self.view.leadingAnchor,
bottom: self.view.bottomAnchor,
trailing: self.view.trailingAnchor,
padding: UIEdgeInsets(top: tabBarBannerHeight, left: 0, bottom: 0, right: 0)
)
}
}
// MARK: - UITableView Datasource & Delegate Extension
extension BMSettingsViewController: UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
{
return "Select an option below to configure it's settings..."
}
func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return categoryNames.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: BMSettingsViewController.reuseIdentifier, for: indexPath) as! BMUserSettingsCell
cell.configureCell(categoryName: categoryNames[indexPath.row], optionDetailDescription: categoryOptions[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let selectedCategory = categoryNames[indexPath.row]
settingsDetailVC = BMDetailSettingsViewController()
guard let settingsVC = settingsDetailVC else {return}
settingsVC.options = BMUserSettings.shared.options[BMCategory.init(rawValue: selectedCategory)!]!
settingsVC.delegate = self
settingsVC.selectedCategoryIndex = indexPath.row
BMViewControllerManager.shared.getTopViewController()?.present(settingsVC, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 120
}
}
// MARK: - Protocol Extension
extension BMSettingsViewController: OptionsSelector
{
func didFinishSelectingOption(selectedCategoryIndex: Int, selectedOptionIndex: Int)
{
self.selectedCategoryIndex = selectedCategoryIndex
// BMUserSettings.shared.currOptionsSelected[self.selectedCategoryIndex] = selectedOptionIndex
}
}
以下是设置详细信息控制器,其中仅列出了该特定类别中的选项:
import UIKit
// MARK: - Protocol (used to notify Settings view controller when an option was selected)
protocol OptionsSelector
{
func didFinishSelectingOption(selectedCategoryIndex: Int, selectedOptionIndex: Int)
}
final class BMDetailSettingsViewController: UIViewController
{
// MARK: - Instance Variables
private let cellId = "cellId"
private let tabBarBannerHeight: CGFloat = 150
private var selectedOptionIndex: Int = 0
private let tableview = UITableView(backgroundColor: .white, autoResizingMask: false)
var options: [String] = [String]()
var selectedCategoryIndex: Int = 0
var delegate: OptionsSelector?
// MARK: - View Life Cycle Methods
override func loadView()
{
super.loadView()
self.tableview.dataSource = self
self.tableview.delegate = self
self.tableview.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
displayContent()
}
// MARK: - Custom Methods
private func displayContent()
{
view.addSubview(tableview)
tableview.anchor(
top: self.view.topAnchor,
leading: self.view.leadingAnchor,
bottom: self.view.bottomAnchor,
trailing: self.view.trailingAnchor,
padding: UIEdgeInsets(top: tabBarBannerHeight, left: 0, bottom: 0, right: 0)
)
}
}
// MARK: - UITableView Datasource & Delegate Extension
extension BMDetailSettingsViewController: UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return "Select an option below..." }
func numberOfSections(in tableView: UITableView) -> Int { return 1 }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return options.count }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
cell.textLabel?.text = "\(options[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
BMViewControllerManager.shared.getTopViewController()?.dismiss(animated: true)
self.selectedOptionIndex = indexPath.row
self.delegate?.didFinishSelectingOption(selectedCategoryIndex: self.selectedCategoryIndex, selectedOptionIndex: self.selectedOptionIndex)
}
}
谢谢!
【问题讨论】:
-
将
currOptionsSelected设为字符串数组,以便您立即了解类别。更好的是,让它成为一个集合,而不是一个数组。更好的是,将类别定义为枚举。 -
你能告诉我你的意思吗?
-
数组
options是干什么用的? -
options 包含每个类别的单独选项。这是一个多维数组...
-
这样你就可以解决 2) 我可能会转向字典结构。
var options = [OptionsKey, [String]]。我会做一个enum OptionsKey: String { case brandOptionsGroup, environmentOptionsGroup, etc}。访问该字典类似于let array = options[.brandOptionsGroup]添加另一个类别不会成为问题。
标签: ios arrays swift uitableview multidimensional-array