Intro to Cocoa KVC/KVO and Bindings

33,144 views

Published on

Presentation for the CocoaHeads Mexico City's session from November 28th, 2008.

Published in: Technology
0 Comments
34 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
33,144
On SlideShare
0
From Embeds
0
Number of Embeds
437
Actions
Shares
0
Downloads
524
Comments
0
Likes
34
Embeds 0
No embeds

No notes for slide

Intro to Cocoa KVC/KVO and Bindings

  1. 1. KVC/KVO and Bindings quot;MVC with less codequot; CocoaHeads México 27-Nov-2008 1
  2. 2. Key Value Coding 2
  3. 3. What is it? • Access properties by name: • Every class essentially becomes a dictionary • Not a 'trick'. This is fundamental Cocoa programming. 3
  4. 4. What is it? • Access properties by name: [person name] [person setName:@quot;Sergioquot;] • Every class essentially becomes a dictionary • Not a 'trick'. This is fundamental Cocoa programming. 3
  5. 5. What is it? • Access properties by name: [person name] [person valueForKey:@quot;namequot;] [person setName:@quot;Sergioquot;] [person setValue:@quot;Sergioquot; forKey:@quot;namequot;] • Every class essentially becomes a dictionary • Not a 'trick'. This is fundamental Cocoa programming. 3
  6. 6. How it works • NSKeyValueCoding (informal) protocol • Implemented by NSObject • NSKeyValueCoding.h 4
  7. 7. Using key value coding 5
  8. 8. Code! Using key value coding 5
  9. 9. Accessor lookup 6
  10. 10. Accessor lookup 1. Search for a public accessor ('getLastName' or 'lastName') 6
  11. 11. Accessor lookup 1. Search for a public accessor ('getLastName' or 'lastName') 2. If not found, search for a private accessor method based on key ('_getLastName' or '_lastName'). 6
  12. 12. Accessor lookup 1. Search for a public accessor ('getLastName' or 'lastName') 2. If not found, search for a private accessor method based on key ('_getLastName' or '_lastName'). 3. If not found' search for an instance variable (_lastName or lastName) 6
  13. 13. Accessor lookup 1. Search for a public accessor ('getLastName' or 'lastName') 2. If not found, search for a private accessor method based on key ('_getLastName' or '_lastName'). 3. If not found' search for an instance variable (_lastName or lastName) 4. If not found, invoke valueForUndefinedKey: 6
  14. 14. No magic! • KVC uses the runtime information generated by the compiler • Easy to fake... 7
  15. 15. quot;Implementingquot; KVC quot;from scratchquot; 8
  16. 16. Code! quot;Implementingquot; KVC quot;from scratchquot; 8
  17. 17. Performance? • Every Objective-C message goes through objc_msgSend() anyways • KVC caches property lookups • Not likely to be the bottleneck 9
  18. 18. KVC, value types and nil • Property values are always of type id (reference type) • structs ➔ NSValue • numbers ➔ NSNumber • You should implement setNilValueForKey: 10
  19. 19. NSDictionary KVC • NSDictionary has a custom implementation of KVC that attempts to match keys against keys in the dictionary. NSDictionary *dictionary; [dictionary setValue:@quot;Sergioquot; forKey:@quot;namequot;]; 11
  20. 20. Practical uses of KVC • Used by UI bindigs • Key-based archiving (serialization) 12
  21. 21. More on KVC 13
  22. 22. Model Validation • Optional set of validation methods • Some views call automatically the validation methods • Important!: You are not supposed to reject the value in setValue:forKey: • validateValue:forKey:error: automatically calls: validate{property}:error: 14
  23. 23. Key Paths • Like file paths (/usr/local/bin) • Used to traverse an object graph: ”document.header.title” • valueForKeyPath:, setValue:forKeyPath: • Warning!: you cannot pass a keyPath if the selector is just 'forKey:' only to 'forKeyPath:' 15
  24. 24. Using key paths 16
  25. 25. Code! Using key paths 16
  26. 26. KVC and Array properties • No native support. You cannot pass indexes in key paths: • valueForKeyPath:@quot;order.items[1].pricequot; • Ask an array for a key, the array will ask all its elements and return an array of the resulting values. 17
  27. 27. Set and array operators • Arrays and sets support ‘aggregate’ keys: • @avg, @count, @max, @min, @sum, @distinctUnionOfArrays, @distinctUnionOfObjects, @distinctUnionOfSets, @unionOfArrays, @unionOfObjects, @unionOfSets • You can use this aggregate properties to bind to in IB NSNumber *total = [purchaseOrder valueForKeyPath: @quot;@sum.pricequot;]; 18
  28. 28. NSPredicates • You can build NSPredicates to use more complex queries, like And, Or, RegExps, method calling, etc. • Cocoa's 'LINQ' NSArray *severalObjects = [NSArray arrayWithObjects:@quot;Stigquot;, @quot;Shaffiqquot;, @quot;Chrisquot;, nil]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@quot;SELF IN %@quot;, severalObjects]; BOOL result = [predicate evaluateWithObject:@quot;Shaffiqquot;]; 19
  29. 29. The secret to KVC compliance... 20
  30. 30. The secret to KVC compliance... Just use the correct naming conventions for your accessors! (or Objective-C 2.0 properties) 20
  31. 31. Key Value Observing 21
  32. 32. What is it? • Change notifications to model classes • Observer pattern • Based on KVC 22
  33. 33. How it works • Subscribe: • addObserver:forKeyPath:options:context: • opitons: NSKeyValueObservingOptionOld NSKeyValueObservingOptionNew • Unsubscribe: • removeObserver:forKeyPath: • Receive notification: • observeValue:forKeyPath: ofObject:change:context: 23
  34. 34. Important! • Notification works by replacing your accessors. • This means that direct ivar access will not produce notifications! 24
  35. 35. Observing with KVO notifications 25
  36. 36. Code! Observing with KVO notifications 25
  37. 37. Derived properties • Example: fullName property that changes when lastName and firstName change • Implement: keyPathsForValuesAffectingValueForKey:, and return a set of all the properties that affect that keyPath. 26
  38. 38. Manual notifications • Example: dynamic value that changes a lot. Calculated value you only want to display at certain times • willChangeValueForKey:, didChangeValueForKey:, automaticallyNotifyObserversForKey: 27
  39. 39. Manual notifications and derived properties 28
  40. 40. Code! Manual notifications and derived properties 28
  41. 41. Careful! • addObserver:… does not throw an exception when you get the keyPath wrong. • If you observe a path with multiple stages, you should observer at every level in the path: • “document.header.title” 29
  42. 42. Observing Array changes • Difficult. You can't observe them at all • (in KVO, only the property is observed, not the value) • Option 1: mutableArrayValueForKey: • Returns a proxy (expensive) that sends notifications when modified • Option 2: Implement all the array- related accessors 30
  43. 43. KVC Accessor selector formats {property} memberOf{property}: set{property}: intersect{property}: insertObject:in{property}AtIndex: _set{property}: insert{property}:atIndexes: {property}ForKeyPath: removeObjectFrom{property}AtIndex: _{property}ForKeyPath: remove{property}AtIndexes: get{property} replaceObjectIn{property}AtIndex:withObject: _get{property} replace{property}AtIndexes:with{property}: is{property} add{property}Object: _is{property} remove{property}: validate{property}:error: remove{property}Object: countOf{property} add{property}: objectIn{property}AtIndex: getPrimitive{property} {property}AtIndexes: primitive{property} get{property}:range: setPrimitive{property}: enumeratorOf{property} 31
  44. 44. Observe array element changes • You can’t. You have to observe each of the elements individually • Solution: NSArrayController • Bind the 'contents' property to the array of interest and observe the path arrangedObjects.{propertyName} • For insertions and deletions, observe the arrangedObjects property directly. 32
  45. 45. Uses for KVO? • Coherence between multiple views and a model • Simplifying flow control • Simplifying undo implementation • Any kind of observer, not only UI views. • Binding controllers: NSController and NSArrayController are based on KVO 33
  46. 46. Bindings 34
  47. 47. What is it? “Allows you to establish a mediated connection between a view and a piece of data, “binding” them such that a change in one is reflected in the other” - Cocoa Bindings Programming Topics guide • Not restricted to 'views' and 'models'. General binding mechanism. 35
  48. 48. Manual binding • Call: bind:toObject:withKeyPath:options: on the ‘view’ object • The ‘view’ will use KVC/KVO • KVC to load the initial values • Receives notifications via KVO • Changes the ‘model’ with KVC 36
  49. 49. Manual bindings 37
  50. 50. Code! Manual bindings 37
  51. 51. Binding Controllers • Basic binding works without controllers! • Object controller: dumb wrapper around KVO • Array Controller: selection proxy for master- detail UI, and observing of arrays. • User Defaults Controller: Simulates KVC/KVO compliance! 38
  52. 52. Bindings in IB 39
  53. 53. Code! Bindings in IB 39
  54. 54. (if time permits) 40
  55. 55. One more thing... Value Transformers (if time permits) 40
  56. 56. Goal: Reduce 'glue' code 41
  57. 57. Goal: Reduce 'glue' code • Example: binding an 'enabled' control to a 'false' property 41
  58. 58. Goal: Reduce 'glue' code • Example: binding an 'enabled' control to a 'false' property • Example: showing an image for a string property 41
  59. 59. Goal: Reduce 'glue' code • Example: binding an 'enabled' control to a 'false' property • Example: showing an image for a string property • Example: handling null values on the model 41
  60. 60. Available value transformers: • NSNegateBooleanTransformer • NSIsNilTransformer • NSIsNotNilTransformer • NSUnarchiveFromDataTransformer • NSKeyedUnarchiveFromDataTransformer • Custom (write your own transformer!) 42
  61. 61. Value Transformers 43
  62. 62. Code! Value Transformers 43
  63. 63. Resources • Introduction to Cocoa Bindings Programming Topics (Apple) • Key Value Coding programming guide (Apple) • Key Value Observing programming guide (Apple) • Model Object Implementation Guide (Apple) • Late Night Cocoa episode 35: KVC/KVO with Stefen Frey • Introduction to Cocoa Bindings by Scott Stevenson • Cocoa Bindings Wiki page at Cocoadev.com 44
  64. 64. 45
  65. 65. The End 45

×