Fetching PassioFoodItem from PassioAdvisorFoodInfo
To display the food details, PassioFoodItem is required.
Fetch PassioFoodItem from PassioFoodDataInfo
// We already have PassioAdvisorFoodInfo
var food: PassioAdvisorFoodInfo?
// We will fetch PassioFoodItem from PassioAdvisorFoodInfo
var foodItem: PassioFoodItem?
func fetchPassioFoodItem() {
guard let food = food else { return }
if let packagedFoodItem = food.packagedFoodItem {
self.foodItem = packagedFoodItem
tableView.reloadData()
}
else {
if let foodDataInfo = food.foodDataInfo {
let servingQuantity = foodDataInfo.nutritionPreview?.servingQuantity
let servingUnit = foodDataInfo.nutritionPreview?.servingUnit
updateLoader(show: true)
PassioNutritionAI.shared.fetchFoodItemFor(foodDataInfo: foodDataInfo,
servingQuantity: servingQuantity,
servingUnit: servingUnit) { passioFoodItem in
DispatchQueue.main.async {
self.updateLoader(show: false)
if let foodItem = passioFoodItem {
self.foodItem = foodItem
tableView.reloadData()
}
}
}
}
}
}
Showing the Food Detail and Macro-Nutrients
We build a UI component to display macro-nutrients like calories, carbohydrates, protein, and fat. We get these macro nutrients for the selected size of the food.
func setup(foodItem: PassioFoodItem) {
// 1. Name & short name
labelName.text = foodItem.name
labelShortName.text = foodItem.details
let entityType: PassioIDEntityType = foodItem.ingredients.count > 1 ? .recipe : .item
if labelName.text?.lowercased() == self.labelShortName.text?.lowercased()
|| entityType == .recipe {
labelShortName.isHidden = true
} else {
labelShortName.isHidden = false
}
// 2. Food image
imageFood.loadIcon(id: foodItem.iconId)
// 3. Calories
let calories = foodItem.nutrientsSelectedSize().calories()?.value ?? 0
let carbs = foodItem.nutrientsSelectedSize().carbs()?.value ?? 0
let protein = foodItem.nutrientsSelectedSize().protein()?.value ?? 0
let fat = foodItem.nutrientsSelectedSize().fat()?.value ?? 0
caloriesLabel.text = calories.noDigit
carbsLabel.text = carbs.oneDigit + " \(UnitsTexts.g)"
protienLabel.text = protein.oneDigit + " \(UnitsTexts.g)"
fatLabel.text = fat.oneDigit + " \(UnitsTexts.g)"
// 4. Percentage
let total = [c,p,f].reduce(0, { $0 + $1.percent })
if total > 0 {
fatPercentLabel.text = "(\(f.percent.oneDigit)%)"
protienPercentLabel.text = "(\(p.percent.oneDigit)%)"
carbsPercentLabel.text = "(\(c.percent.oneDigit)%)"
} else {
fatPercentLabel.text = "(0%)"
protienPercentLabel.text = "(0%)"
carbsPercentLabel.text = "(0%)"
}
// 5. Chart
let percents = macronutrientPercentages(carbsG: carbs,
fatG: fat,
proteinG: protein,
totalCalories: calories)
let c = DonutChartView.ChartDatasource(color: .lightBlue,
percent: percents.carbPercentage)
let p = DonutChartView.ChartDatasource(color: .green500,
percent: percents.proteinPercentage)
let f = DonutChartView.ChartDatasource(color: .purple500,
percent: percents.fatPercentage)
nutritionView.updateData(data: [c,p,f])
}
func macronutrientPercentages(carbsG: Double,
fatG: Double,
proteinG: Double,
totalCalories: Double) -> (carbPercentage: Double,
fatPercentage: Double,
proteinPercentage: Double)
{
// Calculate calories contributed by each macronutrient
let carbCalories = carbsG * 4
let fatCalories = fatG * 9
let proteinCalories = proteinG * 4
// Calculate total calories from macronutrients
let totalMacronutrientCalories = carbCalories + fatCalories + proteinCalories
// Calculate percentages
let carbPercentage = (carbCalories / totalMacronutrientCalories) * 100
let fatPercentage = (fatCalories / totalMacronutrientCalories) * 100
let proteinPercentage = (proteinCalories / totalMacronutrientCalories) * 100
return (carbPercentage: carbPercentage,
fatPercentage: fatPercentage,
proteinPercentage: proteinPercentage)
}
Edit Serving Size
The setSelectedQuantity() function handles changes to the serving quantity. It calculates the corresponding weight based on the selected serving unit and updates the passioFoodItem object accordingly.
For example, once user changes the quantity from a textfield or from a slider, we can call setSelectedQuantity() function on passioFoodItem.
let quantity = Double(textField.text)
self.foodItem?.setSelectedQuantity(quantity)
// Refresh data
tableView.reloadData()
Edit Serving Unit
The setSelectedUnit() function handles changes to the serving unit.
For example, once user changes the unit (e.g. Packet, Cup, Gram) from a list of units, we can call setSelectedQuantity() function on passioFoodItem.
let unit = // User selected unit
self.foodItem?.setSelectedUnit(unit)
// Refresh data
tableView.reloadData()
To get list of all units for a food item:
guard let servingUnits = foodItem?.amount.servingUnits else { return }
let items = servingUnits.map { $0.unitName }