PvUIDev
PvUIDev

Reputation: 125

How to load array value int cell without creating multiple custom cell in UITableView iOS Swift?

I have multiple label in tableview. Created an array for label left side. now i am trying to load data from array model for each label. But it says index out of range, cause it model array index is 0.

Here is my model :

 class PrItemDetailModel {

var Material: String?
var Description: String?
var FixedVendor: String?
var VendorName: String?
var PurchOrg: String?
var PurchGroup: String?
var qtyUoM: String?
var valuationPrice: String?
var TotalValue: String?
var DeliveryDate: String?
var MatGrp: String?
var Plant: String?
var StorageLocation: String?
var ReqTrack: String?
var AAC: String?
var ItemCategory: String?
var GLAccount: String?
var CostCenter: String?
var Order: String?
var WBS: String?
var ProfitCenter: String?


init(Material: String?, Description: String?, FixedVendor: String?, VendorName:String?, PurchOrg: String?, PurchGroup: String?, qtyUoM: String?, valuationPrice: String?, TotalValue: String?, DeliveryDate: String?, MatGrp: String?, Plant: String?, StorageLocation: String?, ReqTrack: String?, AAC: String?, ItemCategory: String?, GLAccount: String?, CostCenter: String?, Order: String?, WBS: String?, ProfitCenter: String?){

    self.Material = Material
    self.Description = Description
    self.FixedVendor = FixedVendor
    self.VendorName = VendorName
    self.PurchOrg = PurchOrg
    self.PurchGroup = PurchGroup
    self.qtyUoM = qtyUoM
    self.valuationPrice = valuationPrice
    self.TotalValue = TotalValue
    self.DeliveryDate = DeliveryDate
    self.MatGrp = MatGrp
    self.Plant = Plant
    self.StorageLocation = StorageLocation
    self.ReqTrack = ReqTrack
    self.AAC = AAC
    self.ItemCategory = ItemCategory
    self.GLAccount = GLAccount
    self.CostCenter = CostCenter
    self.Order = Order
    self.WBS = WBS
    self.ProfitCenter = ProfitCenter

    }

 }

Here is array created for label:

   var PrItemTitleLblArray = ["Material#", "Description", "Fixed Vendor#","Vendor Name", "Purch Org", "Purch Group", "Qty | UoM", "valuation Price", "Total Value", "Delivery Date", "Mat Grp", "Plant", "Storage Location", "Req Track#", "AAC", "Item Category", "G/L Account", "Cost Center", "Order", "WBS", "Profit Center"]

Here is the array from model:

  var prItemArray = [PrItemDetailModel(Material: "", Description: "Bottles", FixedVendor: "KP04", VendorName: "KP Suppliers", PurchOrg: "1000", PurchGroup: "002", qtyUoM: "40.000 EA", valuationPrice: "EUR 40.00", TotalValue: "EUR 1,600.00", DeliveryDate: "09/12/2014", MatGrp: "00807", Plant: "1100", StorageLocation: "", ReqTrack: "", AAC: "Cost Center", ItemCategory: "0", GLAccount: "000040000", CostCenter: "0000010000", Order: "", WBS: "0000000", ProfitCenter: "0000001402")]

Here is the code which i have used in tableview:

       let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! PrItemCellTableViewCell

       cell.material.text = PrItemTitleLblArray[indexPath.row]
       cell.materialvalue = prItemArray[indexPath.row]

    return cell

Here is screenshot which i want to achieve: enter image description here

here is my json response:

 "results": [
  {

   "PoDocNo": "4500022400",
   "Item": "00010",
   "Material": "RMECC_MOB1",
   "StorageLocation": "3001",
   "MatGroup": "00107",
   "Quantity": "2.000",
    "OrderUnit": "KG",
   "NetPrice": "1000.000",
   "UnitofPrice": "1.000",
   "ItemCat": "0",
   "Requistor": ""
   },
  {

  "PoDocNo": "4500022400",
  "Item": "00020",
  "Material": "RMECC_MOB1",
  "StorageLocation": "3001",
  "MatGroup": "00107",
  "Quantity": "2.000",
   "OrderUnit": "KG",
  "NetPrice": "1000.000",
  "UnitofPrice": "1.000",
  "ItemCat": "0",
  "Requistor": ""
  }
  ] 

Any help much appreciated pls...

Upvotes: 2

Views: 120

Answers (2)

Ram
Ram

Reputation: 804

@Parameswaran V

Here below check my simple updated answer for Can you suggest me best way for above one while passing json

You can create the Structure to form your required record like below,

    struct DemoItems {

        var key: String?
        var value: String?
    }

fileprivate var demoItems: [DemoItems]?

fileprivate func loadDemoItems() -> [DemoItems] {

        var tempItems = [DemoItems]()

        let item1 = DemoItems.init(key: "Material#", value: "")
        let item2 = DemoItems.init(key: "Description", value: "Bottles")
        let item3 = DemoItems.init(key: "Fixed Vendor#", value: "KP04")
        let item4 = DemoItems.init(key: "Vendor Name", value: "KP Suppliers")
        let item5 = DemoItems.init(key: "Purch Org", value: "1000")

        tempItems.append(item1)
        tempItems.append(item2)
        tempItems.append(item3)
        tempItems.append(item4)
        tempItems.append(item5)

        return tempItems
    }

In viewDidLoad like,

    demoItems = loadDemoItems()

    if let tempDemoItems = demoItems {

        print(tempDemoItems)
        print(tempDemoItems[0].key)
        print(tempDemoItems[0].value)
    }

Output:

[permisdesauver_dev.DemoItems(key: Optional("Material#"), value: Optional("")), permisdesauver_dev.DemoItems(key: Optional("Description"), value: Optional("Bottles")), permisdesauver_dev.DemoItems(key: Optional("Fixed Vendor#"), value: Optional("KP04")), permisdesauver_dev.DemoItems(key: Optional("Vendor Name"), value: Optional("KP Suppliers")), permisdesauver_dev.DemoItems(key: Optional("Purch Org"), value: Optional("1000"))]
Optional("Material#")
Optional("")

So your cell.material.text = tempDemoItems[indexPath.row].key & cell.materialvalue.text = tempDemoItems[indexPath.row].value

Hope it's help you!

Upvotes: 1

DonMag
DonMag

Reputation: 77476

The problem is that you are creating an array of Label Strings, and then you think you are creating an array of Values... but you're only creating an array of ONE PrItemDetailModel object.

Consider this (I've simplified your class to make it easier to see):

class PrItemDetailModel {

    var Material: String?
    var Description: String?
    var FixedVendor: String?

    init(Material: String?, Description: String?, FixedVendor: String?) {

        self.Material = Material
        self.Description = Description
        self.FixedVendor = FixedVendor

    }

}

class ViewController: UIViewController {

    // create array of Label Strings
    var PrItemTitleLblArray = ["Material#", "Description", "Fixed Vendor#"]

    // create array of PrItemDetailModel objects
    var prItemArray = [PrItemDetailModel(Material: "", Description: "Bottles", FixedVendor: "KP04")]

    override func viewDidLoad() {
        super.viewDidLoad()

        // this will print "3"
        print(PrItemTitleLblArray.count)

        // this will print "1"
        print(prItemArray.count)

    }

}

So when you try to fill rows in a table, your first row - indexPath.row equals 0 - your codes says:

// get the "Label String" from the array of Label Strings
// at index 0, this will be "Material#"
cell.material.text = PrItemTitleLblArray[indexPath.row]

// get the "Value String" from the array of PrItemDetailModel objects
// at index 0, this will be AN OBJECT, not a String
cell.materialvalue = prItemArray[indexPath.row]

The next row - indexPath.row equals 1 - your codes says:

// get the "Label String" from the array of Label Strings
// at index 1, this will be "Description"
cell.material.text = PrItemTitleLblArray[indexPath.row]

// get the "Value String" from the array of PrItemDetailModel objects
// at index 1 ... ERROR, because prItemArray has only one element
cell.materialvalue = prItemArray[indexPath.row]

You probably want to re-think your data structure... Where will you be getting these values? Via json from a server? From a database? You might be better off simply storing the data in an array of Dictionaries.

Or, and this is just one other way to approach it... modify your class to return values based on indexing:

class PrItemDetailModel {

    var Material: String?
    var Description: String?
    var FixedVendor: String?

    init(Material: String?, Description: String?, FixedVendor: String?) {

        self.Material = Material
        self.Description = Description
        self.FixedVendor = FixedVendor

    }

    func getProperty(at index: Int) -> String {

        switch index {
        case 0:
            return self.Material ?? ""
        case 1:
            return self.Description ?? ""
        case 2:
            return self.FixedVendor ?? ""
        default:
            return "Error"
        }

    }

}

You would then change your code to:

    // create ONE PrItemDetailModel object
    var prItem = PrItemDetailModel(Material: "", Description: "Bottles", FixedVendor: "KP04")

and in cellForRowAt:

// get the "Label String" from the array of Label Strings
cell.material.text = PrItemTitleLblArray[indexPath.row]

// get the "Value String" from the array of PrItemDetailModel objects
// based on the index
cell.materialvalue.text = prItem.getProperty(at: indexPath.row)

Upvotes: 1

Related Questions