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 ClasscalledEntryTableViewCellthat 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
entryof an optional typeEntryvar entry: Entry? -
Create a function called
updateUIthat takes in anInt. This will update the UI Elements on ourUITableViewCell. Note that we are not setting ourhigherorLowerLabelyet 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 ClasscalledEntryListTableViewController- be sure to subclass our TableView as type
EntryListTableViewController
- be sure to subclass our TableView as type
- Remove all functions except
ViewDidLoadnumberOfRowsInSectioncellForRowAt
- Create a variable called
averageHappinessof typeInt, give it a preset value of0 - In our
numberOfRowsInSectionreturnEntryController.entries.count - In our
cellForRowAtguard let our cell to be of typeEntryTableViewCellguard 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
EntryTableViewCelldeclare a new protocol calledEntryCellDelegateof typeclassabove ourEntryTableViewCellclass - Inside our protocol declare a function called
switchToggledthat takes in aEntrytableViewCell - Inside our
EntryTableViewCellclass create a new property calleddelegateof typeEntryCellDelegate? - Create an
IBActionfor theUISwitchwith a sender ofUISwitch - Inside the
UIActioncall our delegatesswitchToggledfunction passing inself - Back on our
EntryListTableViewControllercreate an extension of typeEntryCellDelegateand conform to all protocols. - Inside of our newly made
switchToggledfunction add a print statement for that says “switchToggled” for testing purposes - In our
CellForRowAtaddcell.delegate = selfbefore we return the cell - Run the app and make sure that “switchToggled” is being printed
- Create a new function in our
EntryListTableViewControllercalledupdateHappinessthat 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
switchToggledfunction 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
.swiftfile calledNotificationKeysin ourResourcesfolder - Inside of our
NotificationKeyscreate a struct calledConstantsthe contains a static property callednotificationKey. Set it equal toNotification.Name(rawValue: “didChangeHappiness”) - On our
averageHappinessadd 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
EntryTableViewCellcreate a function calledaddObserverthat 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
recalcHappinessthat 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”
}