我的桌子表现得很奇怪。我的桌子上有4行。
我第一次访问该表格时,didSelectRowAt
使用1个标签,但是当我前后点击8次左右(进出)时,最后4次需要2个标签。
这就是我所拥有的
import UIKit
import SwiftyJSON
class AddDevicesViewController: UIViewController {
@IBOutlet weak var addDeviceTable: UITableView!
@IBOutlet weak var doneButton: UIButton!
@IBOutlet weak var doneButtonWidth: NSLayoutConstraint!
var profile: Profile?
var devices: [Device] = []
var selectedDevices: [Device] = []
var showOnlyProfileDevices: Bool = false
var deviceStartList = [String]()
var selectedIndexPath : IndexPath!
var disableBackNavigation : Bool = false
var selectedRow : Int = 0
var mode : String = "addDevice"
var radioOff : UIImageView {
let imageSize = Constants.IS_SMALLSCREEN ? 25 : 30
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: imageSize, height: imageSize))
imgView.clipsToBounds = true
imgView.image = UIImage(named: "radio_off")
return imgView
}
var radioOn : UIImageView {
let imageSize = Constants.IS_SMALLSCREEN ? 25 : 30
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: imageSize, height: imageSize))
imgView.clipsToBounds = true
imgView.contentMode = .scaleToFill
imgView.image = UIImage(named: "ok")
imgView.tintColor = UIColor.blue
return imgView
}
override func viewDidLoad() {
super.viewDidLoad()
let backIndicator = UIBarButtonItem(image: UIImage(named: "backArrow"), style: UIBarButtonItem.Style.plain, target: self, action: #selector(goBack))
backIndicator.tintColor = UIColor.white
self.navigationItem.leftBarButtonItem = backIndicator
addDeviceTable.delegate = self
addDeviceTable.dataSource = self
//Add rounded corner to Done button
if Constants.IS_SMALLSCREEN {
doneButtonWidth.constant = 200
}
doneButton.layer.cornerRadius = 5.0
//Add target action for Done button
doneButton.addTarget(self, action: #selector(donePressed), for: .touchUpInside)
addDeviceTable.refreshControl = UIRefreshControl()
addDeviceTable.refreshControl?.addTarget(self, action: #selector(refreshData), for: .valueChanged)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.title = self.title
self.tabBarItem.title = "Profile"
if !showOnlyProfileDevices {
self.navigationItem.title = "Add device to \((profile?.name)!)"
} else {
self.navigationItem.title = "\((profile?.name)!)'s devices"
}
doneButton.isHidden = showOnlyProfileDevices
//Disable back navigation when new profile is added and this screen is shown
self.navigationItem.leftBarButtonItem?.isEnabled = !disableBackNavigation
selectedDevices.removeAll()
profile?.assignedDevices.forEach { (device) in
if !isDeviceQuarantined(device.mac ?? "") {
selectedDevices.append(device)
}
}
for index in 0..<(selectedDevices.count) {
deviceStartList.append(selectedDevices[index].mac!)
}
}
@objc func goBack(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
func loadDeviceNamesAndACL() {
devices.forEach { (device) in
APIService.shared.getDeviceName(cpe: (loginAccount.cpe?.mac)!, vlan: "100", mac: device.mac!, caller: self)
APIService.shared.getCpeDeviceACL(cpe: (loginAccount.cpe?.mac)!, vlan: "100", device: device.mac!, caller: self)
}
}
@objc func refreshData() {
let id = self.profile?.id
let cpe = self.profile?.cpe
if !showOnlyProfileDevices {
APIService.shared.cpeDevices(cpe: cpe!, caller: self)
} else {
APIService.shared.profileDevices(cpe: cpe!,profileId: id!, caller: self)
}
}
@objc func donePressed(_ sender: Any) {
//Move back to Profile Detail.
if !showOnlyProfileDevices {
profile?.assignedDevices = selectedDevices
}
var deviceEndList = [String]()
for index in 0..<(selectedDevices.count) {
deviceEndList.append(selectedDevices[index].mac!)
}
//Delete if uncheck
for index in 0..<(self.deviceStartList.count) {
if deviceEndList.contains(deviceStartList[index]){
}else {
let id = self.profile?.id
let cpe = self.profile?.cpe
let deviceMac = deviceStartList[index]
APIService.shared.removeDeviceFromProfile(cpe: cpe!,profileId: id!, deviceMac: deviceMac, caller: self)
}
}
for index in 0..<(selectedDevices.count) {
let id = self.profile?.id
let cpe = self.profile?.cpe
let deviceMac = selectedDevices[index].mac
APIService.shared.addDeviceToProfile(cpe: cpe!,profileId: id!, deviceMac: deviceMac!, caller: self)
}
navigationController?.popToRootViewController(animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDeviceDetail" {
let destVC = segue.destination as! DeviceDetailViewController
if let _ = addDeviceTable.indexPathForSelectedRow {
destVC.device = devices[selectedRow]
}
}
}
}
extension AddDevicesViewController : UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return devices.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "devicecell", for: indexPath) as! DeviceTableViewCell
let device = devices[indexPath.row]
cell.rowNumber = indexPath.row
if device.access ?? false {
cell.playpauseButton?.setImage(UIImage(named: "play"), for: .normal)
} else {
cell.playpauseButton?.setImage(UIImage(named: "pause"), for: .normal)
}
cell.playpauseButton?.isEnabled = true
cell.delegate = self
cell.deviceName?.text = getDeviceName(device: device)
cell.deviceMAC?.text = device.status?.ip
if device.status?.state == "active" {
cell.deviceStatus?.setImage(UIImage(named: "greendot"), for: .normal)
} else {
cell.deviceStatus?.setImage(UIImage(named: "reddot"), for: .normal)
}
cell.deviceStatus.layer.cornerRadius = 5.0
let deviceImageName = getDeviceIcon(device)
cell.deviceImageView?.image = UIImage(named: deviceImageName!)
if !showOnlyProfileDevices {
if let image = getProfileImage(device: device) {
cell.profileImageView.image = image
cell.profileImageView.isHidden = false
} else {
cell.profileImageView.isHidden = true
}
} else {
cell.profileImageView.isHidden = true
}
if !showOnlyProfileDevices {
let assignedDevices = profile?.assignedDevices
let matchingIndex = assignedDevices?.index(where: { (thisDevice) -> Bool in
return thisDevice.mac == device.mac
})
cell.isSelected = (matchingIndex != nil)
cell.accessoryView = cell.isSelected ? radioOn : radioOff
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as? DeviceTableViewCell
selectedRow = indexPath.row
consoleLog("Click")
if !showOnlyProfileDevices {
cell?.accessoryView = radioOn
cell?.isSelected = true
cell?.profileImageView.image = profileImages[profile?.name ?? "Unknown"]
cell?.profileImageView.isHidden = false
//Add to the list
let device = devices[indexPath.row]
if selectedDevices.index(where: { (dev) -> Bool in
return dev.mac == device.mac
}) != nil {
//Don't add again
} else {
selectedDevices.append(device)
}
} else {
performSegue(withIdentifier: "showDeviceDetail", sender: self)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as? DeviceTableViewCell
if !showOnlyProfileDevices {
cell?.accessoryView = radioOff
cell?.isSelected = false
//Remove from list
let device = devices[indexPath.row]
if let image = getProfileImage(device: device) {
if cell?.profileImageView.image == image {
cell?.profileImageView.image = nil
cell?.profileImageView.isHidden = true
} else {
cell?.profileImageView.image = image
cell?.profileImageView.isHidden = false
}
} else {
cell?.profileImageView.isHidden = true
}
if let index = selectedDevices.index(where: { (dev) -> Bool in
return device.mac == device.mac
}) {
selectedDevices.remove(at: index)
}
} else {
cell?.profileImageView.isHidden = true
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
var configuration : UISwipeActionsConfiguration!
let deleteAction = self.contextualDeleteAction(forRowAtIndexPath: indexPath)
let editAction = self.contextualEditAction(forRowAtIndexPath: indexPath)
if showOnlyProfileDevices {
configuration = UISwipeActionsConfiguration(actions: [deleteAction, editAction])
} else {
configuration = UISwipeActionsConfiguration(actions: [])
configuration.performsFirstActionWithFullSwipe = false
}
return configuration
}
func contextualDeleteAction(forRowAtIndexPath: IndexPath) -> UIContextualAction {
selectedIndexPath = forRowAtIndexPath
let action = UIContextualAction(style: .normal, title: "Delete") { (contextAction: UIContextualAction, sourceView: UIView, completionHandler: (Bool) -> Void) in
let alertController = UIAlertController(title: "Warning", message: "Delete this device?", preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (UIAlertAction) in
//Call API Service to delete device from Profile
let deviceMac = self.devices[self.selectedIndexPath.row].mac
self.devices.remove(at: self.selectedIndexPath.row)
APIService.shared.deleteDeviceFromNetwork(cpe: (loginAccount.cpe?.mac)!, vlan: "100", deviceMac: deviceMac ?? "", caller: self)
OperationQueue.main.addOperation {
self.addDeviceTable.reloadData()
}
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: { (UIAlertAction) in
self.addDeviceTable.reloadData()
}))
self.present(alertController, animated: true)
}
action.backgroundColor = .red
return action
}
func contextualEditAction(forRowAtIndexPath: IndexPath) -> UIContextualAction {
selectedIndexPath = forRowAtIndexPath
let cpe = loginAccount.cpe?.mac ?? ""
let deviceMac = devices[selectedIndexPath.row].mac ?? ""
let deviceOldName = getDeviceName(device: devices[selectedIndexPath.row])
var deviceNewName : String?
let action = UIContextualAction(style: .normal, title: "Edit") { (contextAction: UIContextualAction, sourceView: UIView, completionHandler: (Bool) -> Void) in
let alertController = UIAlertController(title: "Edit Device Name", message: "", preferredStyle: UIAlertController.Style.alert)
alertController.addTextField(configurationHandler: { (deviceName) in
deviceName.text = deviceOldName
})
alertController.addAction(UIAlertAction(title: "Save", style: UIAlertAction.Style.default, handler: { (UIAlertAction) in
deviceNewName = alertController.textFields?[0].text ?? deviceOldName
if (deviceNewName != deviceOldName) || (deviceNewName != "") {
self.devices[self.selectedIndexPath.row].deviceName = deviceNewName
//Call API Service to rename the device
APIService.shared.updateDeviceName(cpe: cpe, vlan: "100", mac: deviceMac, name: deviceNewName!, caller: self)
OperationQueue.main.addOperation {
self.addDeviceTable.reloadData()
}
}
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: { (UIAlertAction) in
self.addDeviceTable.reloadData()
}))
self.present(alertController, animated: true)
}
action.backgroundColor = .blue
return action
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return Constants.IS_SMALLSCREEN ? 68 : 80
}
}
extension AddDevicesViewController: DeviceTableViewCellDelegate {
func updateACL(_ row : Int, _ flag : Bool) {
if devices[row].status?.state == "active" {
devices[row].access = flag
}
let cpe = (loginAccount.cpe?.mac)!
let deviceMac = devices[row].mac
let vlan = "100"
addDeviceTable.reloadRows(at: [IndexPath(row: row, section: 0)], with: .none)
APIService.shared.updateCpeDeviceACL(cpe: cpe,vlan: vlan, device: deviceMac!, portalUrl: "", acl: flag, caller: self)
}
}
extension AddDevicesViewController : APIServiceCallbackDelegate {
func processData(_ reqParams: [String: Any], _ data: Data?, _ response: URLResponse?, _ error: Error?) {
OperationQueue.main.addOperation {
self.addDeviceTable.refreshControl?.endRefreshing()
}
if error != nil {
OperationQueue.main.addOperation {
print("Error: ", error.debugDescription)
if self.addDeviceTable.refreshControl?.isRefreshing == true {
self.addDeviceTable.refreshControl?.endRefreshing()
}
}
return
}
let json = JSON(data as Any)
if !checkHttpResponse(response) {
if let msg = json["message"].string {
OperationQueue.main.addOperation {
print("Message: ", msg)
if self.addDeviceTable.refreshControl?.isRefreshing == true {
self.addDeviceTable.refreshControl?.endRefreshing()
}
}
}
} else {
let reqType = reqParams["reqType"] as! RequestType
switch reqType {
case .addDeviceToProfile:
print("Added Device to Profile successfully")
case .removeDeviceFromProfile:
print("Removed Device from Profile successfully")
case .deleteDeviceFromNetwork:
print("Removed Device from Network successfully")
case .cpeDevices:
loginAccount.cpeDevices = parseCpeDevices(json)
devices.removeAll()
loginAccount.cpeDevices.forEach { (device) in
devices.append(device)
}
OperationQueue.main.addOperation {
self.loadDeviceNamesAndACL()
}
case .profileDevices:
profile?.assignedDevices = parseProfileDevices(json)
devices.removeAll()
profile?.assignedDevices.forEach({ (device) in
devices.append(device)
})
OperationQueue.main.addOperation {
self.loadDeviceNamesAndACL()
}
case .getDeviceName:
let deviceMac = reqParams["mac"] as! String
let name = json["name"].string
if let index = devices.firstIndex(where: { (dev) -> Bool in
return dev.mac == deviceMac
}) {
devices[index].deviceName = name
OperationQueue.main.addOperation {
self.addDeviceTable.reloadData()
}
}
case .getCpeDeviceACL:
let access = parseCpeDeviceACL(json)
if let index = devices.index(where: { (device) -> Bool in
return device.mac == (reqParams["device"] as! String)
}) {
devices[index].access = access
OperationQueue.main.addOperation {
self.addDeviceTable.reloadData()
}
}
case .updateCpeDeviceACL:
let _ = parseCpeDeviceACL(json)
default:
break
}
}
}
}
我在做什么我应该避免的事情?