Ian Ian - 1 month ago 8
Swift Question

Swift How do I show tableview cell only if there is value in my database

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 ! :/

Answer

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
}