如何根据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 附件复选标记的状态

Swift - 多个 TableView 复选标记 - 保存和加载选择

swift 3中的静态关键字

表视图复选标记