Как внедрить условное в UITableViewDataSource в Swift 4 - PullRequest
0 голосов
/ 22 мая 2019

Я создаю приложение для iOS с Swift 4, которое пытается получить данные из внешнего API с помощью Alamofire, затем эти данные преобразуются в JSON с помощью Swifty JSON и представляются пользователю в UIViewTable.Я хочу добавить условное выражение (например, if или swift) к использованию различных типов структур данных в соответствии с типом данных, которые отправляет API.

У меня есть несколько быстрых файлов, один для запросов API, другойдля функций и один для объявления структуры UITableCell.

Я хочу добавить оператор if o switch в NotificationsViewController, чем можно получить тип ответа API.В функции createCells я получаю тип уведомлений, поэтому я могу указать в ответе необходимые данные.Этот код уже получает данные и помещает их в 2D-массив с пользовательским типом NotificationData.Проблемы, когда я хочу добавить другой тип пользовательских ячеек в зависимости от типа уведомления в 2D-массиве.

* 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 () * Функция, которая получает данные из API с помощью Alamofire

    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) и преобразует их в 2D-массив, используя структуру 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, который определяет ячейку прототипа Score

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

Я попытался добавить оператор if или switch в NotificationsViewController, чтобы получить тип уведомления, например, если тип3, типом является Score, поэтому я должен использовать ячейку-прототип с именем ScoreCell, используя let cell = tableView.dequeueReusableCell(withIdentifier: "ScoreCell") as! ScoreCell, но если тип равен 1, тип является Ingress, поэтому он должен измениться на let cell = tableView.dequeueReusableCell(withIdentifier: "IngressCell") as! IngressCell и использовать ячейку-прототип Ingress.Когда я пытаюсь добавить эти условия в ViewController, xcode отмечает ошибку.В NotificationsViewController включите пробный код в качестве комментария.Вы можете мне помочь?

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Используйте протокол с одним требованием

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
0 голосов
/ 22 мая 2019

Вам нужно заботиться о cellForRowAt

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

    let typeSection = array[indexPath.row].type

    switch typeSection {
    case .CenterTitleCell:
        return getCenterTitleCell(tableView, indexPath)
    case .CenterDescriptionCell:
        return getCenterDescriptionCell(tableView, indexPath)
    case .CenterImageCell:
        return getImageCell(tableView, indexPath)
    case .FooterTitleCell:
        return getFooterViewCell(tableView, indexPath)
    }
}

, где типом является enum возможного типа объектов

...