1

this is my database structure

"type" : {
      "A" : {
        "nightAmount" : 5,
        "noonAmount" : 2
      },
      "B" : {
        "nightAmount" : 5,
        "noonAmount" : 3
      },
      "C" : {
        "nightAmount" : 2,
        "noonAmount" : 5
      }}

I want my tableviewCell to show labels like :-

1st cell: A - noonAmount - 2

2nd cell : A - nightAmount - 5

3rd cell: B - noonAmount - 3

4th cell: B - nightAmount - 5

5th cell : C - noonAmount - 5

6th cell : C - nightAmount - 2

But the amount can be 0 and I don't want the type which the amount is 0 to show on my tableview cell,

what am I suppose to call in cellforrowat function?

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

    let cell =  tableView.dequeueReusableCell(withIdentifier: "confCell")! as UITableViewCell {  

And here's my numberofrowsinsection

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {  
    if AnoontAmount >= 1 {
        let V1 = 1
    } else { V1 = 0 }

    if ANightAmount >= 1 {
        let V2 = 1
    } else { V2 = 0 }

    if BnoonAmount >= 1 {
        let V3 = 1
    } else { V3 = 0 }

    if BNightAmount >= 1 {
        let V4 = 1
    } else { V4 = 0 }

    if CnoonAmount >= 1 {
        let V5 = 1
    } else { V5 = 0 }

    if CNightAmount >= 1 {
        let V6 = 1
    } else { V6 = 0 }


    let cellTotal = V1 + V2 + V3 + V4 + V5 + V6
    return cellTotal

I don't know if it's gonna work

Can anyone tell if there is a proper way to get this done ?

Thanks !!

UPDATE

I updated my code as the following

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    var cellTotal = 0

    if  V1amount > 0 {
        cellTotal += 1
    }

    if  V2amount > 0 {
        cellTotal += 1
    }

    if  V3amount > 0 {
        cellTotal += 1
    }


    if  V4amount > 0 {
        cellTotal += 1
    }


    if  V5amount > 0 {
        cellTotal += 1
    }

    if  V6amount > 0 {
        cellTotal += 1
    }

    return cellTotal

}

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


    var mealtype : Array = ["TypeA", "TypeA", "TypeB", "TypeB", "TypeC", "TypeC"]
    var mealtime : Array = ["lunch", "dinner", "lunch","dinner","lunch","dinner"]
    var mealamount : Array = ["\(V1amount!)","\(V2amount!)","\(V3amount!)","\(V4amount!)","\(V5amount!)","\(V6amount!)"]

    if V1amount == 0 {
        mealtype.remove(at: 0)
        mealtime.remove(at: 0)
        mealamount.remove(at: 0)
    }

    if V2amount == 0 {
        mealtype.remove(at: 1)
        mealtime.remove(at: 1)
        mealamount.remove(at: 1)
    }


    print (mealtype)
    print (mealtime)
    print (mealamount)




    if let cell = tableView.dequeueReusableCell(withIdentifier: "confCell") as! confCell! {

        cell.confMealName.text = mealtype[(indexPath as NSIndexPath).row]
        cell.confNN.text = mealtime[(indexPath as NSIndexPath).row]
        cell.confAmount.text! = mealamount[(indexPath as NSIndexPath).row]

        return cell
    } else {
        return confCell()
    }

}

The problem now is, if there's only one VAmount = 0, it works just fine I removed index in the array so that it won't show it the tableview cell But if there are two or more VAmount = 0

It just acting weird , I guess it's because the program is executed from top to bot ... and not at once...

Is there anyone who can tell me how to improve this code

I pretty sure there's a better way to do this ! :/

Ian
  • 239
  • 1
  • 14
  • What do you actually want? You dont want show value 0 into cell – Jitendra Modi Oct 26 '16 at 05:48
  • I'd suggest that you create a data object to represent the contents of each cell (e.g. with the fields: name, time, amount). When you receive your json, parse it accordingly into a list of data objects. If the amount is empty, don't add it to the list. This way, you have 1-1 mapping between the data objects and the list cells of your tableview, i.e. for numberOfRowsInSection, you could simply return list.count. For cellForRowAtIndexPath, you could grab the data object by list[indexPath.row], and then render your cell accordingly based on its values. – Ken Toh Oct 26 '16 at 05:55
  • @Jecky , Yes. like if type/A/noonAmount = 0, then I will have only 5 rows. its easy to have all 6 row, I just don't how to show those with value > 0. – Ian Oct 26 '16 at 15:32
  • @kentoh, do you think I call dequereusalbeCell to have all 6 rows and then call deleteRow to delete those have empty value is a good idea or nah :/ – Ian Oct 26 '16 at 15:34
  • Ian, it's better that you don't perform operations on the arrays inside the `cellForRowAtIndexPath` method because this method is called several times depending on how many rows you've got. And this can cause unwanted effects of your program performance. – Elena Oct 27 '16 at 05:47

2 Answers2

2

Your logic seems to be ok except that you'll get compilation errors because V1, V2 etc are declared in closed scopes.

I would suggest something like this:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

    var cellTotal = 6

    guard AnoonAmount > 0 else {cellTotal -= 1}

    guard ANightAmount > 0 else {cellTotal -= 1}

    guard BnoonAmount > 0 else {cellTotal -= 1}

    guard BNightAmount > 0 else {cellTotal -= 1}

    guard CnoonAmount > 0 else {cellTotal -= 1}

    guard CnightAmount > 0 else {cellTotal -= 1}

    return cellTotal      
}
Elena
  • 829
  • 8
  • 20
  • 1
    Hi Elena, thanks for replying! looks like your code makes perfect sense, I will give it a try! anyidea how do I cellforrowat Indexpath function ? thanks – Ian Oct 26 '16 at 06:43
  • Ian, for that you've got plenty [posts](http://stackoverflow.com/questions/24022763/uitableview-in-swift). – Elena Oct 26 '16 at 08:09
2

As suggested in my comment, one way would be to create a data object to hold the contents for each cell. This way, you have a 1-1 mapping between the data objects and the list cells of your tableview.

First, create an array to hold objects with meals with non-zero amounts. This should be done at where you fetch your JSON from your database (i.e. not within cellForRowAtIndexPath). I'm going to use a Swift tuple in this case for the data object for simplicity, but you could always use a plain old Swift object.

// An array of Meal tuples, each of which can hold a type, time and amount)
var meals:[(type: String, time: String, amount: Double)]  = []

For each meal object, if the amount is empty, we simply don't add it to the array:

if v1amount > 0 {
    meals.append((type: "TypeA", time: "lunch", amount: v1amount))
}
if v2amount > 0 {
    meals.append((type: "TypeA", time: "dinner", amount: v2amount))
}
if v3amount > 0 {
    meals.append((type: "TypeB", time: "lunch", amount: v3amount))
}
if v4amount > 0 {
    meals.append((type: "TypeB", time: "dinner", amount: v4amount))
}
if v5amount > 0 {
    meals.append((type: "TypeC", time: "lunch", amount: v5amount))
}
if v6amount > 0 {
    meals.append((type: "TypeC", time: "dinner", amount: v6amount))
}

Because you have a 1-1 mapping between your meals array and your tableview, implementing the numberOfRowsInSection delegate method become straightforward:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // return the number of meals in your array
    return meals.count
}

Similarly, for cellForRowAtIndexPath, you could simply get the object from the array at the relevant index, and render its contents:

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

    let cell = tableView.dequeueReusableCell(withIdentifier: "confCell") as! confCell
    // Get the meal object for this row
    let meal = meals[indexPath.row]

    // Populate the fields based on the meal's property
    cell.confMealName.text = meal.type
    cell.confNN.text = meal.time
    cell.confAmount.text! = meal.amount

    return cell
}
Ken Toh
  • 3,721
  • 1
  • 24
  • 30
  • Hi kenton, your logic is perfect !! your code looks just like how I want to do it but Xcode is keep yelling " Value of type 'AnyObject' has no member 'time'" error at me. I don't know what possibly went wrong – Ian Oct 27 '16 at 06:29
  • Which line? When you declare your meals array, make sure you have also declared the type of object that the array is holding, as per my answer above. – Ken Toh Oct 27 '16 at 06:39
  • 1
    Hi kenton, Now it totally works. Thank you so much, I learn A LOT from your code ! – Ian Oct 27 '16 at 07:53