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.