Sometimes you need to send messages far and wide in your app. And NoficiationCenter is a way to do that. In this section we are going to use NotificationCenter to help us with logout.
Let's start by adding a logout button to our AccountSummaryViewController screen, and see why sending that message back to our AppDelegate is harder than it looks.
First let's add the logout button to our AccountSummaryViewController.
AccountSummaryViewController
lazy var logoutBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(logoutTapped))
barButtonItem.tintColor = .label
return barButtonItem
}()
extension AccountSummaryViewController {
private func setup() {
setupNavigationBar()
func setupNavigationBar() {
navigationItem.rightBarButtonItem = logoutBarButtonItem
}
}
// MARK: Actions
extension AccountSummaryViewController {
@objc func logoutTapped(sender: UIButton) {
}
}
If we run this logout button should now appear.
Discussion:
- Note how
labelis a color - Explain
lazy var- a different way of initializing controls
If we click on the button, it won't do anything. That's because we haven't yet hooked it up to our protocol-delegate.
Now this leads to an interesting question. How do we send logout as a message back to the AppDelegate?
If we look at our view hierarchy we can see we've got a pretty long way to go if we wanted to use protocol-delegate.
AppDelegate > MainViewController > AccountSummaryViewController
Better option here would be another communication pattern - NotificationCenter.
First let's add a new class in Utils to strongly type our notification names.
NSNotificationName
extension Notification.Name {
static let logout = Notification.Name("Logout")
}Then let's register for this event in our AppDelegate.
AppDelegate
loginViewController.delegate = self
onboardingViewController.delegate = self
registerForNotifications()
private func registerForNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(didLogout), name: .logout, object: nil)
}
@objc func didLogout() {Now that we are registered, we just need to fire the event when the user logs out.
AccountSummaryViewController
extension AccountSummaryViewController {
@objc func logoutTapped(sender: UIButton) {
NotificationCenter.default.post(name: .logout, object: nil)
}
}OK lets's test. 🎉
Discuss Pros / Cons of NotificationCenter.
- With great power comes great responsibility.
Add an eye to show password. Create a new extension.
UITextField+SecureToggle
import Foundation
import UIKit
let passwordToggleButton = UIButton(type: .custom)
extension UITextField {
func enablePasswordToggle(){
passwordToggleButton.setImage(UIImage(systemName: "eye.fill"), for: .normal)
passwordToggleButton.setImage(UIImage(systemName: "eye.slash.fill"), for: .selected)
passwordToggleButton.addTarget(self, action: #selector(togglePasswordView), for: .touchUpInside)
rightView = passwordToggleButton
rightViewMode = .always
}
@objc func togglePasswordView(_ sender: Any) {
isSecureTextEntry.toggle()
passwordToggleButton.isSelected.toggle()
}
}Call in LoginView.
LoginView
passwordTextField.delegate = self
passwordTextField.enablePasswordToggle()Notice how our label is getting truncated. Let's have a conversation with our UX folks and fix.
AccountSummaryCell
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.font = UIFont.preferredFont(forTextStyle: .body)
nameLabel.adjustsFontSizeToFitWidth = true
nameLabel.text = "Account name"
balanceLabel.translatesAutoresizingMaskIntoConstraints = false
balanceLabel.font = UIFont.preferredFont(forTextStyle: .body)
balanceLabel.textAlignment = .right
balanceLabel.adjustsFontSizeToFitWidth = true
balanceLabel.text = "Some balance"> git add .
> git commit -m "feat: Add logout button"





