首页 > 解决方案 > 如何在 Swift 4 中实现条件到 UITableViewDataSource

问题描述

我正在使用 Swift 4 创建一个 iOS 应用程序,而不是尝试使用 Alamofire 从外部 API 获取数据,然后使用 Swifty JSON 将这些数据转换为 JSON 并在 UIViewTable 中呈现给用户。我想根据 API 发送的数据类型添加条件(如 if 或 swift 语句)以使用不同类型的数据结构。

我有多个 swift 文件,一个用于 API 请求,另一个用于函数,一个用于 UITableCell 结构声明。

我想在 NotificationsViewController 中添加一个 if o switch 语句,而不是可以获得一种 API 响应。在 createCells 函数中,我得到了通知的类型,因此我可以将必要的数据设置到响应中。此代码已获取数据并将其放入自定义类型 NotificationData 的二维数组中。问题是当我想根据二维数组中的通知类型添加不同类型的自定义单元格时。

* NotificationsViewController * 项目主画面的文件


class NotificationsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    private let request = GetNotificationsRequest()
    private let functions = Functions()

    (...)

    var cells: [[NotificationData]] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let urlToExecute = URL(string: functions.generateUrl(stage: "dev", parameters: "appnotification/notificatios/\(idAssociation!)/\(idUser!)/10/1", side: "inside")) else {
            return
        }
        request.execute(urlToExecute, user: userName as! String, pass: userPassword as! String) { (json, noItems, statusCode, error) in
            print(urlToExecute)
            if let error = error {
                print("Ha ocurrido un error.\n\(error)")
            }
            else {
                //--------------------------- Se ha realizado el llamado
                self.cells = self.functions.createCells(json: json!, noItems: noItems!)
                print(type(of: self.cells))
                // Output: Array<Array<NotificationData>>
                print(self.cells.count)
                // Output: 10
            }
        }        
    }

    //I WANT TO ADD THE IF OR SWITCH STATEMENT HERE BUT XCODE GETS AN ERROR


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        print("Hay \(cells.count) celdas.")
        return cells.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //for index in 0..<cells.count {
            //switch cells[index][indexPath.row].typeLabel {
            //case "Score":
        let cell = tableView.dequeueReusableCell(withIdentifier: "ScoreCell") as! ScoreCell
        cell.fullNameLabel.text = cells[indexPath.row][indexPath.row].fullNameLabel
        cell.agoLabel.text = cells[indexPath.row][indexPath.row].agoLabel
        cell.sisLabel.text = cells[indexPath.row][indexPath.row].sisLabel
        cell.rcLabel.text = cells[indexPath.row][indexPath.row].rcLabel
        cell.soLabel.text = cells[indexPath.row][indexPath.row].soLabel
        cell.oLabel.text = cells[indexPath.row][indexPath.row].oLabel
        cell.diaLabel.text = cells[indexPath.row][indexPath.row].diaLabel
        cell.tempLabel.text = cells[indexPath.row][indexPath.row].tempLabel
        cell.respLabel.text = cells[indexPath.row][indexPath.row].respLabel
        cell.avpuLabel.text = cells[indexPath.row][indexPath.row].avpuLabel
        cell.scoreLabel.text = cells[indexPath.row][indexPath.row].scoreLabel
        print(cell)
        return cell
        //}
    }
}

* GetNotifications() 函数 * 该函数比使用 Alamofire 从 API 获取数据

    let functions = Functions()
    typealias WebServiceResponse = (JSON?, Int?, Int?, Error?) -> Void
    //Definición del método llamado execute() que realiza la sequest
    func execute(_ url:URL,user: String, pass: String, completion: @escaping WebServiceResponse) {
        //Definición de headers y credenciales para realizar la request
        let usr = "\(user)"
        //let usr = "USER"
        let pass = "\(pass)"
        //let pass = "PASSWORD"
        let parameters: Parameters = [:]
        let credentialsData = "\(usr):\(pass)".data(using: String.Encoding.utf8)!
        let codCredentials = credentialsData.base64EncodedString(options: [])
        let headers = [
            "Authorization": "Basic \(codCredentials)"
        ]

        //Definición del tipo de request, envío de headers para la autenticación y establecimiento de reglas de validación
        Alamofire.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: headers) .validate(statusCode: 200..<300) .responseJSON { response in
            let statusCode = response.response?.statusCode
            print(headers)
            print(usr)
            print(pass)
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                let noItems = json["notifications"].count
                completion(json, noItems, statusCode, nil)
                print("Se ejecutó el llamado correctamente. Contiene \(noItems) ítems.")
            case .failure(let error):
                completion(nil, nil, statusCode, error)
                print("Ha ocurrido un error al ejecutar el llamado")
                print(error)
            }
        }
    }
}

* createCells() 函数 * 获取 API 数据 json(在 Swifty JSON 中)并使用 NotificationData 结构转换为二维数组并将其保存在 arrayNotifications 中的函数

func createCells(json: JSON, noItems: Int) -> Array<Array<NotificationData>> {

        var arrayNotifications = [[NotificationData]]()
        for index in 0..<noItems {
            var type = json["notifications"][index]["idnotification_type"].rawString()!
            var notification = [NotificationData]()

            switch type {
            case "1":
                print("Ingreso")
                type = "Ingreso"
                var ago = ""
                let agoWithoutFormat = json["notifications"][index]["detail"]["start"].rawString()!
                print(agoWithoutFormat)
                var fullName = json["notifications"][index]["detail"]["name"].rawString()!; fullName += " "; fullName += json["notifications"][index]["detail"]["lastname"].rawString()!
                let reason = json["notifications"][index]["detail"]["reason_for_admission"].rawString()!
                let room = json["notifications"][index]["detail"]["room"].rawString()!
                let floor = json["notifications"][index]["detail"]["floor"].rawString()!
                let timeStart = json["notifications"][index]["detail"]["start"].rawString()!

                let dateFormatterGet = DateFormatter()
                dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ssZZZZZ"
                //according to date format your date string
                if let date = dateFormatterGet.date(from: agoWithoutFormat) {
                    ago = date.self.timeAgoDisplay()
                    print(ago)
                } else {
                    print("Se ha producido un error al codificar la hora")
                    ago = "Hace tiempo."
                }
                // --------- AGREGAR notificación al array
                notification = [NotificationData(typeLabel: type, agoLabel: ago, fullNameLabel: fullName, sisLabel: "", diaLabel: "", rcLabel: "", tempLabel: "", soLabel: "", respLabel: "", oLabel: "", avpuLabel: "", scoreLabel: "", reasonLabel: reason, roomLabel: room, floorLabel: floor, timeStartLabel: timeStart, dateStartLabel: "", timeEndLabel: "", dateEndLabel: "")]
                arrayNotifications.append(notification)
            case "2":
                print("Egreso")

            case "3":
                print("Score")
                type = "Score"
                var ago = ""
                let agoWithoutFormat = json["notifications"][index]["detail"]["time"].rawString()!
                //print(agoWithoutFormat)
                var fullName = json["notifications"][index]["detail"]["name"].rawString()!; fullName += " "; fullName += json["notifications"][index]["detail"]["lastname"].rawString()!
                let sis = json["notifications"][index]["detail"]["detail"]["sistolica"].rawString()!
                let dia = json["notifications"][index]["detail"]["detail"]["diastolica"].rawString()!
                let rc = json["notifications"][index]["detail"]["detail"]["ritmocardiaco"].rawString()!
                let temp = json["notifications"][index]["detail"]["detail"]["temperatura"].rawString()!
                let so = json["notifications"][index]["detail"]["detail"]["saturaciondeoxigeno"].rawString()!
                let resp = json["notifications"][index]["detail"]["detail"]["respiracionesxminuto"].rawString()!
                let o = json["notifications"][index]["detail"]["detail"]["oxigenosuplementario"].rawString()!
                let avpu = json["notifications"][index]["detail"]["detail"]["avpu"].rawString()!
                let score = json["notifications"][index]["detail"]["total"].rawString()!
                //let score = json["notifications"][index]["detail"]["detail"]["avpu"].rawString()!
                let dateFormatterGet = DateFormatter()
                dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
                //according to date format your date string
                if let date = dateFormatterGet.date(from: agoWithoutFormat) {
                    ago = date.self.timeAgoDisplay()
                    print(ago)
                } else {
                    print("Se ha producido un error al codificar la hora")
                    ago = "Hace tiempo."
                }
                notification = [NotificationData(typeLabel: type, agoLabel: ago, fullNameLabel: fullName, sisLabel: sis, diaLabel: dia, rcLabel: rc, tempLabel: temp, soLabel: so, respLabel: resp, oLabel: o, avpuLabel: avpu, scoreLabel: score, reasonLabel: "", roomLabel: "", floorLabel: "", timeStartLabel: "", dateStartLabel: "", timeEndLabel: "", dateEndLabel: "")]
                arrayNotifications.append(notification)
                //print(notification)
            case "4":
                print("Recordatorio de Score")

            case "5":
                print("Deterioro fisiológico")

            default:
                print("Ha ocurrido un error al crear la celda.")

            }
        }
        //print(arrayNotifications)
        return arrayNotifications
    }
}

* NotificationData * NotificationData 的结构

struct NotificationData {
    var typeLabel: String
    var agoLabel: String
    var fullNameLabel: String
    var sisLabel: String
    var diaLabel: String
    var rcLabel: String
    var tempLabel: String
    var soLabel: String
    var respLabel: String
    var oLabel: String
    var avpuLabel: String
    var scoreLabel: String
    var reasonLabel: String
    var roomLabel: String
    var floorLabel: String
    var timeStartLabel: String
    var dateStartLabel: String
    var timeEndLabel: String
    var dateEndLabel: String
}

* ScoreCell * 一个自定义的 UITableViewCell 比定义一个分数原型单元格

class ScoreCell: UITableViewCell {
    @IBOutlet weak var typeLabel: UILabel!
    @IBOutlet weak var agoLabel: UILabel!
    @IBOutlet weak var fullNameLabel: UILabel!
    @IBOutlet weak var sisLabel: UILabel!
    @IBOutlet weak var diaLabel: UILabel!
    @IBOutlet weak var rcLabel: UILabel!
    @IBOutlet weak var tempLabel: UILabel!
    @IBOutlet weak var soLabel: UILabel!
    @IBOutlet weak var respLabel: UILabel!
    @IBOutlet weak var oLabel: UILabel!
    @IBOutlet weak var avpuLabel: UILabel!
    @IBOutlet weak var scoreLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

* IngressCell * 一个自定义的 UITableViewCell,它定义了一个 Ingress 原型单元

class IngressCell: UITableViewCell {
    @IBOutlet weak var reasonLabel: UILabel!
    @IBOutlet weak var agoLabel: UILabel!
    @IBOutlet weak var patientNameLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UITextView!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

我尝试在 NotificationsViewController 中添加 if 或 switch 语句来获取通知的类型,例如如果类型为 3,则类型为分数,因此我必须使用名为 ScoreCell 的原型单元格,let cell = tableView.dequeueReusableCell(withIdentifier: "ScoreCell") as! ScoreCell但如果类型为 1,该类型是 Ingress,因此它必须更改为let cell = tableView.dequeueReusableCell(withIdentifier: "IngressCell") as! IngressCell并使用 Ingress 原型单元。当我尝试在 ViewController 中添加这些条件时,xcode 会标记一个错误。在 NotificationsViewController 中包含尝试过的代码作为注释。你能帮助我吗?

标签: iosswiftalamofirealexaalexa-skills-kit

解决方案


使用具有一个要求的协议

protocol NotificationData {
    var type : String { get }
}

然后使用不同的结构并仅声明属于该结构的成员,例如

struct Ingreso : NotificationData {
   let type : String

   let room : String
   let floor : String

   // other members 
}

struct Egreso : NotificationData {
   let type : String

   // other members
}

struct Score : NotificationData {
   let type : String

   let sis: String
   let dia: String
   // other members
}

根据createCells类型创建不同的结构并分配type.

不清楚您是否真的需要二维数组,简单的解决方案是将一维数组声明为协议类型并按以下方式对数组进行排序type

var cells = [NotificationData]()

cellForRow打开type,获取项目并将其转换为实际的静态类型以访问结构成员

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

    let item = cells[indexPath.row]
    switch item.type {
       case "Score":
           let cell = tableView.dequeueReusableCell(withIdentifier: "ScoreCell", for: indexPath) as! ScoreCell
           let score = item as! Score

           // assign values to the UI
           return cell

        case "Ingreso":
           let cell = tableView.dequeueReusableCell(withIdentifier: "IngresoCell", for: indexPath) as! IngresoCell
           let ingreso = item as! Ingreso

           // assign values to the UI
           return cell

        case "Egreso":
           let cell = tableView.dequeueReusableCell(withIdentifier: "EgresoCell", for: indexPath) as! EgresoCell
           let egreso = item as! Egreso

           // assign values to the UI
           return cell

        // and so on

推荐阅读