如何根据swift 3中的数组选择复选标记?
Posted
技术标签:
【中文标题】如何根据swift 3中的数组选择复选标记?【英文标题】:how to make checkmark to be selected depending on the array in swift 3? 【发布时间】:2017-09-25 04:51:01 【问题描述】:我有一个数组,其中选定的名称将被存储并传递到视图控制器之前,当我需要转到前一个视图控制器时,需要选择先前选择的复选标记,但这里它只启用最后一个选定的元素问题是如果我选择三个然后它不是选择三个它只是检查标记最后一个元素但我需要三个选择任何人都可以帮助我如何为三个元素选择复选标记?
protocol ArrayToPass: class
func selectedArrayToPass(selectedStrings: [String])
class FilterSelectionViewController: UIViewController,UITableViewDataSource,UITableViewDelegate
var productName = [String]()
var productprice = [String]()
var imageArray = [String]()
var idArray = [Int]()
let urlString = "http://www.json-generator.com/api/json/get/bOYOrkiosq?indent=2"
var values = [String]()
var selected: Bool?
var delegate: ArrayToPass?
var nameSelection: Bool?
var namesArray = [String]()
override func viewDidLoad()
super.viewDidLoad()
self.downloadJsonWithURL()
tableDetails.separatorInset = UIEdgeInsets.zero
activityIndicator.startAnimating()
tableDetails.isHidden = true
tableDetails.dataSource = self
tableDetails.delegate = self
let rightBarButton = UIBarButtonItem(title: "Apply", style: UIBarButtonItemStyle.plain, target: self, action: #selector(applyBarButtonActionTapped(_:)))
self.navigationItem.rightBarButtonItem = rightBarButton
tableDetails.estimatedRowHeight = UITableViewAutomaticDimension
tableDetails.rowHeight = 60
// Do any additional setup after loading the view.
func applyBarButtonActionTapped(_ sender:UIBarButtonItem!)
self.delegate?.selectedArrayToPass(selectedStrings: values)
navigationController?.popViewController(animated: true)
func downloadJsonWithURL()
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: (data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSArray
for item in jsonObj!
if let itemDict = item as? NSDictionary
if let name = itemDict.value(forKey: "name")
self.productName.append(name as! String)
if let price = itemDict.value(forKey: "value")
self.productprice.append(price as! String)
if let image = itemDict.value(forKey: "img")
self.imageArray.append(image as! String)
if let id = itemDict.value(forKey: "id")
self.idArray.append(id as! Int)
OperationQueue.main.addOperation(
self.tableDetails.reloadData()
)
).resume()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return productName.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "filterSelectionCell", for: indexPath) as! FilterSelectionCell
activityIndicator.stopAnimating()
activityIndicator.hidesWhenStopped = true
tableDetails.isHidden = false
cell.brandProductName.text = productName[indexPath.row]
if nameSelection == true
if namesArray.count != 0
print(namesArray)
for name in namesArray
if productName[indexPath.row].contains(name)
print(productName[indexPath.row])
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
selected = false
if let cell = tableView.cellForRow(at: indexPath as IndexPath)
if cell.accessoryType == .checkmark
cell.accessoryType = .none
print("\(productName[indexPath.row])")
values = values.filter$0 != "\(productName[indexPath.row])"
selected = true
else
cell.accessoryType = .checkmark
if selected == true
print(values)
else
getAllTextFromTableView()
print(values)
func getAllTextFromTableView()
guard let indexPaths = self.tableDetails.indexPathsForSelectedRows else // if no selected cells just return
return
for indexPath in indexPaths
values.append(productName[indexPath.row])
here is the image for this
【问题讨论】:
如何将数组发送回第一个视图控制器? 我正在使用协议将数据传递给另一个视图控制器@AravindAR 这里当我从第一个视图控制器返回到上一个时,我需要勾选之前选择的复选框,以便选择其他更多品牌@AravindAR 发回数据后是否重新加载表? 这里需要重新加载表格视图吗? @Tj3n 【参考方案1】:基本上不操作视图(单元格)。使用数据模型。
struct Product
let name : String
let value : String
let img : String
let id : Int
var selected = false
init(dict : [String:Any])
self.name = dict["name"] as? String ?? ""
self.value = dict["value"] as? String ?? ""
self.img = dict["img"] as? String ?? ""
self.id = dict["id"] as? Int ?? 0
并且永远不要使用多个数组作为数据源。这是一个非常坏的习惯。
将数据源数组声明为
var products = [Product]()
解析 JSON 数据并进行(更好的)错误处理
func downloadJsonWithURL()
let url = URL(string: urlString)!
let task = URLSession.shared.dataTask(with: url) (data, response, error) in
if error != nil print(error!); return
do
if let jsonObj = try JSONSerialization.jsonObject(with: data!) as? [[String:Any]]
self.products = jsonObj.map Product(dict: $0)
DispatchQueue.main.async
self.tableDetails.reloadData()
catch
print(error)
task.resume()
在cellForRow...
中将名称分配给标签并根据selected
设置复选标记
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "filterSelectionCell", for: indexPath)
let product = products[indexPath.row]
cell.textLabel!.text = product.name
cell.accessoryType = product.selected ? .checkmark : .none
return cell
在didSelect...
切换selected
并重新加载行
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let selected = products[indexPath.row].selected
products[indexPath.row].selected = !selected
tableView.reloadRows(at: [indexPath], with: .none)
获取所有选定的项目也很容易。
let selectedItems = products.filter $0.selected
或只获取名称
let selectedNames = products.filter $0.selected .map $0.name
根本不需要从视图获取任何信息。 controller 总是从 model 获取信息,并使用 tableview 数据源和委托来更新 view。
如果您想将数据传递给另一个视图控制器,请传递 Product
实例。它们包含所有相关信息。
【讨论】:
从模型中获取数据很好,但首先我需要将整个数据发送到表视图,我将在其中选择一些数据,但这里的数组是空的,如选择后提到的那样,数据将正如你所说的对象数组,在数组中 你的设计很繁琐。不要使用像namesArray
这样的临时数组。你可以用模型做任何事情。 cellForRow
仅用于更新 UI,仅此而已。
无论你说什么都很好,但作为实习生,我无法完全理解,但我明白,永远不要用视图来管理一切,试着用你说的模型类来管理@Vadian
如果可能,您能否提供一个示例项目,该项目使用不在视图中的模型进行管理@vadian
答案中的代码包含所有组件。这很简单。而不是 productName
([String]
) 使用模型并创建数据源数组,其中模型的初始化程序传递字符串。将单元格标识符替换为您的标识符。以上是关于如何根据swift 3中的数组选择复选标记?的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中保存 UITableViewCell 复选标记选择
添加/删除 UITableView 选择到数组,复选标记在滚动时消失 - Swift
如何在 Swift 3 中保存 UITableViewCell 附件复选标记的状态