distributing information agenda
play

DISTRIBUTING INFORMATION AGENDA What does information distribution - PowerPoint PPT Presentation

DISTRIBUTING INFORMATION AGENDA What does information distribution mean? Delegation Closures Notifications Property Observers Bindings / Key Value Observation INFORMATION DISTRIBUTION Mobile apps are highly interactive Multiple interfaces


  1. DISTRIBUTING INFORMATION

  2. AGENDA What does information distribution mean? Delegation Closures Notifications Property Observers Bindings / Key Value Observation

  3. INFORMATION DISTRIBUTION Mobile apps are highly interactive Multiple interfaces drive data changes: UI Network Main task is responding to events and distributing new data

  4. CODE LOCALITY FolderView Each piece of code needs well download Button Tapped defined responsibility (1) downloadImage Example: 
 (2) The code that triggers 
 EntryView Image (3) update Image network request is not 
 OtherView necessarily the code that 
 update Image is interested in response

  5. TYPE TO TYPE COMMUNICATION

  6. TYPE TO TYPE COMMUNICATION class UserView { class UserViewController: UIViewController { var userViewController: UserViewController? func infoButtonTapped() { func infoButtonTapped() { // communicate with business logic userViewController?.infoButtonTapped() } } } } Tight coupling!

  7. TYPE TO TYPE COMMUNICATION The UserView could call any method provided by UserViewController, including all the ones inherited from UIView Controller UserView can become dependent on UIViewController UserView has to deal with huge interface: func infoButtonTapped() //… init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) var view: UIView! func loadView() var nibName: String? { get } var nibBundle: NSBundle? { get } var storyboard: UIStoryboard? { get } //…

  8. TYPE TO TYPE COMMUNICATION Typically used to establish a life long connection Easy to use Results in tight coupling No tight interface for communication between two types Mostly only useful for 1-1 communication

  9. DELEGATION

  10. DELEGATION Create a formal protocol that describes the communication interface Use this protocol to create an indirect connection between the two types

  11. DELEGATION protocol UserViewResponder { func infoButtonTapped() } class UserView { class UserViewController: UIViewController, var delegate: UserViewResponder? UserViewResponder { func infoButtonTapped() { func infoButtonTapped() { responder?.infoButtonTapped() // communicate with business logic } } } } Indirection = looser coupling

  12. DELEGATION Typically used to establish a life long connection Decouples communication, easy to replace delegate with any other type conforming to protocol Tight interface that contains only methods that are relevant for this specific communication channel Mostly only useful for 1-1 communication

  13. CLOSURES

  14. CLOSURES typealias UserDetailsCallback = User? -> () class UserViewController: UIViewController { class APIClient { override func viewDidAppear(animated: Bool) { func userDetails(userId: String, callback: APIClient().userDetails("13") { user in UserDetailsCallback) { // do something with user // network request } callback(user) } } } } Indirection = looser coupling

  15. CLOSURE GOTCHAS Code locality Code locality class UserViewController: UIViewController { class UserViewController2: UIViewController { override func viewDidAppear(animated: Bool) { override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) super.viewDidAppear(animated) 
 APIClient().userDetails("13") { user in APIClient().userDetails("13", callback: receivedUser) // do something with user } } } func receivedUser(user: User?) { // do something with user } } }

  16. CLOSURE GOTCHAS Retain Cycles Object retains the callback class UserViewController: UIViewController { var callback: UserDetailsCallback? Callback retains the object through override func viewDidAppear(animated: Bool) { self reference callback = { user in self.showUser(user) } } Results in retain cycle func showUser(user: User?) { //... } }

  17. CLOSURE GOTCHAS No Retain Cycles Use capture list to capture self class UserViewController: UIViewController { weakly var callback: UserDetailsCallback? override func viewDidAppear(animated: Bool) { Callback will no longer retain self callback = { [unowned self] user in self.showUser(user) } } Breaks retain cycle! func showUser(user: User?) { //... } }

  18. CLOSURES Typically used for short lived relationships Decouples communication Provides a communication interface with only a single function Requires caution regarding code locality Need to be careful to avoid retain cycles

  19. NOTIFICATIONS

  20. NOTIFICATIONS Notifications allow us to broadcast information (1 to N) Sender has no information about which objects have subscribed to notifications

  21. NOTIFICATIONS Posting a notification: func synchronize() { // network request NSNotificationCenter.defaultCenter().postNotificationName( "MyApp.SynchronizationCompleted", object: self) } Notifications are delivered on the same thread on which they are posted! Optionally you can use a userData argument to attach arbitrary data to the notification

  22. NOTIFICATIONS Registering for Notifications: Specify which notification you want to listen to class Listener { Specify which method on which object init() { NSNotificationCenter.defaultCenter().addObserver(self, should be called once this notification selector: "syncComplete", name: nil, object: nil) occurs } @objc func syncComplete() { Mark the target method with @objc if // work print("ok") you are not subclassing from an } Objective-C object }

  23. NOTIFICATION GOTCHAS Don’t forget to unsubscribe! If a deallocated object is registered class Listener { with the notification center, your app deinit { NSNotificationCenter.defaultCenter().removeObserver(self) will crash on an attempt to deliver a } //… } notification to the dead object class UserViewController: UIViewController { override func viewDidDisappear(animated: Bool) { super.viewDidDisappear(animated) NSNotificationCenter.defaultCenter().removeObserver(self) } }

  24. NOTIFICATIONS Used for broadcasting information Easy to communicate with di ff erent parts of the program without explicit references No well defined communication interface / no type information Causes crashes if you forget to unregister Can create dependencies between code that should not be coupled

  25. PROPERTY OBSERVERS

  26. PROPERTY OBSERVERS class UserViewController: UIViewController { var label: UILabel! Implicitly propagate changes within var user: User? { didSet { an instance of a type if let label = label, let user = user { label.text = user.name } } } }

  27. PROPERTY OBSERVERS Used for information propagation within an instance Easy to use, type safe Not applicable in many scenarios

  28. BINDINGS / KEY VALUE OBSERVATION

  29. KEY VALUE OBSERVATION (KVO) Objective-C API that relies on the Objective-C Runtime Generates notifications when an observed property on an observed object changes Think: property observers for other objects

  30. KVO class Observer: NSObject { API was not designed for Swift! var user: User init(user: User) { self.user = user super.init() self.user.addObserver(self, forKeyPath: "name", options: NSKeyValueObservingOptions.New, context: nil) } override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if let newValue = change?[NSKeyValueChangeNewKey] { print("Name changed: \(newValue)") } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } } deinit { self.user.removeObserver(self, forKeyPath: "name") } }

  31. KVO Used to observe changing values on other objects Allows observation of (almost) any property without additional work on class that is being observed API doesn’t provide type information of observed values API is arcane, e.g. one callback for all observer properties Not available on Swift classes, need to inherit from NSObject and use the dynamic keyword

  32. KVO / BINDINGS Swift doesn’t have it’s own KVO mechanism, but there are third party alternatives and it’s easy to implement your own KVO alternative [1] One framework that provides KVO and Binding capabilities is Bond [2] [1]: Exploring KVO Alternatives with Swift [2]: Summer Academy lecture discussing Bond

  33. DYNAMIC PROPERTIES IN BOND Declaring an Observable property: var image: Observable<UIImage?> = Observable(nil) Setting an Observable property: image.value = otherImage

  34. OBSERVING NEW VALUES Calls callback whenever new value is available: post.likes.observe { [unowned self] users in self.likingUsers = users //… }

  35. OBSERVING NEW VALUES Updates image view whenever new value is available: post.image.bindTo(postImageView.bnd_image)

  36. BONDS Used to observe changing values on other objects Allows observation of (almost) any property without much additional work on class that is being observed Communication protocol is implicit, harder to understand for other developers

  37. SUMMARY Delegation Closures Notifications Property Observers Bindings / Key Value Observation

  38. ADDITIONAL RESOURCES NSNotificationCenter class reference Swift Language Reference: Property Observers NSHipster: Key-Value Observing Exploring KVO Alternatives with Swift Bond Framework on Github

Recommend


More recommend