Object-Oriented Programming: Beyond the Basics

Oct 17 2023 · Swift 5.9, iOS 17, Xcode 15

Lesson 03: Design Patterns

Demo 3

Episode complete

Play next episode

Next

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In this demo, you’ll implement the Observer pattern to allow the contacts book to receive update notifications whenever a contact is updated. Ideally, in a system with a user interface, the contacts book will also notify the UI to update, so it will reflect changes to individual contacts.

public protocol Subject: AnyObject {
}
public protocol Observer: AnyObject {
}
public protocol Observer: AnyObject {
  func subjectUpdated(subject: any Subject)
}
public protocol Subject: AnyObject {
  var observers: [Observer] { get set }
  func addObserver(_ obj: Observer) 
  func removeObserver(_ obj: Observer) 
  func broadcastUpdates() 
}
public extension Subject {
  func addObserver(_ obj: Observer) {
    observers.append(obj)
  }

  func removeObserver(_ obj: Observer) {
    observers.removeAll { item in
      item === obj
    }
  }

  func broadcastUpdates() {
    observers.forEach { observer in
      observer.subjectUpdated(subject: self)
    }
  }
}
public class ContactCard: Subject {
  public var observers: [Observer]
  ...
public init(firstName: String, lastName: String, phoneNumber: String) {
  self.firstName = firstName
  self.lastName = lastName
  self.phoneNumber = phoneNumber
  isCompany = false
  contactID = UUID()
  relatedContacts = []
  observers = [] // new code
}
extension ContactsBook: Observer {
  public func subjectUpdated(subject: Subject) {
    let index = contactsList.firstIndex { contact in
      contact === subject
    }

    guard let index else {
      return
    }
    print("Contact at index \(index) has been updated")
  }
}
ehabContact.set(phone: "333333333333")
ehabContact.set(phone: 44444444444)
timContact.set(firstName: "Nick", lastName: "Fury")
//print(ehabContact.contactInformation())
//print(kodeco.contactInformation())
//print(razeware.contactInformation())

//book1.printContacts()
//print("Contacts Book has \(contactsList.count) entries")
// print("Calling super from Person")

//print("Other contact is a Person too. Add 2-way relationship")
//print("Calling super from Company")

//print("Other contact is a company too. Adding 2-way relationship")
public func saveContact(contact: ContactCard) {
  contactsList.append(contact)
  contact.addObserver(self) // new code
}
public func addRelatedContact(_ contact: ContactCard) {
  relatedContacts.append(contact.contactID)
  broadcastUpdates() // new code
}

public func set(firstName: String, lastName: String) {
  self.firstName = firstName
  self.lastName = lastName
  broadcastUpdates() // new code
}

public func set(phone: String) {
  phoneNumber = phone
  broadcastUpdates() // new code
}

public func set(phone: Double) {
  phoneNumber = "\(phone)"
  broadcastUpdates() // new code
}
See forum comments
Cinema mode Download course materials from Github
Previous: Introduction 3 Next: Conclusion