• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Easy undo.key
 

Easy undo.key

on

  • 917 views

 

Statistics

Views

Total Views
917
Views on SlideShare
856
Embed Views
61

Actions

Likes
0
Downloads
5
Comments
0

2 Embeds 61

http://baltimorecocoa.com 49
http://baltimorecocoa.tumblr.com 12

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />

Easy undo.key Easy undo.key Presentation Transcript

  • A How-To for an Easy Undo
  • Last Time • Objective C • Tutorial resources • XCode projects
  • This Time • A simple, common pattern with Cocoa
  • Undo/Redo • You should have undo in your app.
  • The Theory of Undo @interface dot : NSObject { int x; int y; }
  • The Theory of Undo History of X @interface dot : NSObject { • x = 100; int x; int y; }
  • The Theory of Undo History of X @interface dot : NSObject { • x = 100; int x; int y; • x = 22; }
  • The Theory of Undo History of X @interface dot : NSObject { • x = 100; int x; int y; • x = 22; } •x=
  • The Theory of Undo History of X @interface dot : NSObject { int x; x = 22; • int y; } • x = 100; •x=
  • The Theory of Undo History of X x = 22; x = 100; •x=
  • The Theory of Undo Undo Stack x = 22; x = 100; •x=
  • The Theory of Undo Undo Stack x = 22; •x= x = 100;
  • The Theory of Undo Undo Stack x = 22; •x= x = 100;
  • The Theory of Undo Undo Stack x = 22; x= x = 100;
  • The Theory of Undo Undo Stack x = 22; x= x = 100;
  • The Theory of Undo Undo Stack Redo Stack x = 22; x= x = 100;
  • Undo Stack Redo Stack x = 22; x= x = 100;
  • Undo Stack Redo Stack
  • NSUndoManager Undo Stack Redo Stack
  • NSUndoManager
  • NSUndoManager
  • NSUndoManager Q: How many managers?
  • NSUndoManager Q: How many managers? A1: It depends.
  • NSUndoManager Q: How many managers? A1: It depends... A2: ...but often one per doc.
  • NSUndoManager Q: How many managers? A1: It depends... A2: ...but often one per doc. NSDocument
  • NSUndoManager Q: How many managers? A1: It depends... A2: ...but often one per doc. NSDocument eebie # 472: Co coa fr saved arked as un doc m not empty if undo stack
  • Registering Undos 1. Simple Undo 2. Invocation-based Undo
  • Simple Undo [self.document.undoManager registerUndoWithTarget: target selector: aSelector object: anObject];
  • Simple Undo: Example - (void) setX: (int) newX { NSUndoManager undoManager = self.document.undoManager; if (x != newX) { [undoManager registerUndoWithTarget: self selector: @selector(setX:) object: x]; [myObject setX:newX]; } }
  • Simple Undo: Example - (void) setX: (int) newX { NSUndoManager undoManager = self.document.undoManager; if (x != newX) { [undoManager registerUndoWithTarget: self selector: @selector(setX:) object: x]; ject [myObject setX:newX]; } } N ot a n ob
  • Simple Undo: Example - (void) setX: (NSNumber *) newX { NSUndoManager undoManager = self.document.undoManager; if (![x isEqual:newX]) { [undoManager registerUndoWithTarget: self selector: @selector(setX:) object: x]; [myObject setX:newX]; } }
  • Simple Undo: Example - (void) setX: (NSNumber *) newX { NSUndoManager undoManager = self.document.undoManager; if (![x isEqual:newX]) { [undoManager registerUndoWithTarget: self selector: @selector(setX:) object: x]; [myObject setX:newX]; } } Tip: Cocoa uses objects. You usually should too.
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>];
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; Magic
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation Magic
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation Magic
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation Magic
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation • “An action turned into an object.”
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation • “An action turned into an object.” • Contains: target, selector, arguments, etc.
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation • “An action turned into an object.” • Contains: target, selector, arguments, etc.
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; NSInvocation • “An action turned into an object.” • Contains: target, selector, arguments, etc. byte level
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens:
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens: • Prepare target - “incoming!”
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens: • Prepare target - “incoming!” • becomes an NSInvocation <any method> object
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens: • Prepare target - “incoming!” • becomes an NSInvocation <any method> object • NSUndoManager doesn’t respond to method> <any
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens: • Prepare target - “incoming!” • becomes an NSInvocation <any method> object • NSUndoManager doesn’t respond to method> <any
  • Invocation-based Undo [[undoManager prepareWithInvocationTarget: target] <any method>]; What happens: • Prepare target - “incoming!” • becomes an NSInvocation <any method> object • NSUndoManager doesn’t respond to method> <any • calls with the NSInvocation forwardInvocation:
  • Invocation Undo: Example - (void) setX: (int) newX { NSUndoManager undoManager = self.document.undoManager; if (oldX != newX) { [[undoManager prepareWithInvocationTarget:self] setX:oldX]; [myObject setX:newX]; } }
  • Invocation Undo: Example - (void) setX: (int) newX { NSUndoManager undoManager = self.document.undoManager; if (oldX != newX) { [[undoManager prepareWithInvocationTarget:self] setX:oldX]; [myObject setX:newX]; } } OK
  • Undo Details
  • Undo Details 1. [undoManager setActionName:@”What’s Changing”];
  • Undo Details 1. [undoManager setActionName:@”What’s Changing”]; 2. Memory management: what’s going on?
  • Undo Details 1. [undoManager setActionName:@”What’s Changing”]; 2. Memory management: what’s going on? • Simple - retains object, not target
  • Undo Details 1. [undoManager setActionName:@”What’s Changing”]; 2. Memory management: what’s going on? • Simple - retains object, not target • Invocation - Probably retained?
  • Undo Details 1. [undoManager setActionName:@”What’s Changing”]; 2. Memory management: what’s going on? • Simple - retains object, not target • Invocation - Probably retained? 3. Undo groupings
  • Undo Architecture • How do we make sure all changes are captured? • Parallel controller objects? • ...that gets repetitive...
  • Ta da!
  • Key/Value Observation (K
  • Key/Value * Observation (K (the basics)
  • K VO: What is it? • Built into base NSObject
  • K VO: What is it? • Built into base NSObject • Automated notifications of property changes
  • K VO: What is it? • Built into base NSObject • Automated notifications of property changes... • ...but allows for manual override
  • K VO: What’s a key? • A string that identifies a property
  • K VO: What’s a key? • A string that identifies a property • e.g. via an accessor method or instance variable
  • K VO: What’s a key? • A string that identifies a property • e.g. via an accessor method or instance variable These accessors... - (void) setHeight: (NSNumber *) newHeight; - (NSNumber *) height;
  • K VO: What’s a key? • A string that identifies a property • e.g. via an accessor method or instance variable These accessors... ...correspond to this key. - (void) setHeight: (NSNumber *) newHeight; @"height" - (NSNumber *) height;
  • K VO: How to use it. 1. Must be KVO compliant for properties you want to observe
  • K VO: How to use it. 1. Must be KVO compliant for properties you want to observe 2. Must register for each property
  • K VO: How to use it. 1. Must be KVO compliant for properties you want to observe 2. Must register for each property 3. Observer must handle the notification
  • 1. K VO Compliance Depends on what kind of property. • To-one • To-many (indexed) • To-many (unordered)
  • 1. K VO Compliance Depends on what kind of property: e.g. - (void • To-one ) setHe - (NSNu ight: ( mber *) NSNumbe height; r *) ne wHeight ; • To-many (indexed) • To-many (unordered)
  • 1. K VO Compliance Depends on what kind of property: e.g. - (void • To-one ) setHe - (NSNu ight: ( mber *) NSNumbe height; r *) ne wHeight ; • To-many (indexed) • To-many (unordered) - (NSUI e.g. - (NSEn - (id) nteger) umerato countOf r *) en MySet; memberO umerato fMySet: rOfMySe (id) an t; Object;
  • 2. K VO Registration [object addObserver: (NSObject *) anObserver forKeyPath: (NSString *) keyPath options: (NSKeyValueObservingOptions) options context: (void *) context];
  • 3. K VO Notifications - (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) object change: (NSDictionary *) change context: (void *) context
  • 3. K VO Notifications - (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) object change: (NSDictionary *) change context: (void *) context { int kindOfChange = [[change objectForKey:NSKeyValueChangeKindKey] intValue]; id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; id newValue = [change objectForKey:NSKeyValueChangeNewKey]; NSIndexSet *indexSet = [change objectForKey:NSKeyValueChangeIndexesKey]; ...
  • Put it all together...