Ich mache Einheit Konverter App mit benutzerdefinierten Zellen, jede Zelle hat ein Textfeld innen und die Idee war, wenn Sie den Wert in einer Einheit eingeben alle Einheiten automatisch berechnet werden, die Problem ist nur, wenn es mehr Zellen gibt und wenn Sie scrollen müssen, wenn Zellen wiederverwendet werden, verwirren sie Tags und weil meine Funktion für die Berechnung über die Tag-Zelleneigenschaft funktioniert, bekomme ich falsche Werte. Hier ist mein Code und ich werde auch einen Screenshot meines Projekts im Voraus danken. Nicht: Ich weiß, dass einige Teile dynamischer und besser geschrieben sein könnten, aber ich bin neu in der iOS-Welt, also wusste ich in dieser Zeit nicht wirklich, wie ich es besser machen könnte.Swift UITableViewCell Wiederverwendung ist verwirrend Tags/App hat falsche Berechnung
Wenn Sie irgendwelche Fragen über den Code haben, werde ich gerne antworten.
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
}
Sie Ihren Code in einem anderen lang als eng kommentierte, es pls korrigieren. –
Ich korrigiere es so schnell wie möglich –
Es ist nicht der richtige Weg, wenn Sie wiederverwendbare Zellen speichern, denn während sie gespeichert sind, können sie wiederverwendet werden und somit einem anderen Gegenstand zugewiesen werden. Versuchen Sie, Ihren Code nur mit Zeilenindexen neu zu schreiben und die Zelle am angegebenen Index neu zu laden, anstatt die Zelle direkt zu ändern. – Varrry