how to make checkmark to be selected depending on

2019-03-01 00:28发布

I am having array in which selected name will be stored and passed to before view controller and when ever i need to go previous view controller then the previously selected check mark needs to be selected but here it is enabling the last selected element only the problem is if i select three then it is not selecting three it is check marking only the last element but i need the three selected can anyone help me how to make the check mark to be selected for three elements ?

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

1条回答
Explosion°爆炸
2楼-- · 2019-03-01 00:54

Basically do not manipulate the view (the cell). Use a data model.

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
    }
}

And never use multiple arrays as data source . That's a very bad habit.

Declare the data source array as

var products = [Product]()

Parse the JSON data and do a (better) error handling

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()
}

in cellForRow... assign the name to the label and set the checkmark depending on 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
}

In didSelect... toggle selected and reload the row

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selected = products[indexPath.row].selected
    products[indexPath.row].selected = !selected
    tableView.reloadRows(at: [indexPath], with: .none)
}

To get all selected items is very easy, too.

let selectedItems = products.filter{ $0.selected }

or get only the names

let selectedNames = products.filter{ $0.selected }.map{ $0.name }

There is no need at all to get any information from the view. The controller gets the information always from the model and uses tableview data source and delegate to update the view.

If you want to pass data to another view controller pass Product instances. They contain all relevant information.

查看更多
登录 后发表回答