skip to Main Content

i am facing a very strange bug in my tableView. When changing the row height, the content gets mixed up very strangely (see the GIF).
enter image description here

Here is the code for my tableView, I think I have all labels, imageViews etc. properly resetted at the beginning. I added the Task @ MainAnchor method but it didnt change anything.

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "detailVerbindungTableViewCell", for: indexPath) as! detailVerbindungTableViewCell
    Task { @MainActor in
        
        for view in cell.contentView.subviews {
            if let label = view as? LineHalfTriangleView {
                label.removeFromSuperview()
            }
        }
        for view in cell.sideLineView.subviews {
            cell.sideLineView.willRemoveSubview(view)
        }
        
        var arrayIndex = indexPath.row / 2
        print(arrayIndex)
        let middleSeperator = UIView(frame: CGRect(x: 0, y: cell.contentView.frame.height / 2, width: cell.contentView.frame.width, height: 1))
        middleSeperator.backgroundColor = UIColor.systemBlue
        var sideLineType = "end"
        let timeFormatHHMM = DateFormatter()
        timeFormatHHMM.timeStyle = .short
        var sideColor = UIColor.clear
        var sideTopColor = UIColor.clear
        var sideBottomColor = UIColor.clear
        cell.devLabel.text = "(arrayIndex)"
        cell.devLabel.isHidden = !UserDefaults.standard.bool(forKey: "devDetailVerbIndex")
        cell.lineNumberLabel.text = ""
        cell.lineNumberLabel.textColor = .label
        cell.lineNumberLabel.backgroundColor = .clear
        
        cell.destinationLabel.text = ""
        cell.timeBottomLabel.text = ""
        cell.timeMiddleLabel.text = ""
        cell.timeTopLabel.text = ""
        cell.constDestToNumber.constant = 8
        cell.constDestToStrich.constant = 58
        cell.constDestToNumber.isActive = true
        cell.destinationLabel.font = UIFont.systemFont(ofSize: cell.destinationLabel.font.pointSize)
        cell.timeTopLabel.textColor = UIColor.label
        cell.timeMiddleLabel.textColor = UIColor.label
        cell.timeBottomLabel.textColor = UIColor.label
        
        if indexPath.row % 2 == 0 {
            //Location cell
            cell.contentView.backgroundColor = UIColor.systemBackground
            cell.constDestToNumber.isActive = false
            cell.constDestToStrich.constant = 8
            cell.destinationLabel.font = UIFont.systemFont(ofSize: cell.destinationLabel.font.pointSize, weight: .semibold)
            if arrayIndex == resultLegArray[selectedIndex][0].count {
                cell.destinationLabel.text = resultLegArray[selectedIndex][0].last?.arrival.name
            } else {
                cell.destinationLabel.text = resultLegArray[selectedIndex][0][arrayIndex].departure.name
            }
            if arrayIndex == resultLegArray[selectedIndex][0].count {
                //Location cell
                //Show Time
                //Last cell
                sideLineType = "end"
                cell.timeTopLabel.isHidden = true
                cell.timeMiddleLabel.isHidden = false
                cell.timeBottomLabel.isHidden = true
                if resultLegArray[selectedIndex][0].last is PublicLeg {
                    print("PublicLeg")
                    var tempPublicLeg = resultLegArray[selectedIndex][0].last as! PublicLeg
                    if tempPublicLeg.arrivalTime == tempPublicLeg.plannedArrivalTime {
                        cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.plannedArrivalTime)
                        cell.timeMiddleLabel.textColor = UIColor.systemGreen
                    } else {
                        let timeDifference = tempPublicLeg.plannedArrivalTime.distance(to: tempPublicLeg.arrivalTime )
                        cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.arrivalTime)
                        cell.timeMiddleLabel.textColor = UIColor.systemRed
                        if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                            cell.timeMiddleLabel.textColor = UIColor.systemBlue
                        }
                    }
                    sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                } else {
                    print("IndividualLeg")
                    var tempIndLeg = resultLegArray[selectedIndex][0].last as! IndividualLeg
                    cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempIndLeg.arrivalTime)
                    cell.timeMiddleLabel.textColor = UIColor.label
                    sideColor = UIColor.lightGray
                }
            } else {
                //Not last cell
                //Location cell
                //Show Time
                if arrayIndex == 0 {
                    sideLineType = "start"
                    cell.timeTopLabel.isHidden = true
                    cell.timeMiddleLabel.isHidden = false
                    cell.timeBottomLabel.isHidden = true
                    if resultLegArray[selectedIndex][0].first?.departureTime == resultLegArray[selectedIndex][0].first?.plannedDepartureTime {
                        cell.timeMiddleLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0].first!.plannedDepartureTime)
                        cell.timeMiddleLabel.textColor = UIColor.systemGreen
                    } else {
                        let timeDifference = resultLegArray[selectedIndex][0].first?.plannedDepartureTime.distance(to: (resultLegArray[selectedIndex][0].first?.departureTime ?? resultLegArray[selectedIndex][0].first?.plannedDepartureTime)!)
                        cell.timeMiddleLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0].first!.departureTime)
                        cell.timeMiddleLabel.textColor = UIColor.systemRed
                        if timeDifference?.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                            cell.timeMiddleLabel.textColor = UIColor.systemBlue
                        }
                    }
                    //MARK: Location middle Side Color
                    if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                        print("PublicLeg")
                        var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
                        sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                    } else {
                        print("IndividualLeg")
                        var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                        sideColor = UIColor.lightGray
                    }
                } else {//MARK: sideLineType Middle
                    sideLineType = "middle"
                    cell.timeTopLabel.isHidden = false
                    cell.timeMiddleLabel.isHidden = true
                    cell.timeBottomLabel.isHidden = false
                    if resultLegArray[selectedIndex][0][arrayIndex].departureTime == resultLegArray[selectedIndex][0][arrayIndex].plannedDepartureTime {
                        cell.timeBottomLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex].departureTime)
                        cell.timeBottomLabel.textColor = UIColor.systemGreen
                    } else {
                        let timeDifference = resultLegArray[selectedIndex][0][arrayIndex].plannedDepartureTime.distance(to: resultLegArray[selectedIndex][0][arrayIndex].departureTime )
                        cell.timeBottomLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex].departureTime)
                        cell.timeBottomLabel.textColor = UIColor.systemRed
                        if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                            cell.timeBottomLabel.textColor = UIColor.systemBlue
                        }
                    }
                    if resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime == resultLegArray[selectedIndex][0][arrayIndex-1].plannedArrivalTime {
                        cell.timeTopLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime)
                        cell.timeTopLabel.textColor = UIColor.systemGreen
                    } else {
                        let timeDifference = resultLegArray[selectedIndex][0][arrayIndex-1].plannedArrivalTime.distance(to: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime )
                        cell.timeTopLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime)
                        cell.timeTopLabel.textColor = UIColor.systemRed
                        if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                            cell.timeTopLabel.textColor = UIColor.systemBlue
                        }
                    }
                    if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                        print("PublicLeg")
                        var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
                        sideBottomColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                    } else {
                        print("IndividualLeg")
                        var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                        sideBottomColor = UIColor.lightGray
                    }
                    if resultLegArray[selectedIndex][0][arrayIndex-1] is PublicLeg { //Line before current
                        print("PublicLeg")
                        var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex-1] as! PublicLeg
                        sideTopColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                    } else {
                        print("IndividualLeg")
                        var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex-1] as! IndividualLeg
                        sideTopColor = UIColor.lightGray
                    }
                }
            }
            
            //Even index
        } else {
            //Info cell
            cell.timeTopLabel.isHidden = true
            cell.timeMiddleLabel.isHidden = true
            cell.timeBottomLabel.isHidden = true
            sideLineType = "static"
            cell.backgroundColor = UIColor.systemBackground
            if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                //Fahrzeug
                print("PublicLeg")
                var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
                cell.lineNumberLabel.text = tempPublicLeg.line.label ?? ""
                cell.destinationLabel.text = tempPublicLeg.destination?.name
                if tempPublicLeg.line.style.backgroundColor2 == nil || tempPublicLeg.line.style.backgroundColor2 == 0 {
                    
                    cell.lineNumberLabel.backgroundColorC = tempPublicLeg.line.style.backgroundColor
                } else {
                    cell.lineNumberLabel.backgroundColorC = UInt32(UIColor.clear.hexa)
                    let backgroundLineHalfHalf = LineHalfTriangleView(frame: cell.lineNumberLabel.frame)
                    backgroundLineHalfHalf.topColor = tempPublicLeg.line.style.backgroundColor
                    backgroundLineHalfHalf.bottomColor = tempPublicLeg.line.style.backgroundColor2
                    backgroundLineHalfHalf.borderColor = tempPublicLeg.line.style.borderColor
                    cell.contentView.addSubview(backgroundLineHalfHalf)
                    cell.contentView.sendSubviewToBack(backgroundLineHalfHalf)
                }
                cell.lineNumberLabel.foregroundColor = tempPublicLeg.line.style.foregroundColor
                cell.lineNumberLabel.roundCorners(corners: .allCorners, radius: 0)
                //MARK: Info PublicLeg Time
                if tempPublicLeg.departureTime == tempPublicLeg.plannedDepartureTime {
                } else {
                    let timeDifference = tempPublicLeg.plannedDepartureTime.distance(to: tempPublicLeg.departureTime )
                    cell.timeTopLabel.text = timeDifference.stringFromTimeIntervalWithText()
                    cell.timeTopLabel.textColor = UIColor.systemRed
                    cell.timeTopLabel.isHidden = false
                    cell.timeTopLabel.text = "+ (timeDifference.stringFromTimeIntervalOnlyNumber())"
                    if cell.timeTopLabel.text?.contains("-") == true {
                        cell.timeTopLabel.text = cell.timeTopLabel.text?.replacingOccurrences(of: "+ ", with: "")
                        cell.timeTopLabel.text = cell.timeTopLabel.text?.replacingOccurrences(of: "-", with: "- ")
                        cell.timeTopLabel.textColor = UIColor.systemBlue
                    }
                }
                if tempPublicLeg.arrivalTime == tempPublicLeg.plannedArrivalTime {
                } else {
                    let timeDifference = tempPublicLeg.plannedArrivalTime.distance(to: tempPublicLeg.arrivalTime )
                    cell.timeBottomLabel.text = timeDifference.stringFromTimeIntervalWithText()
                    cell.timeBottomLabel.textColor = UIColor.systemRed
                    cell.timeBottomLabel.isHidden = false
                    cell.timeBottomLabel.text = "+ (timeDifference.stringFromTimeIntervalOnlyNumber())"
                    if cell.timeBottomLabel.text?.contains("-") == true {
                        cell.timeBottomLabel.text = cell.timeBottomLabel.text?.replacingOccurrences(of: "+ ", with: "")
                        cell.timeBottomLabel.text = cell.timeBottomLabel.text?.replacingOccurrences(of: "-", with: "- ")
                        cell.timeBottomLabel.textColor = UIColor.systemBlue
                    }
                }
                if cell.timeTopLabel.text == cell.timeBottomLabel.text {
                    cell.timeTopLabel.isHidden = true
                    cell.timeBottomLabel.isHidden = true
                    cell.timeMiddleLabel.isHidden = false
                    cell.timeMiddleLabel.text = cell.timeTopLabel.text
                    cell.timeMiddleLabel.textColor = cell.timeTopLabel.textColor
                }
                sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                cell.lineNumberLabel.shape = tempPublicLeg.line.style.shape
                
                
                
                //Expandable Cell
                
                let intermediateTableView = UITableView(frame: CGRect(x: 0, y: cell.frame.height, width: cell.frame.width, height: 30))
                intermediateTableView.register(detailVerbindungIntermediateStopTableViewCell.self, forCellReuseIdentifier: "detailVerbindungIntermediateStopTableViewCell")
                intermediateTableView.dataSource = cell
                intermediateTableView.delegate = cell
                cell.contentView.addSubview(intermediateTableView)
                
                
                
                
                
                
                
                
                
            } else {
                //Walk
                print("IndividualLeg")
                var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                cell.destinationLabel.text = "Fußweg: (tempIndLeg.departure.getDistanceText(CLLocation(latitude: CLLocationDegrees(tempIndLeg.arrival.coord?.lat ?? 0)/1000000, longitude: CLLocationDegrees(tempIndLeg.arrival.coord?.lon ?? 0)/1000000)))"
                let config = UIImage.SymbolConfiguration(paletteColors: [.label, .lightGray])
                let walkIconImgView = UIImageView(frame: CGRect(x: 96, y: 24, width: 42, height: 42))
                walkIconImgView.contentMode = .scaleAspectFit
                walkIconImgView.image = UIImage(systemName: "figure.walk.diamond")!.applyingSymbolConfiguration(config)
                cell.addSubview(walkIconImgView)
                walkIconImgView.isHidden = true
                let imageAttachment = NSTextAttachment()
                imageAttachment.image = UIImage(systemName: "figure.walk", withConfiguration: config)
                let fullString = NSMutableAttributedString(string: "")
                fullString.append(NSAttributedString(attachment: imageAttachment))
                cell.lineNumberLabel.attributedText = fullString
                sideColor = UIColor.lightGray
            }
        }
        
        switch sideLineType {
        case "middle": // ⎡ Comes from bottom to top
            // Create the ⏐ UIView
            let leftView = UIView()
            leftView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 + 7, width: 6, height: cell.sideLineView.frame.height / 2)
            leftView.backgroundColor = sideBottomColor
            // Create the ⎯ UIView
            let rightView = UIView()
            rightView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 + 7, width: cell.sideLineView.frame.width, height: 6)
            rightView.backgroundColor = sideBottomColor
            // Add the subviews to the container view
            cell.sideLineView.addSubview(leftView)
            cell.sideLineView.addSubview(rightView)
            // ⎣ Comes from top to bottom
            // Create the ⏐ UIView
            let topLeftView = UIView()
            topLeftView.frame = CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height / 2 - 11)
            topLeftView.backgroundColor = sideTopColor
            // Create the ⎯ UIView
            let topRightView = UIView()
            topRightView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 11, width: cell.sideLineView.frame.width, height: 6)
            topRightView.backgroundColor = sideTopColor
            // Add the subviews to the container view
            cell.sideLineView.addSubview(topLeftView)
            cell.sideLineView.addSubview(topRightView)
        case "start": // ⎡
            let sideLineMainView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: 6, height: cell.sideLineView.frame.height))
            sideLineMainView.backgroundColor = sideColor
            cell.sideLineView.addSubview(sideLineMainView)
            let sideLineSideView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: cell.sideLineView.frame.width, height: 6))
            sideLineSideView.backgroundColor = sideColor
            cell.sideLineView.addSubview(sideLineSideView)
        case "end": // ⎣
            let sideLineMainView = UIView(frame: CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height / 2 + 3))
            sideLineMainView.backgroundColor = sideColor
            cell.sideLineView.addSubview(sideLineMainView)
            let sideLineSideView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: cell.sideLineView.frame.width, height: 6))
            sideLineSideView.backgroundColor = sideColor
            cell.sideLineView.addSubview(sideLineSideView)
        case "static": // ⎥
            let sideLineMainView = UIView(frame: CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height))
            sideLineMainView.backgroundColor = sideColor
            cell.sideLineView.addSubview(sideLineMainView)
            
        default: break
        }
    }
        return cell
    
}

And with the following method, I change the height:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if expandedRowIndex == indexPath.row {
            expandedRowIndex = -1
            shouldExpanded = false
        } else {
            expandedRowIndex = indexPath.row
            shouldExpanded = true
        }
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }


    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == expandedRowIndex && shouldExpanded == true {
            return 91 //Expanded
        }
        return 71 //Not expanded
    }

Thanks in advance and sorry for my bad English 😉

2

Answers


  1. Chosen as BEST ANSWER

    Update:

    Thank you very much for you comments, I appreciate it! To the last comment, this is how my cells should look like/look now: enter image description here

    The data I get comes from a private API Server of the Deutsche Bahn. I've updated my code and now this is my cellForRowAt method:

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "detailVerbindungTableViewCell", for: indexPath) as! detailVerbindungTableViewCell
        Task { @MainActor in
            
            for view in cell.contentView.subviews {
                if let label = view as? LineHalfTriangleView {
                    label.removeFromSuperview()
                }
            }
            for view in cell.sideLineView.subviews {
                cell.sideLineView.willRemoveSubview(view)
            }
            
            var arrayIndex = indexPath.row / 2
            print(arrayIndex)
            let middleSeperator = UIView(frame: CGRect(x: 0, y: cell.contentView.frame.height / 2, width: cell.contentView.frame.width, height: 1))
            middleSeperator.backgroundColor = UIColor.systemBlue
            var sideLineType = "end"
            var sideColor = UIColor.clear
            var sideTopColor = UIColor.clear
            var sideBottomColor = UIColor.clear
            cell.devLabel.text = "(arrayIndex)"
            cell.devLabel.isHidden = !UserDefaults.standard.bool(forKey: "devDetailVerbIndex")
            cell.lineNumberLabel.text = ""
            cell.lineNumberLabel.textColor = .label
            cell.lineNumberLabel.backgroundColor = .clear
            cell.intermediateStops.removeAll()
            cell.destinationLabel.text = ""
            cell.timeBottomLabel.text = ""
            cell.timeMiddleLabel.text = ""
            cell.timeTopLabel.text = ""
            cell.constDestToNumber.constant = 8
            cell.constDestToStrich.constant = 58
            cell.constDestToNumber.isActive = true
            cell.destinationLabel.font = UIFont.systemFont(ofSize: cell.destinationLabel.font.pointSize)
            cell.timeTopLabel.textColor = UIColor.label
            cell.timeMiddleLabel.textColor = UIColor.label
            cell.timeBottomLabel.textColor = UIColor.label
            
            if indexPath.row % 2 == 0 {
                //Location cell
                cell.contentView.backgroundColor = UIColor.systemBackground
                cell.constDestToNumber.isActive = false
                cell.constDestToStrich.constant = 8
                cell.destinationLabel.font = UIFont.systemFont(ofSize: cell.destinationLabel.font.pointSize, weight: .semibold)
                if arrayIndex == resultLegArray[selectedIndex][0].count {
                    cell.destinationLabel.text = resultLegArray[selectedIndex][0].last?.arrival.name
                } else {
                    cell.destinationLabel.text = resultLegArray[selectedIndex][0][arrayIndex].departure.name
                }
                if arrayIndex == resultLegArray[selectedIndex][0].count {
                    //Location cell
                    //Show Time
                    //Last cell
                    sideLineType = "end"
                    cell.timeTopLabel.isHidden = true
                    cell.timeMiddleLabel.isHidden = false
                    cell.timeBottomLabel.isHidden = true
                    if resultLegArray[selectedIndex][0].last is PublicLeg {
                        print("PublicLeg")
                        var tempPublicLeg = resultLegArray[selectedIndex][0].last as! PublicLeg
                        if tempPublicLeg.arrivalStop.predictedTime == nil {
                            cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.plannedArrivalTime)
                            cell.timeMiddleLabel.textColor = UIColor.label
                        } else if tempPublicLeg.arrivalStop.plannedTime == tempPublicLeg.arrivalStop.predictedTime {
                            cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.plannedArrivalTime)
                            cell.timeMiddleLabel.textColor = UIColor.systemGreen
                        } else {
                            let timeDifference = tempPublicLeg.plannedArrivalTime.distance(to: tempPublicLeg.arrivalTime )
                            cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.arrivalTime)
                            cell.timeMiddleLabel.textColor = UIColor.systemRed
                            if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                                cell.timeMiddleLabel.textColor = UIColor.systemBlue
                            }
                        }
                        
                        sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                    } else {
                        print("IndividualLeg")
                        var tempIndLeg = resultLegArray[selectedIndex][0].last as! IndividualLeg
                        cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempIndLeg.arrivalTime)
                        cell.timeMiddleLabel.textColor = UIColor.label
                        sideColor = UIColor.lightGray
                    }
                } else {
                    //Not last cell (here is first and every other cell)
                    //Location cell
                    //Show Time
                    if arrayIndex == 0 {
                        //first cell
                        sideLineType = "start"
                        cell.timeTopLabel.isHidden = true
                        cell.timeMiddleLabel.isHidden = false
                        cell.timeBottomLabel.isHidden = true
                        if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                            print("PublicLeg")
                            var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
                            if tempPublicLeg.departureStop.predictedTime == nil {
                                cell.timeMiddleLabel.textColor = .label
                                cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.plannedTime)
                            } else if tempPublicLeg.departureStop.plannedTime == tempPublicLeg.departureStop.predictedTime {
                                cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.predictedTime!)
                                cell.timeMiddleLabel.textColor = UIColor.systemGreen
                            } else {
                                let timeDifference = tempPublicLeg.departureStop.plannedTime.distance(to: (tempPublicLeg.departureStop.predictedTime ?? tempPublicLeg.departureStop.plannedTime)!)
                                cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.predictedTime!)
                                cell.timeMiddleLabel.textColor = UIColor.systemRed
                                if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                                    cell.timeMiddleLabel.textColor = UIColor.systemBlue
                                }
                            }
                            sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                        } else {
                            print("IndividualLeg")
                            var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                            sideColor = UIColor.lightGray
                            cell.timeMiddleLabel.text = timeFormatHHMM.string(from: tempIndLeg.departureTime)
                            cell.timeMiddleLabel.textColor = UIColor.label
                        }
                    } else {//MARK: sideLineType Middle eg. every cell besiddes first and last
                        sideLineType = "middle"
                        cell.timeTopLabel.isHidden = false
                        cell.timeMiddleLabel.isHidden = true
                        cell.timeBottomLabel.isHidden = false
                        
                        if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                            print("PublicLeg")
                            var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
    
                            if tempPublicLeg.departureStop.predictedTime == nil {
                                cell.timeBottomLabel.textColor = .label
                                cell.timeBottomLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.plannedTime)
                            } else if tempPublicLeg.departureStop.plannedTime == tempPublicLeg.departureStop.predictedTime {
                                cell.timeBottomLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.predictedTime!)
                            cell.timeBottomLabel.textColor = UIColor.systemGreen
                        } else {
                            let timeDifference = tempPublicLeg.departureStop.plannedTime.distance(to: tempPublicLeg.departureStop.predictedTime! )
                            cell.timeBottomLabel.text = timeFormatHHMM.string(from: tempPublicLeg.departureStop.predictedTime!)
                            cell.timeBottomLabel.textColor = UIColor.systemRed
                            if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                                cell.timeBottomLabel.textColor = UIColor.systemBlue
                            }
                        }
                            sideBottomColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                        } else {
                            print("IndividualLeg")
                            var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                            sideBottomColor = UIColor.lightGray
                            cell.timeBottomLabel.text = timeFormatHHMM.string(from: tempIndLeg.departureTime)
                            cell.timeBottomLabel.textColor = UIColor.label
                        }
                        
                        
                        if resultLegArray[selectedIndex][0][arrayIndex-1] is PublicLeg { //Line before current
                            print("PublicLeg")
                            var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex-1] as! PublicLeg
                            sideTopColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                            if tempPublicLeg.arrivalStop.predictedTime == nil {
                                cell.timeTopLabel.textColor = .label
                                cell.timeTopLabel.text = timeFormatHHMM.string(from: tempPublicLeg.arrivalStop.plannedTime)
                            } else if tempPublicLeg.arrivalStop.plannedTime == tempPublicLeg.arrivalStop.predictedTime {
                            cell.timeTopLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime)
                            cell.timeTopLabel.textColor = UIColor.systemGreen
                        } else {
                            let timeDifference = resultLegArray[selectedIndex][0][arrayIndex-1].plannedArrivalTime.distance(to: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime )
                            cell.timeTopLabel.text = timeFormatHHMM.string(from: resultLegArray[selectedIndex][0][arrayIndex-1].arrivalTime)
                            cell.timeTopLabel.textColor = UIColor.systemRed
                            if timeDifference.stringFromTimeIntervalOnlyNumber().contains("-") == true {
                                cell.timeTopLabel.textColor = UIColor.systemBlue
                            }
                        }
                        } else {
                            print("IndividualLeg")
                            var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex-1] as! IndividualLeg
                            sideTopColor = UIColor.lightGray
                            cell.timeTopLabel.text = timeFormatHHMM.string(from: tempIndLeg.arrivalTime)
                            cell.timeTopLabel.textColor = UIColor.label
                        }
                    }
                }
                
                //Even index
            } else {
                //Info cell (Vehicle or Walk)
                cell.timeTopLabel.isHidden = true
                cell.timeMiddleLabel.isHidden = true
                cell.timeBottomLabel.isHidden = true
                sideLineType = "static"
                cell.backgroundColor = UIColor.systemBackground
                if resultLegArray[selectedIndex][0][arrayIndex] is PublicLeg {
                    //Fahrzeug
                    print("PublicLeg")
                    var tempPublicLeg = resultLegArray[selectedIndex][0][arrayIndex] as! PublicLeg
                    cell.lineNumberLabel.text = tempPublicLeg.line.label ?? ""
                    cell.destinationLabel.text = tempPublicLeg.destination?.name
                    if tempPublicLeg.line.style.backgroundColor2 == nil || tempPublicLeg.line.style.backgroundColor2 == 0 {
                        
                        cell.lineNumberLabel.backgroundColorC = tempPublicLeg.line.style.backgroundColor
                    } else {
                        cell.lineNumberLabel.backgroundColorC = UInt32(UIColor.clear.hexa)
                        let backgroundLineHalfHalf = LineHalfTriangleView(frame: cell.lineNumberLabel.frame)
                        backgroundLineHalfHalf.topColor = tempPublicLeg.line.style.backgroundColor
                        backgroundLineHalfHalf.bottomColor = tempPublicLeg.line.style.backgroundColor2
                        backgroundLineHalfHalf.borderColor = tempPublicLeg.line.style.borderColor
                        cell.contentView.addSubview(backgroundLineHalfHalf)
                        cell.contentView.sendSubviewToBack(backgroundLineHalfHalf)
                    }
                    cell.lineNumberLabel.foregroundColor = tempPublicLeg.line.style.foregroundColor
                    cell.lineNumberLabel.roundCorners(corners: .allCorners, radius: 0)
                    //MARK: Info PublicLeg Time
                    if tempPublicLeg.departureTime == tempPublicLeg.plannedDepartureTime {
                        
                    } else {
                        let timeDifference = tempPublicLeg.plannedDepartureTime.distance(to: tempPublicLeg.departureTime )
                        cell.timeTopLabel.text = timeDifference.stringFromTimeIntervalWithText()
                        cell.timeTopLabel.textColor = UIColor.systemRed
                        cell.timeTopLabel.isHidden = false
                        cell.timeTopLabel.text = "+ (timeDifference.stringFromTimeIntervalOnlyNumber())"
                        if cell.timeTopLabel.text?.contains("-") == true {
                            cell.timeTopLabel.text = cell.timeTopLabel.text?.replacingOccurrences(of: "+ ", with: "")
                            cell.timeTopLabel.text = cell.timeTopLabel.text?.replacingOccurrences(of: "-", with: "- ")
                            cell.timeTopLabel.textColor = UIColor.systemBlue
                        }
                    }
                    if tempPublicLeg.arrivalTime == tempPublicLeg.plannedArrivalTime {
                    } else {
                        let timeDifference = tempPublicLeg.plannedArrivalTime.distance(to: tempPublicLeg.arrivalTime )
                        cell.timeBottomLabel.text = timeDifference.stringFromTimeIntervalWithText()
                        cell.timeBottomLabel.textColor = UIColor.systemRed
                        cell.timeBottomLabel.isHidden = false
                        cell.timeBottomLabel.text = "+ (timeDifference.stringFromTimeIntervalOnlyNumber())"
                        if cell.timeBottomLabel.text?.contains("-") == true {
                            cell.timeBottomLabel.text = cell.timeBottomLabel.text?.replacingOccurrences(of: "+ ", with: "")
                            cell.timeBottomLabel.text = cell.timeBottomLabel.text?.replacingOccurrences(of: "-", with: "- ")
                            cell.timeBottomLabel.textColor = UIColor.systemBlue
                        }
                    }
                    if cell.timeTopLabel.text == cell.timeBottomLabel.text {
                        cell.timeTopLabel.isHidden = true
                        cell.timeBottomLabel.isHidden = true
                        cell.timeMiddleLabel.isHidden = false
                        cell.timeMiddleLabel.text = cell.timeTopLabel.text
                        cell.timeMiddleLabel.textColor = cell.timeTopLabel.textColor
                    }
                    sideColor = UIColor(argb: tempPublicLeg.line.style.backgroundColor)
                    cell.lineNumberLabel.shape = tempPublicLeg.line.style.shape
                    
                    
                    
                    //Expandable Cell
                    
                    let intermediateTableView = detailVerbindungIntermediateStopsTableView(frame: CGRect(x: 0, y: cell.frame.height, width: cell.frame.width, height: .zero))
                    intermediateTableView.translatesAutoresizingMaskIntoConstraints = false
                    intermediateTableView.register(detailVerbindungIntermediateStopTableViewCell.self, forCellReuseIdentifier: "detailVerbindungIntermediateStopTableViewCell")
                    intermediateTableView.dataSource = cell
                    intermediateTableView.delegate = cell
                    intermediateTableView.estimatedRowHeight = 20
                    intermediateTableView.rowHeight = 20
                    intermediateTableView.separatorInset.left = 96
                    cell.contentView.addSubview(intermediateTableView)
                    cell.intermediateStops = tempPublicLeg.intermediateStops
                    cell.sideColor = sideColor
                    
                    let bottomConstraint = NSLayoutConstraint(item: intermediateTableView, attribute: .top, relatedBy: .equal, toItem: cell.destinationLabel, attribute: .bottom, multiplier: 1.0, constant: 0)
                    let leadingConstraint = NSLayoutConstraint(item: intermediateTableView, attribute: .leading, relatedBy: .equal, toItem: cell.contentView, attribute: .leading, multiplier: 1.0, constant: 0)
                    let trailingConstraint = NSLayoutConstraint(item: intermediateTableView, attribute: .trailing, relatedBy: .equal, toItem: cell.contentView, attribute: .trailing, multiplier: 1.0, constant: 0)
                    let heightConstraint = NSLayoutConstraint(item: intermediateTableView, attribute: .height, relatedBy: .greaterThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 20)
                    cell.contentView.addConstraints([bottomConstraint, leadingConstraint, trailingConstraint, heightConstraint])
                    
                    
                } else {
                    //Walk
                    print("IndividualLeg")
                    var tempIndLeg = resultLegArray[selectedIndex][0][arrayIndex] as! IndividualLeg
                    cell.destinationLabel.text = "Fußweg: (tempIndLeg.departure.getDistanceText(CLLocation(latitude: CLLocationDegrees(tempIndLeg.arrival.coord?.lat ?? 0)/1000000, longitude: CLLocationDegrees(tempIndLeg.arrival.coord?.lon ?? 0)/1000000)))"
                    let config = UIImage.SymbolConfiguration(paletteColors: [.label, .lightGray])
                    let walkIconImgView = UIImageView(frame: CGRect(x: 96, y: 24, width: 42, height: 42))
                    walkIconImgView.contentMode = .scaleAspectFit
                    walkIconImgView.image = UIImage(systemName: "figure.walk.diamond")!.applyingSymbolConfiguration(config)
                    cell.addSubview(walkIconImgView)
                    walkIconImgView.isHidden = true
                    let imageAttachment = NSTextAttachment()
                    imageAttachment.image = UIImage(systemName: "figure.walk", withConfiguration: config)
                    let fullString = NSMutableAttributedString(string: "")
                    fullString.append(NSAttributedString(attachment: imageAttachment))
                    cell.lineNumberLabel.attributedText = fullString
                    sideColor = UIColor.lightGray
                }
            }
            
            switch sideLineType {
            case "middle": // ⎡ Comes from bottom to top
                // Create the ⏐ UIView
                let leftView = UIView()
                leftView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 + 7, width: 6, height: cell.sideLineView.frame.height / 2)
                leftView.backgroundColor = sideBottomColor
                // Create the ⎯ UIView
                let rightView = UIView()
                rightView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 + 7, width: cell.sideLineView.frame.width, height: 6)
                rightView.backgroundColor = sideBottomColor
                // Add the subviews to the container view
                cell.sideLineView.addSubview(leftView)
                cell.sideLineView.addSubview(rightView)
                // ⎣ Comes from top to bottom
                // Create the ⏐ UIView
                let topLeftView = UIView()
                topLeftView.frame = CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height / 2 - 11)
                topLeftView.backgroundColor = sideTopColor
                // Create the ⎯ UIView
                let topRightView = UIView()
                topRightView.frame = CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 11, width: cell.sideLineView.frame.width, height: 6)
                topRightView.backgroundColor = sideTopColor
                // Add the subviews to the container view
                cell.sideLineView.addSubview(topLeftView)
                cell.sideLineView.addSubview(topRightView)
            case "start": // ⎡
                let sideLineMainView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: 6, height: cell.sideLineView.frame.height))
                sideLineMainView.backgroundColor = sideColor
                cell.sideLineView.addSubview(sideLineMainView)
                let sideLineSideView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: cell.sideLineView.frame.width, height: 6))
                sideLineSideView.backgroundColor = sideColor
                cell.sideLineView.addSubview(sideLineSideView)
            case "end": // ⎣
                let sideLineMainView = UIView(frame: CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height / 2 + 3))
                sideLineMainView.backgroundColor = sideColor
                cell.sideLineView.addSubview(sideLineMainView)
                let sideLineSideView = UIView(frame: CGRect(x: 0, y: cell.sideLineView.frame.height / 2 - 3, width: cell.sideLineView.frame.width, height: 6))
                sideLineSideView.backgroundColor = sideColor
                cell.sideLineView.addSubview(sideLineSideView)
            case "static": // ⎥
                let sideLineMainView = UIView(frame: CGRect(x: 0, y: 0, width: 6, height: cell.sideLineView.frame.height))
                sideLineMainView.backgroundColor = sideColor
                cell.sideLineView.addSubview(sideLineMainView)
                
            default: break
            }
        }
        return cell
        
    }
    

    This is my didSelectRowAt method:

        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row / 2 >= resultLegArray[selectedIndex][0].count {
            return
        }
        
        if resultLegArray[selectedIndex][0][indexPath.row / 2] is PublicLeg && indexPath.row % 2 != 0 {
            if expandedRowIndex == indexPath.row {
                expandedRowIndex = -1
            } else {
                expandedRowIndex = indexPath.row
            }
            tableView.reloadRows(at: [indexPath], with: .automatic)
        } else {
            tableView.deselectRow(at: indexPath, animated: false)
        }
    }
    

    And this my custom tableView Cell that is displayed inside the main cells:

        func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 20
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 20
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return intermediateStops.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "detailVerbindungIntermediateStopTableViewCell", for: indexPath) as! detailVerbindungIntermediateStopTableViewCell
        cell.stopLabel.text = intermediateStops[indexPath.row].location.name
        if let time = intermediateStops[indexPath.row].departure?.time {
            cell.timeLabel.text = timeFormatHHMM.string(from: time)
        } else {
            cell.timeLabel.text = ""
        }
        let sideLineMainView = UIView(frame: CGRect(x: 0, y: 0, width: 6, height: 20))
        sideLineMainView.backgroundColor = sideColor
        cell.lineImageView.addSubview(sideLineMainView)
        cell.rightLabel.isHidden = true
        
        if intermediateStops[indexPath.row].departure?.predictedTime == nil {
            //Keine Live
            cell.timeLabel.textColor = UIColor.label
            if let time = intermediateStops[indexPath.row].departure?.plannedTime {
                cell.timeLabel.text = timeFormatHHMM.string(from: time)
            } else {
                cell.timeLabel.text = ""
            }        } else {
            //Live
            if intermediateStops[indexPath.row].departure?.predictedTime == intermediateStops[indexPath.row].departure?.plannedTime {
                //Pünktlich
                cell.timeLabel.textColor = UIColor.systemGreen
                cell.timeLabel.text = timeFormatHHMM.string(from: intermediateStops[indexPath.row].departure!.plannedTime)
            } else {
                //Außerfahrplanmäßige Zeit
                let timeDifference = intermediateStops[indexPath.row].departure?.predictedTime?.timeIntervalSince(intermediateStops[indexPath.row].departure!.plannedTime)
                
                let delayAttString = NSMutableAttributedString()
                var delayString = NSAttributedString()
                var timeString = NSAttributedString()
                let firstKlammer = NSAttributedString(string: "(", attributes: [NSAttributedString.Key.foregroundColor: UIColor.label])
                let secondKlammer = NSAttributedString(string: ")", attributes: [NSAttributedString.Key.foregroundColor: UIColor.label])
                if timeDifference!.stringFromTimeIntervalWithText().contains("-") {
                    delayString = NSAttributedString(string: timeDifference!.stringFromTimeIntervalOnlyNumber(), attributes: [NSAttributedString.Key.foregroundColor: UIColor.systemBlue])
                    timeString = NSAttributedString(string: timeFormatHHMM.string(from: (intermediateStops[indexPath.row].departure?.predictedTime)!), attributes: [NSAttributedString.Key.foregroundColor: UIColor.systemBlue])
                    cell.timeLabel.textColor = .systemBlue
                } else {
                    delayString = NSAttributedString(string: "+(timeDifference!.stringFromTimeIntervalOnlyNumber())", attributes: [NSAttributedString.Key.foregroundColor: UIColor.systemRed])
                    timeString = NSAttributedString(string: timeFormatHHMM.string(from: (intermediateStops[indexPath.row].departure?.predictedTime)!), attributes: [NSAttributedString.Key.foregroundColor: UIColor.systemRed])
                    cell.timeLabel.textColor = .systemRed
                }
                delayAttString.append(firstKlammer)
                delayAttString.append(delayString)
                delayAttString.append(secondKlammer)
                cell.timeLabel.text = timeFormatHHMM.string(from: (intermediateStops[indexPath.row].departure?.predictedTime)!)
                cell.rightLabel.isHidden = false
                cell.rightLabel.attributedText = delayAttString
                
                
            }
        }
        
        
        return cell
    }
    

    Sorry for that much code, I appreciate your help and hope I gave you the right information. Thanks!


  2. We’re missing a lot of information – data structures, sample data, etc. – so I can’t copy/paste/run your code to figure out exactly what’s wrong.

    However, I would strongly suggest:

    • process your data in your data structure (calculating time differences, etc)
    • put your "cell layout" code inside your cell class(es), not inside cellForRowAt
    • don’t add/remove subviews inside cellForRowAt
    • use auto-layout / constraints rather than calculating sizes

    and, what I think would really help you…

    • use multiple cell classes

    For example, instead of ONE cell class that needs add/remove subviews for every instance, use four classes (I don’t know what your ultimate needs will be, so you might need more). I’ve added vertical space between the cells to make it clear:

    enter image description here

    Now, in each cell’s init process, create and layout only the UI elements that cell will need.

    Then, in cellForRowAt, dequeue and configure the appropriate class.

    Here’s how it would look without the inter-cell spacing:

    enter image description here

    If that’s not quite clear, or if you’re still having trouble… if you put together a minimal reproducible example (post it somewhere like GitHub) that includes your data structures and some sample data and I can help you find the issue.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search