Swift UITableViewCell重用是搞乱标签/ app有错误的计算

时间:2017-12-28 09:00:36

标签: ios swift uitableview

我正在制作带有自定义单元格的单位转换器应用程序,每个单元格里面都有一个文本框,想法是当你在一个单元中输入值时,所有单位都会自动计算,问题是只有当有更多单元格时才需要当单元格被重用时滚动它们会弄乱标签,因为我的计算功能通过标签单元属性工作,我得到了错误的值。 这是我的代码,我还将提前提供我的项目的截图。不是:我知道有些部分可以更有活力,更好写,但我是iOS世界的新手,所以在那段时间我真的不知道怎么做得更好。

如果您对代码有任何疑问,我将很乐意回答。 enter image description here  Screenshot

   import UIKit

    protocol Initializable {
        init()
    }

    class ValuesTableViewController: UITableViewController, Initializable, UITextFieldDelegate {

        @IBOutlet var valuesTableView: UITableView!
        var valueName: String?
        var valueColor: UIColor?
        var selectedValueObject: Properties?
        var listOfAllUnitObjects = [AnyObject]()
        var doubleTextValue : Double?
        var listOfAllCells = [ValuesCell]()
        var listOfCurrentValues = [Double]()
        var returningCalculatedValue : Double?
        var changingObject: Properties?
        var selected = [Int : String]()
        var selectedTag : Int?
        var noValues: String?
        var colorChange: UIColor?
        var classValues: [Properties.Type] = [Properties.Type]()
        var selectedTextField: Int?
        var activeField: UITextField?
        var imageName: String?
        let listOfAllIndexes: [Int] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
       // var testTextField : UITextField
        //"m²","km²","ha","dm²","cm²","mm²","sq mi", "ac", "sq yd","sq ft", "sq in"
       // var areaValues: [String: Area] = ["m²": Acre(), "km²": SquareKilometer(), "ha": Hectare(), "dm²": SquareDecimeter(), ""]
        //var listOfAllUnitsInClass = [Acre,Hectare,SquareCentimeter,SquareDecimeter,SquareFoot,SquareInch,]





        override func viewDidLoad() {
            super.viewDidLoad()



        }

    //    override func numberOfSections(in tableView: UITableView) -> Int {
    //        // #warning Incomplete implementation, return the number of sections
    //        return 0
    //    }

        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            // #warning Incomplete implementation, return the number of rows
            let valuesType = configureTable()
            let valuesObject = createInstance(typeThing: valuesType)
           // print("Value of listOfMainLabels in numberOfRowsInSection : \(valuesObject.listOfMainLabels.count)")

          return valuesObject.listOfMainLabels.count

        }

        func textFieldDidBeginEditing(_ textField: UITextField) {
            activeField = textField
            selectedTextField = textField.tag

            for i in (0...listOfAllCells.count - 1){
                if let textFieldTag = selectedTextField {
                    listOfAllCells[textFieldTag].cellView.backgroundColor = UIColor.white
                    if let imgName = imageName {
                        listOfAllCells[textFieldTag].cellImg.image = UIImage(named: imgName)
                    }
                    if i == textFieldTag {

                    }else{
                    listOfAllCells[i].cellView.backgroundColor = UIColor(red: 232/255.0, green: 232/255.0, blue: 232/255.0, alpha: 1.0)
                    listOfAllCells[textFieldTag].cellImg.image = nil
                    }

            }
            }
            textField.text = ""
            textField.keyboardType = UIKeyboardType.decimalPad
            let valuesType = configureTable()
            let valuesObject = createInstance(typeThing: valuesType)
            if textField.text == "" {
                //Ovde nastaje problem jer samo vrati unetu vrednost
                let entryValueReturned = checkTypesForSelected(tag: textField.tag, cells: listOfAllCells, entryValues: 0, valuesObject: valuesObject)
                returningCalculatedValue = entryValueReturned
                if let returnCalculatedValue = returningCalculatedValue {
                    checkTypes(tag: textField.tag, allCells: listOfAllCells, entryValues: returnCalculatedValue, valuesObject: valuesObject)
                    selectedTag = textField.tag
                    selected[textField.tag] = "0"
                   // print("Prolazi druga funkcija")
                    //valuesTableView.reloadData()
                }

            }
        }
        func textFieldDidEndEditing(_ textField: UITextField) {
            //Deleting previous entered value and setting to blank

            activeField = nil
            if textField.text == "" {

                noValues = ""

            }




        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let valuesType = configureTable()
            let valuesObject = createInstance(typeThing: valuesType)

            //Creating an instance of the object that the user previously selected getting the listOfMainValues which are unit labels 

            //print("TableView called \(indexPath.row)")

            let cell = tableView.dequeueReusableCell(withIdentifier: "valueCell", for: indexPath) as! ValuesCell
            print("Tag for this cell would have been \(indexPath.row)")
            if indexPath.row == 0 {
                cell.cellView.backgroundColor = UIColor.white
                if valuesObject is Area {
                    //Depending of what unit category is selected different image is used
                    imageName = "area-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Temperature{
                    imageName = "temperature-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Length {
                    imageName = "length-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Mass {
                    imageName = "mass-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Speed {
                    imageName = "speed-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Volume {
                    imageName = "volume-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is FuelConsumption {
                    imageName = "fuel-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is Time {
                    imageName = "time-arrow"
                    cell.cellImg.image = UIImage(named: imageName!)
                }else if valuesObject is DigitalStorageData {
                  //Same for all other units ...
                }
            }

            let currentClassName = valuesObject.listOfAllUnits[indexPath.row]
            let unitObject = stringClassFromString(currentClassName)

            cell.cellTextBox.delegate = self
            cell.cellTextBox.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
            //button.addTarget(self, action: #selector(self.buttonClicked(sender:)), for: .touchUpInside)
            //Setting values from an array to cell label
            cell.cellMainLbl.text = valuesObject.listOfMainLabels[indexPath.row]
            cell.cellSmallLbl.text = valuesObject.listofSmallLabels[indexPath.row]
    //            cell.valueLabel.textColor = UIColor.init(red: CGFloat(rColorValue[indexPath.row]), green: CGFloat(gColorValue[indexPath.row]), blue: CGFloat(bColorValue[indexPath.row]), alpha: 1.0)
    //            cell.leftColorView.backgroundColor = UIColor.init(red: CGFloat(rColorValue[indexPath.row]), green: CGFloat(gColorValue[indexPath.row]), blue: CGFloat(bColorValue[indexPath.row]), alpha: 1.0)
            cell.tag = listOfAllIndexes[indexPath.row]
            cell.cellTextBox.tag = listOfAllIndexes[indexPath.row]
            print("Cell tag : \(cell.tag) and CellTextBox tag: \(cell.cellTextBox.tag)")
            cell.cellTextBox.borderStyle = .none
            if valuesObject.listOfMainLabels.count - 1 >= listOfAllCells.count {
                listOfAllCells.append(cell)
            }
            //listOfAllUnitObjects.append(unitObject)
            if let unitObjectUnwrapped = unitObject {
                listOfAllUnitObjects.append(unitObjectUnwrapped)
            }

    //        for unit in valuesObject.listOfAllUnits {
    //            let unitObject = stringClassFromString(unit)
    //            if let unitObjectUnwrapped = unitObject {
    //                listOfAllUnitObjects.append(unitObjectUnwrapped)
    //            }
    //
    //
    //        }

    //        //cell.imageView?.image = UIImage(named: fruitName)
    //        cell.rightValueImage.image = UIImage(named: "\(indexPath.row)")
            if selected[indexPath.row] != nil {
                cell.cellTextBox.text = selected[indexPath.row]
                //print("Ako ovo prodje znaci sredjuj sledecu funkciju koja ih namesta na default da ignorise ovu celiju")
            }
            // Configure the cell...
            return cell
        }
        override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            //Save the last selected textfield value
            let valuesType = configureTable()
            let valuesObject = createInstance(typeThing: valuesType)

            if let seleTag = selectedTag {
                let valueString = selected[seleTag]
                if let valueS = valueString {
                    if let value = Double(valueS){
                        if value == 0 {
                            print("Da vidimo da li upada ovde : \(selected[selectedTag!]!)")
                            let valueFromMethod = checkTypesForSelected(tag: seleTag, cells: listOfAllCells, entryValues: 0, valuesObject: valuesObject)
                            checkTypes(allCells: listOfAllCells, entryValues: valueFromMethod, valuesObject: valuesObject)
                            print("PROLAZI ZA 0 checkTypes")
                        }else{
                             da li je uopste value nekada 0 ili je uvek razlicit od nule
                            print("value vrednost: \(value)")
                            let methodValue = checkTypesForSelected(tag: seleTag, cells: listOfAllCells, entryValues: value, valuesObject: valuesObject)
                            checkTypes(tag: seleTag, allCells: listOfAllCells, entryValues: methodValue, valuesObject: valuesObject)
                            print("OBRATI PAZNU!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
                        }

                    }

                    }

                //Problem: kada ne unese vrednost vraca ih na 1 umesto na 0
                //Ovde radim trenutno
            }else{
                checkTypes(allCells: listOfAllCells, entryValues: 1, valuesObject: valuesObject)
                print("ZAVRSILA SE METODA SA POZIVOM 1")


            }

            if let changeColor = colorChange {
                if indexPath.row == 0 {
                    let cell = tableView.dequeueReusableCell(withIdentifier: "valueCell", for: indexPath) as! ValuesCell
                    cell.cellView.backgroundColor = changeColor
                }
            }
            //checkTypes(allCells: listOfAllCells,entryValues: 1, valuesObject: valuesObject)
            //print("Value of listOfAllCells in willDisplay : \(listOfAllCells.count)")
            valuesTableView.tableFooterView = UIView()
            valuesTableView.tableFooterView?.backgroundColor = UIColor.gray
    //        valuesTableView.tableFooterView?.backgroundColor = UIColor(red: 232/255.0, green: 232/255.0, blue: 232/255.0, alpha: 1.0)
        }
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


            let cell = tableView.cellForRow(at: indexPath) as! ValuesCell
            if (cell.cellTextBox.text?.isEmpty)!{
                cell.cellTextBox.text = "0.0"
            }
            print("Cell clicked has a tag \(cell.tag)")



                for i in (0...listOfAllCells.count - 1){
                    if i == indexPath.row {
                        cell.cellView.backgroundColor = UIColor.white
                        if let imageTxt = imageName {
                            cell.cellImg.image = UIImage(named: imageTxt)
                            print("Prosla slika")
                        }
                    }else{
                        colorChange = cell.backgroundColor
                        listOfAllCells[i].cellView.backgroundColor = UIColor(red: 232/255.0, green: 232/255.0, blue: 232/255.0, alpha: 1.0)
                        cell.cellImg.image = nil
                    }

                }
    //

            self.view.endEditing(true)


        }
        override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
            return .none
        }

        override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
            return false
        }


        func checkTypes<T>(allCells: [ValuesCell],entryValues: Double, valuesObject: T){

            if valuesObject is Area {

           //When cells appear for the first time calculate for 1 all units
             classValues = [SquareMeter.self, SquareKilometer.self, Hectare.self, SquareDecimeter.self,
                                            SquareCentimeter.self, SquareMillimeter.self, SquareMile.self, Acre.self,
                                            SquareYard.self, SquareFoot.self, SquareInch.self]
    //            print("classValues count je : \(classValues.count)")
    //            print("listOfAllCells count je: \(listOfAllCells.count)")


                //Napravi da ako i bude jednako tagu da preskoci tu vrednost jer zelimo da ostane to sto je korisnik uneo
                //u tom polju
                for i in 0...(listOfAllCells.count - 1){
                        //print("Ovde baca index out of range i ima vrednost: \(i)")
                        let object = classValues[i].init()
                        let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                        //print("Vracam vrednost druge metode za \(i) element je : \(value)")
                        listOfAllCells[i].cellTextBox.text = "\(value)"



                    }
            }else if valuesObject is Temperature {
                 classValues = [Celsius.self, Fahrenheit.self, Kelvin.self]
                for i in 0...(listOfAllCells.count - 1){
                    let object = classValues[i].init()
                    let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                    element je : \(value)")
                    listOfAllCells[i].cellTextBox.text = "\(value)"


                }
            }else if valuesObject is Length {
                 classValues = [Meter.self, CentiMeter.self, DeciMeter.self, Foot.self, Inch.self,
                                                  KiloMeter.self, MicroMeter.self, Mile.self, MillieMeter.self, NanoMeter.self, NauticMile.self,Yard.self]
                for i in 0...(listOfAllCells.count - 1){
                    let object = classValues[i].init()
                    let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                    element je : \(value)")
                    listOfAllCells[i].cellTextBox.text = "\(value)"


                }
            }else if valuesObject is Mass {
                classValues = [KiloGram.self, DecaGram.self, Gram.self,LongTon.self, MetricTon.self,
                                                MicroGram.self, MilliGram.self, Ounce.self, Pound.self, ShortTon.self, Stone.self]
                for i in 0...(listOfAllCells.count - 1){
                    let object = classValues[i].init()
                    let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                    element je : \(value)")
                    listOfAllCells[i].cellTextBox.text = "\(value)"


                }
            }else if valuesObject is Speed {
                 classValues = [MetersPerSecond.self, FeetPerSecond.self, KilometersPerHour.self,Knot.self, MilesPerHour.self]
                for i in 0...(listOfAllCells.count - 1){
                    let object = classValues[i].init()
                    let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                    //print("Vracam vrednost druge metode za \(i) element je : \(value)")
                    listOfAllCells[i].cellTextBox.text = "\(value)"


                }
            }else if valuesObject is Volume {
                 classValues = [Liter.self, CubicFoot.self, CubicInch.self,CubicMeter.self,
                                                  ImperialGal.self, ImperialOz.self, ImperialPint.self, ImperialQuart.self,
                                                  ImperialTableSpoon.self,ImperialTeaSpoon.self, MilliLiter.self, UsCup.self,
                                                  UsGal.self,UsOz.self,UsPint.self,UsQuart.self,UsTableSpoon.self,UsTeaSpoon.self]
                for i in 0...(listOfAllCells.count - 1){
                    let object = classValues[i].init()
                    let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                    //print("Vracam vrednost druge metode za \(i) element je : \(value)")
                    listOfAllCells[i].cellTextBox.text = "\(value)"


                }
            }else if valuesObject is FuelConsumption {


             ...//And for all other Units same thing..

            }

        }
        func checkTypes<T>(tag: Int, allCells: [ValuesCell],entryValues: Double, valuesObject: T){

            if valuesObject is Area {

                classValues = [SquareMeter.self, SquareKilometer.self, Hectare.self, SquareDecimeter.self,
                               SquareCentimeter.self, SquareMillimeter.self, SquareMile.self, Acre.self,
                               SquareYard.self, SquareFoot.self, SquareInch.self]

    //            let classValues: [Area.Type] = [SquareMeter.self, SquareKilometer.self, Hectare.self, SquareDecimeter.self,
    //                                            SquareCentimeter.self, SquareMillimeter.self, SquareMile.self, Acre.self,
    //                                            SquareYard.self, SquareFoot.self, SquareInch.self]
    //            print("classValues count je : \(classValues.count)")
    //            print("listOfAllCells count je: \(listOfAllCells.count)")


                //Fixing index difference between tags going out of bounds

                for i in 0...(listOfAllCells.count - 1){
                    if i == tag {
                        print("Evo ga tag \(tag)")
                    }else{
                        //print("Ovde baca index out of range i ima vrednost: \(i)")
                        let object = classValues[i].init()
                        let value = object.ConvertFromMainUnitToUnit(entryValue: entryValues)
                        //print("Vracam vrednost druge metode za \(i) element je : \(value)")
                        listOfAllCells[i].cellTextBox.text = "\(value)"

                    }


                }
            }else if valuesObject is Temperature {


               ...//And for all other Units same thing..



                }
            }
        }
        func checkTypesForSelected<T>(tag: Int,cells: [ValuesCell],entryValues: Double, valuesObject: T) -> Double{
//Checking what unit is selected and calculating all values for all units in that category
            if valuesObject is Area {

                classValues = [SquareMeter.self, SquareKilometer.self, Hectare.self, SquareDecimeter.self,
                                                SquareCentimeter.self, SquareMillimeter.self, SquareMile.self, Acre.self,
                                                SquareYard.self, SquareFoot.self, SquareInch.self]

                if listOfAllUnitObjects[tag] is SquareMeter.Type {
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareMeter.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                } else if listOfAllUnitObjects[tag] is SquareKilometer.Type {
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareKilometer.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is Hectare.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? Hectare.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareDecimeter.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareDecimeter.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareCentimeter.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareCentimeter.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareMillimeter.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareMillimeter.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareCentimeter.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareCentimeter.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareMile.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareMile.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is Acre.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? Acre.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareYard.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareYard.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareFoot.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareFoot.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }else if listOfAllUnitObjects[tag] is SquareInch.Type{
                    var testObject = classValues[tag].init()
                    testObject = createInstance(typeThing: (listOfAllUnitObjects[tag] as? SquareInch.Type)!)
                    let value = testObject.ConvertFromUnitToMainUnit(entryValue: entryValues)
                    return value
                }

            }else if valuesObject is Temperature {

              ...//And for all other Units same thing as above..
                }
            }
            return 0
        }

1 个答案:

答案 0 :(得分:0)

在cellForRow

中尝试这样
  let cell = tableView.dequeueReusableCell(withIdentifier: "valueCell") as! ValuesCell