Average Happiness is a single view application that allows the user to calculate their average happiness. Users can also toggle on and off which entries are included in the calculation.
Our custom cell with contain the UI elements of our UITableViewCell
and update the data within them
- Create a new
Cocoa Touch Class
calledEntryTableViewCell
that is a subclass ofUITableViewCell
- Delete all existing functions within our new cell class
- Drag out outlets for all UI elements on our tableview cell
- be sure to subclass our Cell as type
EntryTableViewCell
- be sure to subclass our Cell as type
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var higherorLowerLabel: UILabel!
@IBOutlet weak var isEnabledSwitch: UISwitch!
-
Create a variable called
entry
of an optional typeEntry
var entry: Entry?
-
Create a function called
updateUI
that takes in anInt
. This will update the UI Elements on ourUITableViewCell
. Note that we are not setting ourhigherorLowerLabel
yet as we don’t have a function to detect what it should be set too. We are building that next.
func updateUI(averageHappiness: Int) {
guard let entry = entry else {return}
titleLabel.text = “\(entry.title) -> \(entry.happiness)”
isEnabledSwitch.isOn = entry.isIncluded
higherorLowerLabel.text = entry.happiness >= averageHappiness ? “Higher” : “Lower”
}
- Create a new
Cocoa Touch Class
calledEntryListTableViewController
- be sure to subclass our TableView as type
EntryListTableViewController
- be sure to subclass our TableView as type
- Remove all functions except
ViewDidLoad
numberOfRowsInSection
cellForRowAt
- Create a variable called
averageHappiness
of typeInt
, give it a preset value of0
- In our
numberOfRowsInSection
returnEntryController.entries.count
- In our
cellForRowAt
guard let our cell to be of typeEntryTableViewCell
guard let cell = tableView.dequeueReusableCell(withIdentifier: “EntryCell”, for: indexPath) as? EntryTableViewCell else {return UITableViewCell()}
- Pass an entry to our cell then update the UI
///grabbing the entry that we want
let entry = EntryController.entries[indexPath.row]
///passing our entry to out function setEntry
cell.entry = entry
///Updating the UI or our cell
cell.updateUI(averageHappiness: averageHappiness)
Explain Protocols and Delegates Analogy that you can use * Intern * Has a list of stuff that the boss might want done and can tells the workers to do it * Boss * Tells his intern what he wants done and might give some information for the intern to pass on, (ex: and Int of bool) * Worker * Is prepared to do anything the boss might want to do * Gets told by the intern when to do a certain task
- Back on our
EntryTableViewCell
declare a new protocol calledEntryCellDelegate
of typeclass
above ourEntryTableViewCell
class - Inside our protocol declare a function called
switchToggled
that takes in aEntrytableViewCell
- Inside our
EntryTableViewCell
class create a new property calleddelegate
of typeEntryCellDelegate?
- Create an
IBAction
for theUISwitch
with a sender ofUISwitch
- Inside the
UIAction
call our delegatesswitchToggled
function passing inself
- Back on our
EntryListTableViewController
create an extension of typeEntryCellDelegate
and conform to all protocols. - Inside of our newly made
switchToggled
function add a print statement for that says “switchToggled” for testing purposes - In our
CellForRowAt
addcell.delegate = self
before we return the cell - Run the app and make sure that “switchToggled” is being printed
- Create a new function in our
EntryListTableViewController
calledupdateHappiness
that recalculates the average happiness
func updateHappiness() {
var happinessTotal = 0
//loops through all of our entries
for entry in EntryController.entries {
//If our entrys isIncluded is == true, then we add its happiness to happiness total
if entry.isIncluded {
happinessTotal += entry.happiness
}
}
//calculates our average happienss
averageHappiness = happinessTotal / EntryController.entries.filter({$0.isIncluded}).count
}
- Back inside our
switchToggled
function we need to update our update our cells info and our average Happiness, run the app
guard let indexPath = tableView.indexPath(for: cell) else {return}
let entry = EntryController.entries[indexPath.row]
EntryController.updateEntry(entry: entry)
updateHappiness()
Note: Explain Notifications and Observers, Analogy that you can use * Notifications are like a radio tower, and observers are like a radio, observers can only hear the station that they are tuned into
- Create a new
.swift
file calledNotificationKeys
in ourResources
folder - Inside of our
NotificationKeys
create a struct calledConstants
the contains a static property callednotificationKey
. Set it equal toNotification.Name(rawValue: “didChangeHappiness”)
- On our
averageHappiness
add a didSet that septs our a notification every time we update the variable. For the object passaveragehappiness
. Also set our title to the average happiness so we can see what it is in the application
var averageHappiness: Int = 0 {
/*
Everytime that we set out happiness level we post a notification that contains our notificationKey and our averageHappiness
*/
didSet {
NotificationCenter.default.post(name: Constants.notificationKey, object: averageHappiness)
self.title = "Average Happiness: \(averageHappiness)"
}
}
- On our
EntryTableViewCell
create a function calledaddObserver
that adds an observer listening for ournotificationKey
func createObserver() {
NotificationCenter.default.addObserver(self, selector:
#selector(self.recalcHappiness), name: Constants.notificationKey, object: nil)
}
- Next add an objC function called
recalcHappiness
that updates our cells average happiness label
@objc func recalcHappiness(notification: NSNotification) {
guard let averageHappiness = notification.object as? Int, let entry = entry else {return}
higherOrLowerLabel.text = entry.happiness >= averageHappiness ? “Higher” : “Lower”
}