For mobile 5/13'

Post on 14-Jun-2015

283 views 3 download

Tags:

transcript

Multi-Level KVOJakub Hladík

Key-Value Observing What?

• Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.

• alternatives you should already know:

• delegate/protocol

• NSNotification

• callback using @selector or block

9

KVC How?

- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(NSInteger)row{ ChildObject *child = [childrenArray objectAtIndex:row]; if ([[column identifier] isEqualToString:@"name"]) { return [child name]; }

if ([[column identifier] isEqualToString:@"age"]) { return [child age]; }

if ([[column identifier] isEqualToString:@"favoriteColor"]) { return [child favoriteColor]; }}

11

KVC How?

- (id)tableView:(NSTableView *)tableviewobjectValueForTableColumn:(id)column row:(NSInteger)row{ ChildObject *child = [childrenArray objectAtIndex:row]; return [child valueForKey:[column identifier]]; }

12

KVC Terminology

• properties:

• attributes (scalar, string, NSNumber, …)

• to-one relationships (self.otherObject, self.superView, …)

• to-many relationships (collection of objects – NSArray, NSSet, …)

• key (@”age”) – identifies object property

• path (@”superView.frame”, @”address.street”)

– dot.separated keys specifying a sequence of objects to traverse

13

Getting/Setting Attributes

– valueForKey:– valueForKeyPath:– dictionaryWithValuesForKeys:– valueForUndefinedKey:…

– setValue:forKeyPath:– setValuesForKeysWithDictionary:– setNilValueForKey:– setValue:forKey:– setValue:forUndefinedKey:…

14

Getting/Setting Attributes

@interface MyClass

@property NSString *stringProperty;@property NSInteger integerProperty;@property MyClass *linkedInstance;

@end

MyClass *myInstance = [[MyClass alloc] init];NSString *string = [myInstance valueForKey:@"stringProperty"];[myInstance setValue:@2 forKey:@"integerProperty"];

MyClass *anotherInstance = [[MyClass alloc] init];myInstance.linkedInstance = anotherInstance;[myInstance setValue:@2 forKeyPath:@"linkedInstance.integerProperty"];

15

Finally KVO

– observeValueForKeyPath:ofObject:change:context:

– addObserver:forKeyPath:options:context:– removeObserver:forKeyPath:– removeObserver:forKeyPath:context:…

– willChangeValueForKey:– didChangeValueForKey:– willChange:valuesAtIndexes:forKey:– didChange:valuesAtIndexes:forKey:…

16

KVO

17

KVO

18

Simple Observing[self setValue:[[self randomPhoneArray] mutableCopy] forKey:@"dataArray"];

// self.dataArray = [[self randomPhoneArray] mutableCopy];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"dataArray"]) { self.dataArray = change[NSKeyValueChangeNewKey]; [self.tableView reloadData]; }}

19

DemoSimple Observing

HPT-Multi-Level-KVObranch stage1

20

NSMutableArray Observing

- (void)insertDataObject:(id)object atIndex:(NSUInteger)index{ [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"dataArray"]; [self.dataArray insertObject:object atIndex:index]; [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"dataArray"];}

21

NSMutableArray Observing

- (void)removeDataObjectAtIndex:(NSUInteger)index{ [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"dataArray"]; [self.dataArray removeObjectAtIndex:index]; [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"dataArray"];}

22

NSMutableArray Observing

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"dataArray"]) { NSIndexSet *set = change[NSKeyValueChangeIndexesKey]; NSKeyValueChange valueChange = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; NSArray *new = change[NSKeyValueChangeNewKey];

switch (valueChange) { case NSKeyValueChangeInsertion: [self addObject:new.lastObject atIndex:set.lastIndex]; break; case NSKeyValueChangeRemoval: [self removeObjectAtIndex:set.lastIndex]; break; case NSKeyValueChangeSetting: self.dataArray = [new mutableCopy]; [self.tableView reloadData]; break; default: break; } }}

23

DemoNSMutableArray Change

Observing

HPT-Multi-Level-KVObranch stage2

24

Array Observing Simpler

- (void)insertDataObject:(id)object atIndex:(NSUInteger)index{ NSMutableArray *array = [self mutableArrayValueForKey:@"dataArray"]; [array insertObject:object atIndex:index];}

- (void)removeDataObjectAtIndex:(NSUInteger)index{ NSMutableArray *array = [self mutableArrayValueForKey:@"dataArray"]; [array removeObjectAtIndex:index];}

25

DemoNSMutableArray Change Observing Done Better

HPT-Multi-Level-KVObranch stage3

26

Nested Object Observing

• NSMutableArray in NSMutableArray ):

• Not possible without ugly hacks…

• NSNotifications… (:

[[NSNotificationCenter defaultCenter] postNotificationName:@"objectInsertedAtIndexPath" object:self userInfo:@{ @"object" : object, @"indexPath" : indexPath }];

27

Multi-Level Demo

Nested NSMutableArray Change Observing using NSNotification

HPT-Multi-Level-KVObranch stage4

28

Is That It?

29

No Way!

30

- (id)valueForUndefinedKey:(NSString *)key{ NSUInteger i = [key integerValue]; return self.dataArray[i];}

Model Change- (id)valueForUndefinedKey:(NSString *)key{ NSUInteger i = [key integerValue]; return self.dataArray[i];}

- (void)insertDataObject:(id)object atIndexPath:(NSIndexPath *)indexPath{ if (indexPath.section == self.dataArray.count) { [self insertDataObject:[NSMutableArray array] atIndex:indexPath.section]; } [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.row] forKey:[@(indexPath.section) description]]; NSMutableArray *array = self.dataArray[indexPath.section]; [array insertObject:object atIndex:indexPath.row]; [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.row] forKey:[@(indexPath.section) description]];}

31

Observer Change 1

- (void)addObserverForKey:(NSString *)key{ [[HPTDataService sharedService] addObserver:self forKeyPath:key options:NSKeyValueObservingOptionNew context:NULL];}

- (void)removeObserverForLastKey{ [[HPTDataService sharedService] removeObserver:self forKeyPath:[@(self.dataArray.count-1) description] context:NULL];}

32

Observer Change 2

- (void)addObject:(id)object atIndex:(NSUInteger)index{ [self.dataArray insertObject:object atIndex:index]; [self addObserverForKey:[@(self.dataArray.count-1) description]]; [self.tableView beginUpdates]; [self.tableView insertSections:[NSIndexSet indexSetWithIndex:index] withRowAnimation:UITableViewRowAnimationRight]; [self.tableView endUpdates];}

33

Final Working Multi-Level KVO Demo

YEAH!

HPT-Multi-Level-KVObranch stage5

34