简体   繁体   中英

Checking if cells are selected or not when button is pressed swift

UI照片

In this photo as you can see user can turn on or off the switch for each cell. At the end when the user presses the button I need to add the selected cell (the cells that have a switch on) to an array to send it to API.

When the user clicks the button (at the bottom of the screen) I should get the unitNo and personId and store them in my struct

My model:

struct Itemm : Codable {
    var unitNo:Int?
    var personId:Int?
}
struct welcome {
    var items : [Itemm?]
}

and I have to send an array like below:

{
  "items": [
    {
      "unitNo": 0,
      "personId": 0
    }
  ]
}

I'm some confused as to how I should access the cell data in UIButton with if statement and then storing them. I would be grateful for any help.

Tableview:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell") as? SmsTableViewCell

    cell?.PhonNumberLbl.text = data![indexPath.section].contacts[indexPath.row]?.phoneNumber
    cell?.NameLbl.text = data![indexPath.section].contacts[indexPath.row]?.name
    cell?.selectedTF.isOn = (data![indexPath.section].contacts[indexPath.row]?.selected)!

    return cell!
}

API response:

 [
    {
        "contacts": [
            {
                "id": 9827,
                "selected": true,
                "phoneNumber": "09203137745",
                "name": "owner"
            },
            {
                "id": 10159,
                "selected": true,
                "phoneNumber": "08523698522",
                "name": "hff"
            },
            {
                "id": 10161,
                "selected": true,
                "phoneNumber": "09586731218",
                "name": "hjdldue"
            }
        ],
        "unitNo": 1,
        "unitPlaque": "jack",
        "billText": "texttext"
    },
    {
        "contacts": [
            {
                "id": 10145,
                "selected": true,
                "phoneNumber": "09123809556",
                "name": "mmm"
            },
            {
                "id": 10160,
                "selected": true,
                "phoneNumber": "85233366888",
                "name": "ttt"
            }
        ],
        "unitNo": 2,
        "unitPlaque": "mm",
        "billText": "texttext"
    }
]

I think I didn't clearly explain what I'm looking for.

The first method I call is a GET method which gives me the data that I'm presenting in the table. The user could only change the switch, the user can change it as many times as they want until he/she presses the button (at the bottom of the screen).

When the button is pressed, I need to get the hidden data behind each cell and store them in my struct and send it to API which has another method. When the user presses the button I need to extract the 2 properties from the cells that has a switch on.

Presenter represents this:

func sendSmsForAllTheMembers(AptId:String , data:[String:Int])
{
    ApiGenerator.request(targetApi: ApartemanService.sendSms(aptId: AptId, data: data), responseModel: Nil.self, success: { (response) in
        if response.response.statusCode == 200 {
            self.view?.SendingSmsSuccess()
        }else {
            do{

                var errorMessage = try response.response.mapString()
                errorMessage = errorMessage.replacingOccurrences(of: "\"", with: "",
                                                                 options: NSString.CompareOptions.literal, range:nil)

                self.view?.SendingSmsFailed(errorMessage: errorMessage)

            }catch let error{
                print(error)
                self.view?.SendingSmsFailed(errorMessage: "error")
            }

        }

    }) { (error) in
        self.view?.SendingSmsFailed(errorMessage: "error")
    }
}

Your first problem is that you need to store the switch state in your view controller somehow; you can't store it in the cell directly since cells are re-used as your table view scrolls.

While you could store the switch state in your model struct, I would probably not do this, as it makes your struct mutable. I would use a Set<IndexPath> to track selections.

Your next problem is knowing when the switch is changed in a cell. You can provide a closure to your UITableviewCell subclass to handle this.

SmsCell

var switchHandler: ((Bool)->Void)?

@IBAction func switchChanged(_ sender: UISwitch) {
    self.switchHandler?(sender.isOn)
}

View Controller

var selectedCells = Set<IndexPath>()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell") as! SmsTableViewCell

    let cellData = self.data![indexPath.section]
    let contact = cellData.contacts[indexPath.row]

    cell.PhonNumberLbl.text = contact.phoneNumber
    cell.NameLbl.text = contact.name
    cell.selectedTF.isOn = self.selectedCells.contains(indexPath)
    cell.switchHandler = { (switchState) in
        if switchState {
            self.selectedCells.insert(indexPath)
        } else {
            self.selectedCells.remove(indexPath)
        }
    }

    return cell
}

Your final task is to create struct that you can encode into the required JSON:

struct Itemm: Codable {
    let unitNo: Int
    let personId: Int
}

struct Welcome: Codable {
    var items:[Itemm]
}

View Controller

@IBAction func sendButtonTapped(_ sender: UIButton) {

   var items = [Itemm]() 
   for indexPath in self.selectedCells {
       let data = self.data![indexPath.section]
       let contact = data.contacts[indexPath.row]
       let newItem = Itemm(unitNo: data.unitNo, personId: contact.id)
       items.append(newItem)
   }
   let welcome = Welcome(items: items)
   // Now you can encode and send welcome
}

ok, as far as i got from what are you trying to do,

1- give the switch tag,

inside the

    func tableView(_ tableView: UITableView, 
      cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      switch.tag = indexPath.row
      switch.addTarget(self, action: #selector(onSwitchValueChanged), for: .touchUpInside)

}

And in the didChange Method of the Switch,

    func onSwitchValueChanged(_ switch: UISwitch) {
       if switch.on {
       selectedArray.append(dataArray[switch.tag])
    } esle {
      selectedArray.remove(at: switch.tag)
}

SmsCell

var switchHandler: ((Bool)->Void)?

@IBAction func switchChanged(_ sender: UISwitch) {
    self.switchHandler?(sender.isOn)
}

View Controller

var selectedCells = Set<IndexPath>()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SmsCell") as! SmsTableViewCell
    let cellData = self.data![indexPath.section]
    let contact = cellData.contacts[indexPath.row]
    cell.PhonNumberLbl.text = contact.phoneNumber
    cell.NameLbl.text = contact.name
    cell.selectedTF.isOn = self.selectedCells.contains(indexPath)
    cell.switchHandler = { (switchState) in
        if switchState {
            self.selectedCells.insert(indexPath)
        } else {
            self.selectedCells.remove(indexPath)
        }
    }
    return cell
}


struct Itemm: Codable {
    let unitNo: Int
    let personId: Int
}

struct Welcome: Codable {
    var items:[Itemm]
}

View Controller

  @IBAction func sendButtonTapped(_ sender: UIButton) {

      var items = [[String:Int]]()
for indexPath in self.selectedCells {
    let data = self.data![indexPath.section]
    let contact = data.contacts[indexPath.row]
    items.append(["Number" : data.unitNo, "ID" : contact!.id])
}
let welcome = ["items" : items]
print(welcome)
Presenter.sendSmsForAllTheMembers(AptId: aptId, data: welcome)
    }

the final answer is a combination of the answer that some people gave me here and some that I found it myself

You can update your Model objects when switch on/off function and also give switch tag as a cell.indexpath .

Update model objects like this Ex :-

if switch == on {

 items[switch_tag].unitNo =0 

} else {

  items[switch_tag].unitNo =1 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM