Often code needs some way to describe a discrete set of cases. You might need values for breakfast lunch and dinner for example. How we configure a view might be set by one of a few choices. There are many types of UIButton
s we can use such as system, custom, and detail disclosure. We would declare them like this:
let systemButton = UIButton(type:UIButtonType.System) let customButton = UIButton(type:.Custom) let detailDisclosureButton = UIButton(type:.DetailDisclosure)
After the type:
parameter we have an enumeration, often called an enum which is the declaration keyword for an enumeration. Enumerations are often misunderstood, and often give powerful ways to control and document code easily. In this lesson, we’ll begin to explore the basic uses for enumeration.
Using IBM’s Swift Sandbox
We won’t write a full app for this lesson. Instead we’ll use a handy tool for exploring the Swift language anywhere there is an internet connection and web browser. In December 2015, Apple released the open source Swift version (Swift 2.2). It does not include the API’s of UIKit
, but does have all the Foundation
framework. IBM in partnership with Apple launched a website-based playground (which they confusingly call a sandbox) for testing code. I’ll use the IBM Sandbox for this lesson, which I find faster than Xcode’s playground, and you can use it on your iPad or even PC since you don’t need Xcode, just a Web browser. You can certainly use Xcode’s playground if you want.
Open your favorite web browser and navigate to http://swiftlang.ng.bluemix.net/#/repl. You’ll get a website looking like a playground:
Depending on your tastes you can change the skin from dark to light. Click the settings gear on the sandbox, then select the Light Theme.
You’ll get a light color scheme.
You’ll see a snippet of code in the left side code window
// TODO: Write some awesome Swift code, or import libraries like "Foundation", // "Dispatch", or"Glibc" print("Hello world!")
At the lower center, you’ll find the Run button. Click that button to make your code compile and run. We get the classic Hello World
message. If you have syntax errors, they show in the Results side of the page. Remove the quote mark after the exclamation mark from the current code and run again. You get several errors starting with:
/swift-execution/code-tmp.swift:4:7: error: unterminated string literal
Fix the error and run again. The errors are replaced by the Hello World
output
Some Code to Fix
To explain enums
, let’s make some code that should use it, but doesn’t. Since I’m writing this in January, a lot of people are obsessed with weight loss now. Let’s make a calorie counter to help them out. Delete the source code in the sandbox, and add this code in its place:
import Foundation var caloriesTotal = [0,0,0,0]
We made an 4-element array to keep totals for calories for each meal. The first position of this array is breakfast, then lunch, dinner and snack. Add this function to the code:
func addCaloriesForMeal(meal:Int,calorie:Int){ caloriesTotal[meal] += calorie print ( "Calories for meal \(meal) is \(caloriesTotal[meal])") if meal == 3 { print("Try not to snack") } if (meal == 0) && (caloriesTotal[meal] > 100){ print("Breakfast is the most important meal of the day. Eat more breakfast.") } }
The code adds calories, gives us feedback to the current calorie count for that meal, and a few comments about our current diet. Without comments, this would be difficult code to understand, and even code for. I have to remember that 0 is breakfast and 3 is snacks. Someone else reading this code would have an even more difficult time. Add the following to call the function:
addCaloriesForMeal(0,calorie:50) addCaloriesForMeal(1,calorie:280) addCaloriesForMeal(2,calorie:650) addCaloriesForMeal(3,calorie:1150)
Run the code and it works.
Calories for meal 0 is 50
Breakfast is the most important meal of the day. Eat more breakfast.
Calories for meal 1 is 280
Calories for meal 2 is 650
Calories for meal 3 is 1150
Try not to snack
The code works. It’s just very difficult to work with
Using Enum
What if we could change the values of 0,1,2,3 with words? We could do this with constants like this:
let breakfast = 0 let lunch = 0 let dinner = 0 let snacks = 0
Even better, we can define a special type that has these constants as the only value of the type. We could use that type anywhere within the scope. This is an enumeration. Add the following code above the var
in your current code.
enum Meal:Int{ case Breakfast = 0 case Lunch = 1 case Dinner = 2 case Snack = 3 }
The first line declares an enumeration type called Meal
. We declare Meal
to be representing an integer value. The next lines contain the values we are representing. We can now use the enumeration as a constant.To make clear these are not variables, values in an enum
have their first letter capitalized. In Swift, you’ll find two ways of using this constant. If there is no context as to type, you will see Meal.Breakfast
. If there is a context, such as in a declared parameter or comparison to a value of the same enumeration type, you can write .Breakfast
.
Change the declaration for our function to this:
func addCaloriesForMeal(meal:Meal,calorie:Int){
We changed the type for the meal to our enumeration. For most cases this will be all you need to do.
We can now change our Boolean statements to be better documented in the code. Change the first if
to this:
if meal == .Snack {
This is much easier to read than before
The rawValue Property
There is one wrinkle to enums
. Unlike a constant or variable, the value of an enum
cannot directly assign its value to something else. Our current array index
caloriesTotal[meal] += calorie
Would cause an error:
/swift-execution/code-tmp.swift:11:15: error: cannot subscript a value of type '[Int]' with an index of type 'Meal'
Meal
is a different type, and Swift requires an Int
here. We have a property of enums
rawValue
. After our function declaration add this line:
let mealIndex = meal.rawValue //get the raw value of the enumeration
Now change the two lines under it to this:
caloriesTotal[mealIndex] += calorie print ("Calories for meal \(mealIndex) is \(caloriesTotal[mealIndex])")
We have one more line to change in our function. Change the breakfast if
statement
if (meal == .Breakfast) && (caloriesTotal[mealIndex] < 100){
Calling the function is a lot easier now. Replace the function calls with the following:
addCaloriesForMeal(.Breakfast,calorie:50) addCaloriesForMeal(.Dinner,calorie:650) addCaloriesForMeal(.Snack,calorie:1150)
Now run the code. We get similar results, but our code is a lot easier to read
Using Switch…Case with Enumeration
We’ve already evaluated situations with if
statements. Often we will have to do something different for every case in an enumeration. This is where the switch...case
decision structure comes in handy. In our code, it’s more user friendly to display breakfast, lunch, dinner, or snack instead of a meal number. Add this code just below the caloriesTotal
addition:
//Add a switch statement for a meal string var mealString = "" switch meal{ case .Breakfast: mealString = "breakfast&" case .Lunch: mealString = "lunch" case .Dinner: mealString = "dinner" case .Snack: mealString = "snack" }
We first make a new variable for our string. Then we use the switch
stating we are looking at options for our meal
variable. Within the brackets, we put case
and one of our enumeration values. Under that case is code which assigns the value of the strong. Unlike an if...else
clause, case
does not need a block for these statements. It assumes your next case
is the end of your block. However, you must be exhaustive. All values must be listed. If you do not list every value, you must include a default
case.
Now that we have a string to use, change the print to this:
print ( "Calories for " + mealString + " is \(caloriesTotal[mealIndex])")
Run your code. You will get a different output:
Calories for breakfast is 50
Breakfast is the most important meal of the day. Eat more breakfast.
Calories for dinner is 650
Calories for snack is 1150
Try not to snack
Methods in Enumerations
There’s a problem with this switch
statement. It is not very adaptable. For any use of my enumeration, I might want to get that string. Enumerations, like classes, can have methods. Under case Snack = 3
in the enum
add this:
func mealName() -> String{ return mealString }
Cut and paste the mealString
declaration and the switch
statement between the func
declaration and the return
. In the switch
, change mealString
to self
. Your code should look like this:
func mealName() -> String{ var mealString = "" switch self{ case .Breakfast: mealString = "breakfast" case .Lunch: mealString ="lunch" case .Dinner: mealString = "dinner" case .Snack: mealString = "snack" } return mealString }
Change the print
to this:
print ( "Calories for " + meal.mealName() +" is \(caloriesTotal[mealIndex])")
We called the function mealName
which returns our string. Run and we get the same results.
Default Values for Int Enums
Change the enum cases to this, then run again:
enum Meal:Int{ case Breakfast = 0 case Lunch case Dinner case Snack
You get the same results. An enum
for an Int
assumes that each value will increment by one, and you have only assigned the starting value of 0. Now try this:
enum Meal:Int{ case Breakfast case Lunch case Dinner case Snack
When you run this, the code still works. Only for a type of Int
, Swift’s enums assume a value of 0 and will increment by 1. This of course begs the question: Can you use other types, or no types at all?
Using Other Types
Open a new sandbox in your web browser. Remove the base code and add this:
import Foundation // Use of other types // any Int Float, Double, or String Works here. enum Meals:String{ case Breakfast = "breakfast" case Lunch = "lunch" case Dinner = "dinner" case Snack = "snack" } print(Meals.Breakfast.rawValue)
Run this and you will get breakfast
. We’ve so far used integer values for the enum
. We can use it to store strings like we did here. Change the type declaration to the appropriate type.
enum Meals:String
You can use any basic type for an enum
raw value including Int
, Float
, Double
, or String
. You cannot use a complex values such as an array, class or another enum
.
The Bare-Bones enum
Often we don’t need a value constant for our enumeration. We need a discrete set of values only. This basic enum
does that:
Meals{ case Breakfast case Lunch case Dinner case Snack } print (Meals.Breakfast)
Try this code in the sandbox. You will once again get Breakfast
in the output.There is a very important caution using this. An enum
like this has no rawValue
. Its only value is one of its four cases. Breakfast
is a value, but it is not a String
. You’ve created a type that only has the four values.
If you want to do this in a shorter version you can do this:
Meals{ case Breakfast,Lunch,Dinner,Snack } print (Meals.Breakfast)
The short version works for Int enums
with default values
enum Meals:Int{ case Breakfast,Lunch,Dinner, Snack } print(Meals.Lunch) print(Meals.Lunch.rawValue)
Associative Enumerations
So far, enumerations have been used as a constant. There is one more case that can have assigned values. Called Associative Enumerations they associate any value with a case of a enumerated value. Each case has its own independent type, and must be declared separately as a tuple. For example, let’s associate a calorie count and the food eaten with each meal.
We’ll use a class Food
for breakfast. So we don’t know what snack we had use an integer only for .Snack
enum Meals{ case Breakfast(Food) case Lunch(Int,String) case Dinner(Int,String) case Snack(Int) }
Getting a value from this is not as easy as rawValue
. You have to extract it in a switch statement. It may be in your code somewhere, or as I did here, add it to the enumeration.
enum Meals{ case Breakfast(Food) case Lunch(Int,String) case Dinner(Int,String) case Snack(Int) func print() -> String{ //return a string describing the meal switch self{ case let Breakfast(food): return "Breakfast: " + food.foodName + " \(food.calories) calories" case let Lunch(calories, foodName): return "Lunch: " + foodName + " \(food.calories) calories" case Dinner(calories, foodName): return ("Dinner: " + foodName + " calories: \(calories) ") case let Snack(calories): return ("A tasty snack of \(calories) calories") } } }
Define a class Food
to get this code to work:
class Food{ var calories:Int = 0 var foodName:String = "" init (calories:Int,foodName:String){ self.calories = calories self.foodName = foodName } }
We defined two properties, calories
and foodName
in our class. We also added an initializer to assign these values directly to a new instance. If you haven’t worked with initializers, I suggest you take a look at my tutorial on classes for more information on this.
After the enum
, let test it with this:
var myMeal = Meals.Breakfast(Food(calories:05,foodName:"Grande Brass Pig")) print (myMeal.print()) myMeal = .Lunch(380,"Grilled Chicken Sandwich") print (myMeal.print()) myMeal = .Dinner(1130,"Shwarma Fest Platter") print (myMeal.print()) myMeal = .Snack(280) print (myMeal.print())
Run the code. You should get this output
Breakfast: Grande Brass Pig 5 calories
Lunch: Grilled Chicken Sandwich 380 calories
Dinner: Shwarma Fest Platter calories: 1130
A tasty snack of 280 calories
Using enums in Real Life
I rarely use associative enums
. Most of the things you can do with them might be better done with classes. If I was writing a real calorie counter app like My Fitness Pal, I’d declare a class with an enum as a property like this:
//The enumeration Declared outside of the class it defaults to global for the target. enum Meals:Int{ case Breakfast case Lunch case Dinner case Snack } class FoodEntry{ var foodName:String var calories:Int var meal:Meals init(meal:Meals,foodName:String,calories:Int){ self.meal = meal self.foodName = foodName self.calories = calories } }
Make a new sandbox, and add the code above. I could include the enum
in the class definition. I generally don’t if I’m defining a class for a model. It’s likely that I will be using boolean expressions at some point to compare things. This
if food.meal == .Breakfast
is easier to write than
if food.meal == food.Meals.Breakfast
As I did earlier, I did use a constant Int
on my enumeration to use it in arrays. This FoodEntry
class could also be used in an array for my daily food list in a class for daily food entries:
class DailyFoodIntake{ var foodList:[FoodEntry] = [] var totalCalories = 0 let zeroMealCalories = [0,0,0,0] var mealCalories:[Int] = [0,0,0,0]
This class also keeps track of total calories for each meal and for the day. I can set up a few functions like this to use these properties:
func computeCalories(){ //recompute daily and meal calorie intake totalCalories = 0 mealCalories = zeroMealCalories for food in foodList{ totalCalories += food.calories mealCalories[food.meal.rawValue] += food.calories } print("Total Calories today: \(totalCalories)") print("\tBreakfast: \(mealCalories[Meals.Breakfast.rawValue]) calories") print("\tLunch: \(mealCalories[Meals.Lunch.rawValue]) calories") print("\tDinner: \(mealCalories[Meals.Dinner.rawValue]) calories") print("\tSnack: \(mealCalories[Meals.Snack.rawValue]) calories") } func addFoodForMeal(meal:Meals,foodName:String,calories:Int){ let food = FoodEntry(meal:meal,foodName:foodName,calories:calories) foodList += [food] computeCalories() }
The addFoodForMeal
method adds a food to the array and then calls the computeCalories
to recompute the totals for the day. This clears the totals first then adds everything up in a loop. For the meals, we use the rawValue
to get an index for the array to total the current value:
mealCalories[food.meal.rawValue] += food.calories
After computing, the totals get printed on the console, with a tab stop indentation. Again, we use the rawValue
to get an index.
print("\tBreakfast: \(mealCalories[Meals.Breakfast.rawValue]) calories") print("\tLunch: \(mealCalories[Meals.Lunch.rawValue]) calories") print("\tDinner: \(mealCalories[Meals.Dinner.rawValue]) calories") print("\tSnack: \(mealCalories[Meals.Snack.rawValue]) calories")
Add the following test data
let today = DailyFoodIntake() today.addFoodForMeal(.Breakfast,foodName:"coffee",calories:5) today.addFoodForMeal(.Breakfast,foodName:"oatmeal",calories:170) today.addFoodForMeal(.Lunch,foodName:"turkey dogs",calories: 90) today.addFoodForMeal(.Dinner,foodName:"Turkey Burger",calories: 340) today.addFoodForMeal(.Dinner,foodName:"Sweet Potato Fries",calories: 270) today.addFoodForMeal(.Snack,foodName:"Candy Bar",calories: 280) today.addFoodForMeal(.Snack,foodName:"Ice Cream mini bar",calories: 180)
Run the code. You’ll get output starting like this:
Total Calories today: 5
Breakfast: 5 calories
Lunch: 0 calories
Dinner: 0 calories
Snack: 0 calories
Total Calories today: 175
Breakfast: 175 calories
Lunch: 0 calories
Dinner: 0 calories
Snack: 0 calories
Total Calories today: 265
Breakfast: 175 calories
Lunch: 90 calories
Dinner: 0 calories
Snack: 0 calories
This is a little too much for our output. Notice we had to write out four print
statements. Since you can’t iterate an enum
this was necessary. Let’s do a modification to our code to better use our enum. Start by adding a function for a string in the enum
func mealsString()-> String{ switch self{ case Breakfast: return "breakfast" case Lunch: return "lunch" case Dinner: return "dinner" case Snack: return "snack" } }
Next, remove the print statements from computeCalories
. Change the addFoodForMeal
to this
func addFoodForMeal(meal:Meals,foodName:String,calories:Int){ let food = FoodEntry(meal:meal,foodName:foodName,calories:calories) foodList += [food] computeCalories() print("Total Calories today: \(totalCalories)") print("\tAdded \(calories) calories for total of \(mealCalories[meal.rawValue]) \(meal.mealsString()) calories") }
In this function, unlike computeCalories
, we have a value meal
that tells us which meal this is. Instead of printing all the meals, we only print the meal that changed. We use the mealsString
function to have a string value for our enum
, since we already have an integer one. Run this and you get a different output
Total Calories today: 5
Added 5 calories for total of 5 breakfast calories
Total Calories today: 175
Added 170 calories for total of 175 breakfast calories
Total Calories today: 265
Added 90 calories for total of 90 lunch calories
Total Calories today: 605
Added 340 calories for total of 340 dinner calories
Total Calories today: 875
Added 270 calories for total of 610 dinner calories
Total Calories today: 1155
Added 280 calories for total of 280 snack calories
Total Calories today: 1335
Added 180 calories for total of 460 snack calories
Enumeration is the way in swift to deal with options in a function or application easily. In the above example, we used meals, but any small set of constant options works well in one. If you have a changing list or a large one, you might use a different data type like an array or dictionary. As you explore the UIKit
API’s you’ll find many uses for enums
. You’ll undoubtedly find many more.
The Whole Code
You’ll find the code below for this lesson. Uncomment each part you want to use. You’ll also find it available in the IBM Swift Sandbox here
import Foundation //Uncomment code to run each iteration. // find this code at the IBM Swift sandbox at // swiftlang.ng.bluemix.net/#/repl/057089281afdef410b81365650399f0935617405bf64e7e54806b010e9af6c09 import Foundation //Uncomment code to run each iteration. /* // Iteration one -- Unreadable code var caloriesTotal = [0,0,0,0] //Breakfast,Lunch,Dinner,Snack calories func addCaloriesForMeal(meal:Int,calorie:Int){ //using the rawValue property of enum to get the integer assigned to the enum caloriesTotal[meal] = calorie // using an enum in a boolean expression -- yell at us if snacking if meal == 3 { print("Try not to snack") } } func printCaloriesForMeal(meal:Int){ //using the rawValue property of enum to get the integer assigned to the enum print ( "Calories for meal \(meal) is \(caloriesTotal[meal])") // using an enum in a comparison -- Breakfast less than 100 calories if (meal == 0) && (caloriesTotal[meal] < 100){ print("Breakfast is the most important meal of the day. Eat more breakfast.") } } addCaloriesForMeal(0,calorie:50) addCaloriesForMeal(2,calorie:650) addCaloriesForMeal(3,calorie:1150) printCaloriesForMeal(0) printCaloriesForMeal(3) */ /* // Iteration two add an enumeration and use value and rawValue enum Meal:Int{ case Breakfast = 0 case Lunch = 1 case Dinner = 2 case Snack = 3 } var caloriesTotal = [0,0,0,0] func addCaloriesForMeal(meal:Meal,calorie:Int){ //using the rawValue property of enum to get the integer assigned to the enum caloriesTotal[meal.rawValue] = calorie // using an enum in a boolean expression -- yell at us if snacking if meal == .Snack { print("Try not to snack") } } func printCaloriesForMeal(meal:Meal){ //using the rawValue property of enum to get the integer assigned to the enum print ( "Calories for meal \(meal.rawValue) is \(caloriesTotal[meal.rawValue])") // using an enum in a comparison -- Breakfast less than 100 calories if (meal == .Breakfast) && (caloriesTotal[meal.rawValue] < 100){ print("Breakfast is the most important meal of the day. Eat more breakfast.") } } addCaloriesForMeal(.Breakfast,calorie:50) addCaloriesForMeal(.Dinner,calorie:650) addCaloriesForMeal(.Snack,calorie:1150) printCaloriesForMeal(.Breakfast) printCaloriesForMeal(.Snack) */ /* // Iteration three add a switch to make a descriptive string // enum only has an intial value, values increment from there enum Meal:Int{ case Breakfast = 0 case Lunch case Dinner case Snack } var caloriesTotal = [0,0,0,0] func addCaloriesForMeal(meal:Meal,calorie:Int){ caloriesTotal[meal.rawValue] = calorie if meal == .Snack { print("Try not to snack") } } func printCaloriesForMeal(meal:Meal){ //Adding a Switch Statement here to create a string from the enum var mealString = "" switch meal{ case .Breakfast: mealString = "breakfast" case .Lunch: mealString = "lunch" case .Dinner: mealString = "Dinner" case .Snack: mealString = "Snack" } print ( "Calories for " + mealString + " is \(caloriesTotal[meal.rawValue])") if (meal == .Breakfast) && (caloriesTotal[meal.rawValue] < 100){ print("Breakfast is the most important meal of the day. Eat more breakfast.") } } addCaloriesForMeal(.Breakfast,calorie:50) addCaloriesForMeal(.Dinner,calorie:650) addCaloriesForMeal(.Snack,calorie:1150) printCaloriesForMeal(.Breakfast) printCaloriesForMeal(.Snack) */ /* // Iteration four -- using a function for the case in the enum // default is 0 for the first enum, so we don't assign anything // I tend to be paranoid and do like iteration 2 if I need raw values. enum Meal:Int{ case Breakfast = 0 case Lunch case Dinner case Snack // A function within the enum. // Uses self to get the enumeration's value func mealName() -> String{ var mealString = "" switch self{ case .Breakfast: mealString = "breakfast" case .Lunch: mealString = "lunch" case .Dinner: mealString = "Dinner" case .Snack: mealString = "snack" } return mealString } } var caloriesTotal = [0,0,0,0] func addCaloriesForMeal(meal:Meal,calorie:Int){ caloriesTotal[meal.rawValue] = calorie if meal == .Snack { print("Try not to snack") } } func printCaloriesForMeal(meal:Meal){ /*var mealString = "" switch meal{ case .Breakfast: mealString = "breakfast" case .Lunch: mealString = "lunch" case .Dinner: mealString = "Dinner" case .Snack: mealString = "Snack" }*/ print ( "Calories for " + meal.mealName() + " is \(caloriesTotal[meal.rawValue])") if (meal == .Breakfast) && (caloriesTotal[meal.rawValue]< 100){ print("Breakfast is the most important meal of the day. Eat more breakfast.") } } addCaloriesForMeal(.Breakfast,calorie:50) addCaloriesForMeal(.Dinner,calorie:650) addCaloriesForMeal(.Snack,calorie:1150) printCaloriesForMeal(.Breakfast) printCaloriesForMeal(.Snack) */ /* // Use of other types // any Int Float, Double, or String Works here. enum Meals:String{ case Breakfast = "breakfast" case Lunch = "lunch" case Dinner = "dinner" case Snack = "snack" } print(Meals.Breakfast.rawValue) */ /* // Basic enum to make a discrete set of values enum Meals{ case Breakfast case Lunch case Dinner case Snack } print (Meals.Breakfast) */ /* //If you want to do this in a shorter version you can do this: enum Meals{ case Breakfast,Lunch,Dinner,Snack } print (Meals.Breakfast) */ /* //The short version works for Int enums with default values enum Meals:Int{ case Breakfast,Lunch,Dinner,Snack } */ /* // Associative enums class Food{ var calories:Int = 0 var foodName:String = "" init (calories:Int,foodName:String){ self.calories = calories self.foodName = foodName } } enum Meals{ case Breakfast(Food) case Lunch(Int,String) case Dinner(Int,String) case Snack(Int) func print() -> String{ switch self{ case let Breakfast(food): return "Breakfast: " + food.foodName + " \(food.calories) calories" case let Lunch(calories, foodName ): return "Lunch: " + foodName + " \(calories) calories" case let Dinner(calories, foodName): return ("Dinner: " + foodName + " calories: \(calories) ") case let Snack(calories): return ("A tasty snack of \(calories) calories") } } } var myMeal = Meals.Breakfast(Food(calories:05,foodName:"Grande Brass Pig")) print (myMeal.print()) myMeal = .Lunch(380,"Grilled Chicken Sandwich") print (myMeal.print()) myMeal = .Dinner(1130,"Shwarma Fest Platter") print (myMeal.print()) myMeal = .Snack(280) print (myMeal.print()) */ /* // a realistic use of enumeration in a calorie counter. enum Meals:Int{ case Breakfast case Lunch case Dinner case Snack } class FoodEntry{ var foodName:String var calories:Int var meal:Meals init(meal:Meals,foodName:String,calories:Int){ self.meal = meal self.foodName = foodName self.calories = calories } } class DailyFoodIntake{ var foodList:[FoodEntry] = [] var totalCalories = 0 let zeroMealCalories = [0,0,0,0] var mealCalories:[Int] = [0,0,0,0] func computeCalories(){ //recompute daily and meal calorie intake totalCalories = 0 mealCalories = zeroMealCalories for food in foodList{ totalCalories += food.calories mealCalories[food.meal.rawValue] += food.calories } print("Total Calories today: \(totalCalories)") print("\tBreakfast: \(mealCalories[Meals.Breakfast.rawValue]) calories") print("\tLunch: \(mealCalories[Meals.Lunch.rawValue]) calories") print("\tDinner: \(mealCalories[Meals.Dinner.rawValue]) calories") print("\tSnack: \(mealCalories[Meals.Snack.rawValue]) calories") } func addFoodForMeal(meal:Meals,foodName:String,calories:Int){ let food = FoodEntry(meal:meal,foodName:foodName,calories:calories) foodList += [food] computeCalories() } } let today = DailyFoodIntake() today.addFoodForMeal(.Breakfast,foodName:"coffee",calories:5) today.addFoodForMeal(.Breakfast,foodName:"oatmeal",calories:170) today.addFoodForMeal(.Lunch,foodName:"turkey dogs",calories: 90) today.addFoodForMeal(.Dinner,foodName:"Turkey Burger",calories: 340) today.addFoodForMeal(.Dinner,foodName:"Sweet Potato Fries",calories: 270) today.addFoodForMeal(.Snack,foodName:"Candy Bar",calories: 280) today.addFoodForMeal(.Snack,foodName:"Ice Cream mini bar",calories: 180) */ /* // changes to the output to summarize the meal eaten and daily totals enum Meals:Int{ case Breakfast case Lunch case Dinner case Snack func mealsString()-> String{ switch self{ case Breakfast: return "breakfast" case Lunch: return "lunch" case Dinner: return "dinner" case Snack: return "snack" } } } class FoodEntry{ var foodName:String var calories:Int var meal:Meals init(meal:Meals,foodName:String,calories:Int){ self.meal = meal self.foodName = foodName self.calories = calories } } class DailyFoodIntake{ var foodList:[FoodEntry] = [] var totalCalories = 0 let zeroMealCalories = [0,0,0,0] var mealCalories:[Int] = [0,0,0,0] func computeCalories(){ //recompute daily and meal calorie intake totalCalories = 0 mealCalories = zeroMealCalories for food in foodList{ totalCalories += food.calories mealCalories[food.meal.rawValue] += food.calories } } func addFoodForMeal(meal:Meals,foodName:String,calories:Int){ let food = FoodEntry(meal:meal,foodName:foodName,calories:calories) foodList += [food] computeCalories() print("Total Calories today: \(totalCalories)") print("\tAdded \(calories) calories for total of \(mealCalories[meal.rawValue]) \(meal.mealsString()) calories") } } let today = DailyFoodIntake() today.addFoodForMeal(.Breakfast,foodName:"coffee",calories:5) today.addFoodForMeal(.Breakfast,foodName:"oatmeal",calories:170) today.addFoodForMeal(.Lunch,foodName:"turkey dogs",calories: 90) today.addFoodForMeal(.Dinner,foodName:"Turkey Burger",calories: 340) today.addFoodForMeal(.Dinner,foodName:"Sweet Potato Fries",calories: 270) today.addFoodForMeal(.Snack,foodName:"Candy Bar",calories: 280) today.addFoodForMeal(.Snack,foodName:"Ice Cream mini bar",calories: 180) */
Leave a Reply