SlideShare a Scribd company logo
UIKit Dynamics

Renzo G. Pretto
iOS Developer
Who’s talking
Who’s talking
About me
Renzo 

iOS Developer

H-art

!

#pragma mark founder

renzo.pretto@pragmamark.org

!

@rgpretto
Conference Hashtag

#pragmaconf
Today Agenda
• Introduction and core concepts
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
• Custom effects: custom behaviors
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
• Custom effects: custom behaviors
• Advanced concepts
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
• Custom effects: custom behaviors
• Advanced concepts
• UIDynamicItem
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
• Custom effects: custom behaviors
• Advanced concepts
• UIDynamicItem
• Collection View
Today Agenda
• Introduction and core concepts
• Standard effects: dynamic behaviors
• Custom effects: custom behaviors
• Advanced concepts
• UIDynamicItem
• Collection View
• Conclusion
UIKit Dynamics
UIKit Dynamics
UIKit Dynamics
Architecture
UIDynamicAnimator
Architecture
UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior
Architecture
UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior
Architecture
UIDynamicAnimator

UIDynamicBehavior

View

UIDynamicBehavior

UIDynamicBehavior
Architecture
UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehavior

View

View

UIDynamicBehavior
Architecture
UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior

View

View

View
Architecture
UIDynamicAnimator

Reference view

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior

View

View

View
Architecture
UIDynamicAnimator

Reference view

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior

View

View

View
UIDynamicAnimator
UIDynamicAnimator

Reference view
UIDynamicAnimator
• Define the coordinate system

UIDynamicAnimator

Reference view
UIDynamicAnimator
• Define the coordinate system
• Wraps underline engine

UIDynamicAnimator

Reference view
UIDynamicAnimator
• Define the coordinate system
• Wraps underline engine
• Keeps track of all the associated behaviors

UIDynamicAnimator

Reference view
UIDynamicAnimator
• Define the coordinate system
• Wraps underline engine
• Keeps track of all the associated behaviors
• Run and optimize the animation

UIDynamicAnimator

Reference view
UIDynamicAnimator
• Define the coordinate system
UIDynamicAnimator
• Wraps underline engine
• Keeps track of all the associated behaviors
Reference view
• Run and optimize the animation
• Each dynamic animator is independent from other dynamic
animators
UIDynamicAnimator
• Define the coordinate system
UIDynamicAnimator
• Wraps underline engine
• Keeps track of all the associated behaviors
Reference view
• Run and optimize the animation
• Each dynamic animator is independent from other dynamic
animators

UIDynamicAnimator *dynamicAnimator;

!

dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView];

!

dynamicAnimator.delegate = self;
...

!

[dynamicAnimator addBehavior:firstBehavior];
[dynamicAnimator addBehavior:secondBehavior];
...
UIDynamicAnimator
• Define the coordinate system
UIDynamicAnimator
• Wraps underline engine
• Keeps track of all the associated behaviors
Reference view
• Run and optimize the animation
• Each dynamic animator is independent from other dynamic
animators

UIDynamicAnimator *dynamicAnimator;

!

dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView];

!

dynamicAnimator.delegate = self;
...

!

[dynamicAnimator addBehavior:firstBehavior];
[dynamicAnimator addBehavior:secondBehavior];
...
UIDynamicAnimator
• Define the coordinate system
UIDynamicAnimator
• Wraps underline engine
• Keeps track of all the associated behaviors
Reference view
• Run and optimize the animation
• Each dynamic animator is independent from other dynamic
animators

UIDynamicAnimator *dynamicAnimator;

!

dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView];

!

dynamicAnimator.delegate = self;
...

!

[dynamicAnimator addBehavior:firstBehavior];
[dynamicAnimator addBehavior:secondBehavior];
...
UIDynamicAnimator
• Define the coordinate system
UIDynamicAnimator
• Wraps underline engine
• Keeps track of all the associated behaviors
Reference view
• Run and optimize the animation
• Each dynamic animator is independent from other dynamic
animators

UIDynamicAnimator *dynamicAnimator;

!

dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView];

!

dynamicAnimator.delegate = self;
...

!

[dynamicAnimator addBehavior:firstBehavior];
[dynamicAnimator addBehavior:secondBehavior];
...
UIDynamicAnimatorDelegate
@protocol UIDynamicAnimatorDelegate <NSObject>

!

@optional
- (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator;
- (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator;

!

@end
UIDynamicAnimatorDelegate
@protocol UIDynamicAnimatorDelegate <NSObject>

!

@optional
- (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator;
- (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator;

!

@end

• Notify pausing and resuming of UIKit Dynamic animator
UIDynamicBehaviour

UIDynamicBehavior
UIDynamicBehaviour
UIDynamicAnimator
UIDynamicBehavior

• Associated to UIDynamicAnimator
UIDynamicBehaviour
UIDynamicAnimator
UIDynamicBehavior

• Associated to UIDynamicAnimator
• Add and remove behaviours to an animator at any times
UIDynamicBehaviour
UIDynamicAnimator
UIDynamicBehavior
View

View

• Associated to UIDynamicAnimator
• Add and remove behaviours to an animator at any times
• Usually associated to a view or a set of view
UIDynamicBehaviour
UIDynamicAnimator
UIDynamicBehavior
View

View

UIDynamicBehavior
View

• Associated to UIDynamicAnimator
• Add and remove behaviours to an animator at any times
• Usually associated to a view or a set of view
• Composed
UIDynamicBehaviour
UIDynamicAnimator
UIDynamicBehavior
View

View

UIDynamicBehavior
View

• Associated to UIDynamicAnimator
• Add and remove behaviours to an animator at any times
• Usually associated to a view or a set of view
• Composed
• Can be subclassed
Behaviors Common characteristics
• Initialized with items to animate
Behaviors Common characteristics
• Initialized with items to animate
• Items can be added to behavior at any times
Behaviors Common characteristics
• Initialized with items to animate
• Items can be added to behavior at any times
• Behaviour can be configured before or after add to an
animator
Behaviors Common characteristics
• Initialized with items to animate
• Items can be added to behavior at any times
• Behaviour can be configured before or after add to an
animator

• Behavior influence stops when behaviour is removed
Primitive behaviors
Default Behaviors
UIDynamicBehavior
Default Behaviors
UIDynamicBehavior

• Gravity

UIGravityBehavior
Default Behaviors
UIDynamicBehavior

• Gravity
• Collisions

UIGravityBehavior
UICollisionBehavior
Default Behaviors
UIDynamicBehavior

• Gravity
• Collisions
• Attachments

UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
Default Behaviors
UIDynamicBehavior

• Gravity
• Collisions
• Attachments
• Snap

UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
Default Behaviors
UIDynamicBehavior

• Gravity
• Collisions
• Attachments

UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior

• Snap

UISnapBehavior

• Forces

UIPushBehavior
Default Behaviors
UIDynamicBehavior

• Gravity
• Collisions
• Attachments

UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior

• Snap

UISnapBehavior

• Forces

UIPushBehavior

• Item properties

UIDynamicItemBehavior
UIGravityBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIGravityBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIGravityBehavior
UIGravityBehavior
@interface DPGravityViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end
@implementation DPGravityViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!
!

UIGravityBehavior *gravityBehavior;
gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UIGravityBehavior
@interface DPGravityViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end
@implementation DPGravityViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!
!

UIGravityBehavior *gravityBehavior;
gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UIGravityBehavior
@interface DPGravityViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end
@implementation DPGravityViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!
!

UIGravityBehavior *gravityBehavior;
gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UIGravityBehavior
@interface DPGravityViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end
@implementation DPGravityViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!
!

UIGravityBehavior *gravityBehavior;
gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UIGravityBehavior
@interface DPGravityViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end
@implementation DPGravityViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!
!

UIGravityBehavior *gravityBehavior;
gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UIGravityBehavior
• Defined by a gravity vector
@property (readwrite, nonatomic) CGVector gravityDirection;
UIGravityBehavior
• Defined by a gravity vector
@property (readwrite, nonatomic) CGVector gravityDirection;

or
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;
UIGravityBehavior
• Defined by a gravity vector
@property (readwrite, nonatomic) CGVector gravityDirection;

or
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;

• Default vector is (0.0, 1.0)
(0.0, 1.0)
UIGravityBehavior
• Defined by a gravity vector
@property (readwrite, nonatomic) CGVector gravityDirection;

or
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;

• Default vector is (0.0, 1.0)
Magnitude 1.0 accelerate view to 1000 points/s2
•

(0.0, 1.0)
UIGravityBehavior
• Defined by a gravity vector
@property (readwrite, nonatomic) CGVector gravityDirection;

or
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;

• Default vector is (0.0, 1.0)
Magnitude 1.0 accelerate view to 1000 points/s2
•
• Can add and remove items at any time
- (void)addItem:(id <UIDynamicItem>)item;
- (void)removeItem:(id <UIDynamicItem>)item;

(0.0, 1.0)
UICollisionBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UICollisionBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UICollisionBehavior
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
UICollisionBehavior
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPGravityCollisionViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
NSArray *items = @[self.greenView];

!

UICollisionBehavior *collisionBehavior;
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
UIGravityBehavior *gravityBehavior;
gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];

}
...
@end
Collision Boundaries
• Can specify different boundaries
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

• Segmentes
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

• Segmentes
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

• Bezier paths (approximated)
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
forPath:(UIBezierPath*)bezierPath;
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

• Segmentes
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

• Bezier paths (approximated)
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
forPath:(UIBezierPath*)bezierPath;
Collision Boundaries
• Can specify different boundaries
• Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

• Segmentes
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

• Bezier paths (approximated)
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier
forPath:(UIBezierPath*)bezierPath;

• Boundaries don't have an existence on screen
Collision Mode
• Property collisionmode
Collision Mode
• Property collisionmode
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
Collision Mode
• Property collisionmode
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries
Collision Mode
• Property collisionmode
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries
• UICollisionBehaviorModeItems
Collision Mode
• Property collisionmode
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries
• UICollisionBehaviorModeItems
• UICollisionBehaviorModeEverything

(default)
Tips
Tips
• Can use multiple collision behaviors
Tips
• Can use multiple collision behaviors
• Add and remove items to this behaviour anytime
- (void)addItem:(id <UIDynamicItem>)item;
- (void)removeItem:(id <UIDynamicItem>)item;
Tips
• Can use multiple collision behaviors
• Add and remove items to this behaviour anytime
- (void)addItem:(id <UIDynamicItem>)item;
- (void)removeItem:(id <UIDynamicItem>)item;

• Collision detection have CPU cost
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2;
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2;

• Methods that inform collision start /end between boundaries
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2;

• Methods that inform collision start /end between boundaries
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier;
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2;

• Methods that inform collision start /end between boundaries
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier;
UICollisionBehaviorDelegate
• Methods that inform collision start / end between view
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item1
withItem:(id <UIDynamicItem>)item2;

• Methods that inform collision start /end between boundaries
- (void)collisionBehavior:(UICollisionBehavior*)behavior
beganContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier
atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior
endedContactForItem:(id <UIDynamicItem>)item
withBoundaryIdentifier:(id <NSCopying>)identifier;

!

• Reference view has nil identifier
UIAttachmentBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIAttachmentBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIAttachmentBehavior
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
@interface DPAttachmentViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!

@implementation DPAttachmentViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIAttachmentBehavior *attachmentBehavior;
attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView
attachedToItem:self.redView];
[self.animator addBehavior:attachmentBehavior];

}

!

- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {

!

CGPoint anchorPoint = [gestureRecognizer locationInView:self.view];
self.redView.center = anchorPoint;
[self.animator updateItemUsingCurrentState:self.redView];

}
...
@end
UIAttachmentBehavior
UIAttachmentBehavior
UIAttachmentBehavior
• View connected to an attachment point
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;

• Two views connected together
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;

• Two views connected together
- (instancetype)initWithItem:(id <UIDynamicItem>)item1
attachedToItem:(id <UIDynamicItem>)item2;
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;

• Two views connected together
- (instancetype)initWithItem:(id <UIDynamicItem>)item1
attachedToItem:(id <UIDynamicItem>)item2;

• Specify connection point offset
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;

• Two views connected together
- (instancetype)initWithItem:(id <UIDynamicItem>)item1
attachedToItem:(id <UIDynamicItem>)item2;

• Specify connection point offset
- (instancetype)initWithItem:(id <UIDynamicItem>)item
offsetFromCenter:(UIOffset)offset
attachedToAnchor:(CGPoint)point;
UIAttachmentBehavior
• View connected to an attachment point
- (instancetype)initWithItem:(id <UIDynamicItem>)item
attachedToAnchor:(CGPoint)point;

• Two views connected together
- (instancetype)initWithItem:(id <UIDynamicItem>)item1
attachedToItem:(id <UIDynamicItem>)item2;

• Specify connection point offset
- (instancetype)initWithItem:(id <UIDynamicItem>)item
offsetFromCenter:(UIOffset)offset
attachedToAnchor:(CGPoint)point;
- (instancetype)initWithItem:(id <UIDynamicItem>)item1
offsetFromCenter:(UIOffset)offset1
attachedToItem:(id <UIDynamicItem>)item2
offsetFromCenter:(UIOffset)offset2;
Springs
• Springs
Springs
• Springs
@property (readwrite, nonatomic) CGFloat damping;
Springs
• Springs
@property (readwrite, nonatomic) CGFloat damping;
@property (readwrite, nonatomic) CGFloat frequency;
Springs
• Springs
@property (readwrite, nonatomic) CGFloat damping;
@property (readwrite, nonatomic) CGFloat frequency;
UISnapBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UISnapBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UISnapBehavior
UISnapBehavior
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
interface DPSnapViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@end

!

@implementation DPSnapViewController
...
- (void)viewDidLoad {
[super viewDidLoad];

!

}

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer {

!

CGPoint snapPoint = [gestureRecognizer locationInView:self.view];
if (nil != self.snapBehavior) {
[self.dynamicAnimator removeBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView
snapToPoint:snapPoint];
[self.animator addBehavior:self.snapBehavior];

}
...
@end
UISnapBehavior
• Snap view in place in non rotated state
UISnapBehavior
• Snap view in place in non rotated state
- (instancetype)initWithItem:(id <UIDynamicItem>)item
snapToPoint:(CGPoint)point;
UISnapBehavior
• Snap view in place in non rotated state
- (instancetype)initWithItem:(id <UIDynamicItem>)item
snapToPoint:(CGPoint)point;

• Customize the dumping effects
UISnapBehavior
• Snap view in place in non rotated state
- (instancetype)initWithItem:(id <UIDynamicItem>)item
snapToPoint:(CGPoint)point;

• Customize the dumping effects
@property (nonatomic, assign) CGFloat damping;
UIPushBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIPushBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIPushBehavior

~ =m~
F
a
UIPushBehavior
~
F =m~
a
UIPushBehavior
~
F = m ~ , apply force to views:
a
•
UIPushBehavior
~
F = m ~ , apply force to views:
a
•
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
UIPushBehavior
~
F = m ~ , apply force to views:
a
•
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• Force vector expressed in two way:
UIPushBehavior
~
F = m ~ , apply force to views:
a
•
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• Force vector expressed in two way:
@property (readwrite, nonatomic) CGVector pushDirection;
UIPushBehavior
~
F = m ~ , apply force to views:
a
•
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• Force vector expressed in two way:
@property (readwrite, nonatomic) CGVector pushDirection;

or
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;
UIPushBehavior
• Customize where apply this force in the view
UIPushBehavior
• Customize where apply this force in the view
UIPushBehavior
• Customize where apply this force in the view
- (void)setTargetOffsetFromCenter:(UIOffset)o
forItem:(id <UIDynamicItem>)item;
UIPushBehavior
• Customize where apply this force in the view
- (void)setTargetOffsetFromCenter:(UIOffset)o
forItem:(id <UIDynamicItem>)item;
UIPushBehavior
• Customize where apply this force in the view
- (void)setTargetOffsetFromCenter:(UIOffset)o
forItem:(id <UIDynamicItem>)item;
UIPushBehavior
• Customize where apply this force in the view
- (void)setTargetOffsetFromCenter:(UIOffset)o
forItem:(id <UIDynamicItem>)item;

• Can add and remove items at any time
UIPushBehavior
• Customize where apply this force in the view
- (void)setTargetOffsetFromCenter:(UIOffset)o
forItem:(id <UIDynamicItem>)item;

• Can add and remove items at any time
- (void)addItem:(id <UIDynamicItem>)item;
- (void)removeItem:(id <UIDynamicItem>)item;
UIPushBehavior Mode
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
• apply a very quick impulse
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
•

automatically disable itself after applying it
UIPushBehavior Mode
• Different mode to apply forces:
- (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous
• force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
•

automatically disable itself after applying it

• to re-enable: @property

(nonatomic, readwrite) BOOL active;
Example: force comparison

~
F =m~
a
~
F
~=
a
m
Example: gravity comparison
Feel The Force!
Feel The Force!
• Gravity
Feel The Force!
• Gravity
• views accelerate with the same rate
Feel The Force!
• Gravity
• views accelerate with the same rate
• Push behavior in continuos mode
Feel The Force!
• Gravity
• views accelerate with the same rate
• Push behavior in continuos mode
• the smaller views accelerate more
Feel The Force!
• Gravity
• views accelerate with the same rate
• Push behavior in continuos mode
• the smaller views accelerate more
• Push behavior in instantaneous mode
Feel The Force!
• Gravity
• views accelerate with the same rate
• Push behavior in continuos mode
• the smaller views accelerate more
• Push behavior in instantaneous mode
• view acquire velocity and then the velocity doesn’t change
Feel The Force!
• Gravity
• views accelerate with the same rate
• Push behavior in continuos mode
• the smaller views accelerate more
• Push behavior in instantaneous mode
• view acquire velocity and then the velocity doesn’t change
• the smaller views acquire more velocity
Unit of Measure
• Real world: Newton
Unit of Measure
• Real world: Newton
1 Newton accelerate 1Kg at a rate of 1 m/s2
•
Unit of Measure
• Real world: Newton
1 Newton accelerate 1Kg at a rate of 1 m/s2
•
• UIKit:
•  magnitude of 1.0 accelerate 100x100 point
view to 100 points/s2
Unit of Measure
• Real world: Newton
1 Newton accelerate 1Kg at a rate of 1 m/s2
•
• UIKit:
•  magnitude of 1.0 accelerate 100x100 point
view to 100 points/s2

• “UIKit Newton”
UIDynamicItemBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIDynamicItemBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIDynamicItemBehavior
• Customize dynamics properties for items
UIDynamicItemBehavior
• Customize dynamics properties for items
@property (readwrite, nonatomic) CGFloat elasticity;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property (readwrite, nonatomic) CGFloat elasticity;
@property (readwrite, nonatomic) CGFloat friction;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property (readwrite, nonatomic) CGFloat elasticity;
@property (readwrite, nonatomic) CGFloat friction;
@property (readwrite, nonatomic) CGFloat density;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat
CGFloat
CGFloat
CGFloat

elasticity;
friction;
density;
resistance;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat
CGFloat
CGFloat
CGFloat
CGFloat

elasticity;
friction;
density;
resistance;
angularResistance;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;

• Add linear velocity (points per second)
- (void)addLinearVelocity:(CGPoint)velocity
forItem:(id <UIDynamicItem>)item;
- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;

• Add linear velocity (points per second)
- (void)addLinearVelocity:(CGPoint)velocity
forItem:(id <UIDynamicItem>)item;
- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

• Add angular velocity (radians per second)
- (void)addAngularVelocity:(CGFloat)velocity
forItem:(id <UIDynamicItem>)item;
- (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;

• Add linear velocity (points per second)
- (void)addLinearVelocity:(CGPoint)velocity
forItem:(id <UIDynamicItem>)item;
- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

• Add angular velocity (radians per second)
- (void)addAngularVelocity:(CGFloat)velocity
forItem:(id <UIDynamicItem>)item;
- (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

• Can add and remove items at any time
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;

• Add linear velocity (points per second)
- (void)addLinearVelocity:(CGPoint)velocity
forItem:(id <UIDynamicItem>)item;
- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

• Add angular velocity (radians per second)
- (void)addAngularVelocity:(CGFloat)velocity
forItem:(id <UIDynamicItem>)item;
- (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

• Can add and remove items at any time
UIDynamicItemBehavior
• Customize dynamics properties for items
@property
@property
@property
@property
@property
@property

(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,
(readwrite,

nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)
nonatomic)

CGFloat elasticity;
CGFloat friction;
CGFloat density;
CGFloat resistance;
CGFloat angularResistance;
BOOL allowsRotation;

• Add linear velocity (points per second)
- (void)addLinearVelocity:(CGPoint)velocity
forItem:(id <UIDynamicItem>)item;
- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

• Add angular velocity (radians per second)
- (void)addAngularVelocity:(CGFloat)velocity
forItem:(id <UIDynamicItem>)item;
- (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

• Can add and remove items at any time
Custom behaviors
Custom Behavior
• Can subclass UIDynamicBehavior
Custom Behavior
• Can subclass UIDynamicBehavior
• add child behavior
- (void)addChildBehavior:(UIDynamicBehavior *)behavior;
- (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
@property (nonatomic, readonly, copy) NSArray* childBehaviors;
Custom Behavior
• Can subclass UIDynamicBehavior
• add child behavior
- (void)addChildBehavior:(UIDynamicBehavior *)behavior;
- (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
@property (nonatomic, readonly, copy) NSArray* childBehaviors;

• No CPU cost or any runtime difference
Example: gravity & collision
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
NSArray *items = @[...];

!

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
NSArray *items = @[...];

!

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
NSArray *items = @[...];

!

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
NSArray *items = @[...];

!

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
NSArray *items = @[...];

!

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior
- (instancetype)initWithItems:(NSArray *)items;
@end

!
!

@implementation DPGravityCollisionBehavior

!

- (instancetype)initWithItems:(NSArray *)items {
self = [super init];

!

!
}

!

if (self) {
UIGravityBehavior *gravity;
UICollisionBehavior *collision;
gravity =[[UIGravityBehavior alloc] initWithItems:items];
collision = [[UICollisionBehavior alloc] initWithItems:items];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self addChildBehavior:gravity];
[self addChildBehavior:collision];
}
return self;

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;

!
!
!
!
!
!!
!

NSArray *items = @[...];
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items];
coll.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:gravity];
[self.animator addBehavior:coll];

}

!

@end
Example: gravity & collision
@interface DPGravityCollisionViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator *animator;
@end

!
!

@implementation DPGravityCollisionViewController

!

- (void)viewDidLoad {
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;

!
!
!
!
!
!
!

NSArray *items = @[...];

DPGravityCollisionBehavior *gravityAndCollision;
gravityAndCollision= [[DPGravityCollisionBehavior alloc] initWithItems:items];
[self.animator addBehavior:gravityAndCollision];

}

!

@end
Action Block
• Can define per-step actions
Action Block
• Can define per-step actions
@property (nonatomic, copy) void (^action)(void);
Action Block
• Can define per-step actions
@property (nonatomic, copy) void (^action)(void);

• UIDynamicAnimator invoke this block in each simulation step
Action Block
• Can define per-step actions
@property (nonatomic, copy) void (^action)(void);

• UIDynamicAnimator invoke this block in each simulation step

• So performance are crucial
UIDynamicItem protocol
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end

• All items animated by UIKit Dynamics must implement this
protocol
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end

• All items animated by UIKit Dynamics must implement this
protocol

• Describe what UIKit Dynamics needs to animate an item
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end

• All items animated by UIKit Dynamics must implement this
protocol

• Describe what UIKit Dynamics needs to animate an item
• position: center
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end

• All items animated by UIKit Dynamics must implement this
protocol

• Describe what UIKit Dynamics needs to animate an item
• position: center
• size: bounds
UIDynamicItem Protocol
@protocol UIDynamicItem <NSObject>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!

@end

• All items animated by UIKit Dynamics must implement this
protocol

• Describe what UIKit Dynamics needs to animate an item
• position: center
• size: bounds
• angle: transform (only 2D-transform)
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical

• After grab the initial state every external change to center,
bounds,

and transform will be ignored
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical

• After grab the initial state every external change to center,
bounds,

and transform will be ignored

• A dynamic item should always have a valid initial state
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical

• After grab the initial state every external change to center,
bounds,

and transform will be ignored

• A dynamic item should always have a valid initial state
• need a size
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical

• After grab the initial state every external change to center,
bounds,

and transform will be ignored

• A dynamic item should always have a valid initial state
• need a size
• need a reasonable position
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
• When adding the item to an animator for the first time
• center and transform are set on every animation tick
• methods performances are critical

• After grab the initial state every external change to center,
bounds,

and transform will be ignored

• A dynamic item should always have a valid initial state
• need a size
• need a reasonable position
UIDynamicItem Protocol
• All items animated by UIKit Dynamics must implement this
protocol
UIDynamicItem Protocol
• All items animated by UIKit Dynamics must implement this
protocol

• UIView conforms to protocol
@interface UIView : UIResponder < NSCoding, UIAppearance,
UIAppearanceContainer, UIDynamicItem > { ... }
UIDynamicItem Protocol
• All items animated by UIKit Dynamics must implement this
protocol

• UIView conforms to protocol
@interface UIView : UIResponder < NSCoding, UIAppearance,
UIAppearanceContainer, UIDynamicItem > { ... }

• UICollectionViewLayoutAttributes conforms to protocol
@interface UICollectionViewLayoutAttributes : NSObject < NSCopying,
UIDynamicItem > { ... }
UIDynamicItem Protocol
• All items animated by UIKit Dynamics must implement this
protocol

• UIView conforms to protocol
@interface UIView : UIResponder < NSCoding, UIAppearance,
UIAppearanceContainer, UIDynamicItem > { ... }

• UICollectionViewLayoutAttributes conforms to protocol
@interface UICollectionViewLayoutAttributes : NSObject < NSCopying,
UIDynamicItem > { ... }

• Custom class can conform to protocol
@interface DPDynamicObject : NSObject < UIDynamicItem > { ... }
Architecture
UIDynamicAnimator

Reference view

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior

View

View

View
Architecture
UIDynamicAnimator

Reference view

UIDynamicBehavior

UIDynamicBehavior

UIDynamicBehavior

NSObject!
<UIDynamicItem>

NSObject!
<UIDynamicItem>

NSObject!
<UIDynamicItem>
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!
@end
!
!
@implementation
!

DPDynamicObject

- (CGRect)bounds {
return CGRectMake(0.0, 0.0, 100.0, 100.0);
}

!

- (CGPoint)center {
return CGPointMake(50.0, 50.0);
}

!

- (void)setCenter:(CGPoint)center {
NSLog(@"Center = %@", NSStringFromCGPoint(center));
}

!

- (CGAffineTransform)transform {
return CGAffineTransformIdentity;
}

!

- (void)setTransform:(CGAffineTransform)transform {
NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform));
}

!

@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!
@end
!
!
@implementation
!

DPDynamicObject

- (CGRect)bounds {
return CGRectMake(0.0, 0.0, 100.0, 100.0);
}

!

- (CGPoint)center {
return CGPointMake(50.0, 50.0);
}

!

- (void)setCenter:(CGPoint)center {
NSLog(@"Center = %@", NSStringFromCGPoint(center));
}

!

- (CGAffineTransform)transform {
return CGAffineTransformIdentity;
}

!

- (void)setTransform:(CGAffineTransform)transform {
NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform));
}

!

@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!
@end
!
!
@implementation
!

DPDynamicObject

- (CGRect)bounds {
return CGRectMake(0.0, 0.0, 100.0, 100.0);
}

!

- (CGPoint)center {
return CGPointMake(50.0, 50.0);
}

!

- (void)setCenter:(CGPoint)center {
NSLog(@"Center = %@", NSStringFromCGPoint(center));
}

!

- (CGAffineTransform)transform {
return CGAffineTransformIdentity;
}

!

- (void)setTransform:(CGAffineTransform)transform {
NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform));
}

!

@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!
@end
!
!
@implementation
!

DPDynamicObject

- (CGRect)bounds {
return CGRectMake(0.0, 0.0, 100.0, 100.0);
}

!

- (CGPoint)center {
return CGPointMake(50.0, 50.0);
}

!

- (void)setCenter:(CGPoint)center {
NSLog(@"Center = %@", NSStringFromCGPoint(center));
}

!

- (CGAffineTransform)transform {
return CGAffineTransformIdentity;
}

!

- (void)setTransform:(CGAffineTransform)transform {
NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform));
}

!

@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem>

!

@property (nonatomic, readwrite) CGPoint center;
@property (nonatomic, readonly) CGRect bounds;
@property (nonatomic, readwrite) CGAffineTransform transform;

!
@end
!
!
@implementation
!

DPDynamicObject

- (CGRect)bounds {
return CGRectMake(0.0, 0.0, 100.0, 100.0);
}

!

- (CGPoint)center {
return CGPointMake(50.0, 50.0);
}

!

- (void)setCenter:(CGPoint)center {
NSLog(@"Center = %@", NSStringFromCGPoint(center));
}

!

- (CGAffineTransform)transform {
return CGAffineTransformIdentity;
}

!

- (void)setTransform:(CGAffineTransform)transform {
NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform));
}

!

@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
@interface DPDynamicItemProtocolViewController : UIViewController
@property (strong, nonatomic) UIDynamicAnimator * animator;
@property (strong, nonatomic) DPDynamicObject *dynamicObject;
@end

!

@implementation DPDynamicItemProtocolViewController
...

!

- (void)viewDidLoad {
[super viewDidLoad];

!
!

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.dynamicObject = [[DPDynamicObject alloc] init];
UIGravityBehavior *g;
g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ];
UIDynamicItemBehavior *b;
b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ];
b.elasticity = 0.5f;
UICollisionBehavior *c;
c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ];
c.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:g];
[self.animator addBehavior:b];
[self.animator addBehavior:c];

}
...
@end
Example 1: conform to UIDynamicItem
Example 1: conform to UIDynamicItem
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17

!

18:58:05.598
18:58:05.609
18:58:05.611
18:58:05.626
18:58:05.629
18:58:05.642
18:58:05.645
18:58:05.659
18:58:05.661
18:58:05.675
18:58:05.677

DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]

Animator is running
Center = {50, 50.04797}
Transform = [1, 0, -0, 1,
Center = {50, 50.447464}
Transform = [1, 0, -0, 1,
Center = {50, 51.054173}
Transform = [1, 0, -0, 1,
Center = {50, 51.915657}
Transform = [1, 0, -0, 1,
Center = {50, 53.031506}
Transform = [1, 0, -0, 1,

18:58:08.742
18:58:08.744
18:58:08.759
18:58:08.761
18:58:08.775
18:58:08.777
18:58:08.792
18:58:08.794
18:58:08.809
18:58:08.810
18:58:08.812

DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]

Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Animator is stopped

0, 0]
0, 0]
0, 0]
0, 0]
0, 0]

...

!

2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17

0, 0]
0, 0]
0, 0]
0, 0]
0, 0]
Example 1: conform to UIDynamicItem
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17

!

18:58:05.598
18:58:05.609
18:58:05.611
18:58:05.626
18:58:05.629
18:58:05.642
18:58:05.645
18:58:05.659
18:58:05.661
18:58:05.675
18:58:05.677

DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]

Animator is running
Center = {50, 50.04797}
Transform = [1, 0, -0, 1,
Center = {50, 50.447464}
Transform = [1, 0, -0, 1,
Center = {50, 51.054173}
Transform = [1, 0, -0, 1,
Center = {50, 51.915657}
Transform = [1, 0, -0, 1,
Center = {50, 53.031506}
Transform = [1, 0, -0, 1,

18:58:08.742
18:58:08.744
18:58:08.759
18:58:08.761
18:58:08.775
18:58:08.777
18:58:08.792
18:58:08.794
18:58:08.809
18:58:08.810
18:58:08.812

DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]
DynamicsPlayground[771:60b]

Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Center = {50, 518.13135}
Transform = [1, 0, -0, 1,
Animator is stopped

0, 0]
0, 0]
0, 0]
0, 0]
0, 0]

...

!

2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17
2013-10-17

0, 0]
0, 0]
0, 0]
0, 0]
0, 0]
UIDynamicItem Use Case
• Can use a single dynamic item to animate different views
UIDynamicItem Use Case
• Can use a single dynamic item to animate different views
• Can map center or transform to something else
UIDynamicItem Use Case
• Can use a single dynamic item to animate different views
• Can map center or transform to something else
• To “animate” something that isn’t a view or a collection view
use a UIDynamicItem
UIDynamicItem Use Case
• Can use a single dynamic item to animate different views
• Can map center or transform to something else
• To “animate” something that isn’t a view or a collection view
use a UIDynamicItem
Example 2: remap center property
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem>

!
!

@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem>

!

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target;

!

@end

!
!

@protocol ResizableDynamicItem <UIDynamicItem>

!

@property (nonatomic, readwrite) CGRect bounds;

!

@end
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem>

!
!

@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem>

!

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target;

!

@end

!
!

@protocol ResizableDynamicItem <UIDynamicItem>

!

@property (nonatomic, readwrite) CGRect bounds;

!

@end
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem>

!
!

@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem>

!

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target;

!

@end

!
!

@protocol ResizableDynamicItem <UIDynamicItem>

!

@property (nonatomic, readwrite) CGRect bounds;

!

@end
Example 2: remap center property
#import "APLPositionToBoundsMapping.h"

!

@interface APLPositionToBoundsMapping ()
@property (nonatomic, strong) id<ResizableDynamicItem> target;
@end

!
@implementation
!

APLPositionToBoundsMapping

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target {
if ((self = [super init])) {
_target = target;
}
return self;
}

!

- (CGRect)bounds {
return self.target.bounds;
}

// Pass through

!

- (CGPoint)center {
return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height);
}

!

- (void)setCenter:(CGPoint)center {
self.target.bounds = CGRectMake(0, 0, center.x, center.y);
}

!

- (CGAffineTransform)transform {
return self.target.transform; // Pass through
}

!

- (void)setTransform:(CGAffineTransform)transform {
self.target.transform = transform; // Pass through
}
@end
Example 2: remap center property
#import "APLPositionToBoundsMapping.h"

!

@interface APLPositionToBoundsMapping ()
@property (nonatomic, strong) id<ResizableDynamicItem> target;
@end

!
@implementation
!

APLPositionToBoundsMapping

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target {
if ((self = [super init])) {
_target = target;
}
return self;
}

!

- (CGRect)bounds {
return self.target.bounds;
}

// Pass through

!

- (CGPoint)center {
return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height);
}

!

- (void)setCenter:(CGPoint)center {
self.target.bounds = CGRectMake(0, 0, center.x, center.y);
}

!

- (CGAffineTransform)transform {
return self.target.transform; // Pass through
}

!

- (void)setTransform:(CGAffineTransform)transform {
self.target.transform = transform; // Pass through
}
@end
Example 2: remap center property
#import "APLPositionToBoundsMapping.h"

!

@interface APLPositionToBoundsMapping ()
@property (nonatomic, strong) id<ResizableDynamicItem> target;
@end

!
@implementation
!

APLPositionToBoundsMapping

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target {
if ((self = [super init])) {
_target = target;
}
return self;
}

!

- (CGRect)bounds {
return self.target.bounds;
}

// Pass through

!

- (CGPoint)center {
return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height);
}

!

- (void)setCenter:(CGPoint)center {
self.target.bounds = CGRectMake(0, 0, center.x, center.y);
}

!

- (CGAffineTransform)transform {
return self.target.transform; // Pass through
}

!

- (void)setTransform:(CGAffineTransform)transform {
self.target.transform = transform; // Pass through
}
@end
Example 2: remap center property
#import "APLPositionToBoundsMapping.h"

!

@interface APLPositionToBoundsMapping ()
@property (nonatomic, strong) id<ResizableDynamicItem> target;
@end

!
@implementation
!

APLPositionToBoundsMapping

- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target {
if ((self = [super init])) {
_target = target;
}
return self;
}

!

- (CGRect)bounds {
return self.target.bounds;
}

// Pass through

!

- (CGPoint)center {
return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height);
}

!

- (void)setCenter:(CGPoint)center {
self.target.bounds = CGRectMake(0, 0, center.x, center.y);
}

!

- (CGAffineTransform)transform {
return self.target.transform; // Pass through
}

!

- (void)setTransform:(CGAffineTransform)transform {
self.target.transform = transform; // Pass through
}
@end
Example 2: remap center property
@import UIKit;

!
!

@interface APLCustomDynamicItemViewController : UIViewController
@end

!
!

@interface APLCustomDynamicItemViewController ()
@property (nonatomic, weak) IBOutlet UIButton *button1;
@property (nonatomic, readwrite) CGRect button1Bounds;
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end

!
!

@implementation APLCustomDynamicItemViewController

!

- (void)viewDidLoad {

!

// Save the button's initial bounds.
self.button1Bounds = self.button1.bounds;
// Force the button image to scale with its bounds.
self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill;

}

!

// ... continue

!

@end
Example 2: remap center property
@import UIKit;

!
!

@interface APLCustomDynamicItemViewController : UIViewController
@end

!
!

@interface APLCustomDynamicItemViewController ()
@property (nonatomic, weak) IBOutlet UIButton *button1;
@property (nonatomic, readwrite) CGRect button1Bounds;
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end

!
!

@implementation APLCustomDynamicItemViewController

!

- (void)viewDidLoad {

!

// Save the button's initial bounds.
self.button1Bounds = self.button1.bounds;
// Force the button image to scale with its bounds.
self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill;

}

!

// ... continue

!

@end
Example 2: remap center property
!
@implementation APLCustomDynamicItemViewController
!
...
!
- (IBAction)buttonAction:(id)sender {
!

// Reset the buttons bounds to their initial state.
self.button1.bounds = self.button1Bounds;
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

!

APLPositionToBoundsMapping *buttonBoundsDynamicItem;
buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender];
UIAttachmentBehavior *attachment;
attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem
attachedToAnchor:buttonBoundsDynamicItem.center];
[attachment setFrequency:2.0];
[attachment setDamping:0.3];
[animator addBehavior:attachment];
UIPushBehavior *pushBehavior;
pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem]
mode:UIPushBehaviorModeInstantaneous];
pushBehavior.angle = M_PI_4;
pushBehavior.magnitude = 2.0;
[animator addBehavior:pushBehavior];
self.animator = animator;

}
@end
Example 2: remap center property
!
@implementation APLCustomDynamicItemViewController
!
...
!
- (IBAction)buttonAction:(id)sender {
!

// Reset the buttons bounds to their initial state.
self.button1.bounds = self.button1Bounds;
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

!

!

APLPositionToBoundsMapping *buttonBoundsDynamicItem;
buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender];
UIAttachmentBehavior *attachment;
attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem
attachedToAnchor:buttonBoundsDynamicItem.center];
[attachment setFrequency:2.0];
[attachment setDamping:0.3];
[animator addBehavior:attachment];
UIPushBehavior *pushBehavior;
pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem]
mode:UIPushBehaviorModeInstantaneous];
pushBehavior.angle = M_PI_4;
pushBehavior.magnitude = 2.0;
[animator addBehavior:pushBehavior];
self.animator = animator;

}
@end
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics

More Related Content

Similar to #pragma conf 2013 - UIKit dynamics

iOS UIkit Dynamic
iOS UIkit DynamiciOS UIkit Dynamic
iOS UIkit Dynamic
Seta Cheam
 
NinjaScript 2010-10-14
NinjaScript 2010-10-14NinjaScript 2010-10-14
NinjaScript 2010-10-14
lrdesign
 
jQTouch and Titanium
jQTouch and TitaniumjQTouch and Titanium
jQTouch and Titanium
Marc Grabanski
 
Ui kit dynamics(1)
Ui kit dynamics(1)Ui kit dynamics(1)
Ui kit dynamics(1)
geniteamsolutions
 
Using Advanced Technology to Provide Enhanced, Device-based User Support
Using Advanced Technology to Provide Enhanced, Device-based User SupportUsing Advanced Technology to Provide Enhanced, Device-based User Support
Using Advanced Technology to Provide Enhanced, Device-based User Support
UBMCanon
 
Win8 development lessons learned jayway
Win8 development lessons learned jaywayWin8 development lessons learned jayway
Win8 development lessons learned jayway
Andreas Hammar
 
Flexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework WorldFlexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework World
FITC
 
Flexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework WorldFlexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework World
Kevin Ball
 
Yaron Inger - Enlight - Inside the app of the year
 Yaron Inger - Enlight - Inside the app of the year  Yaron Inger - Enlight - Inside the app of the year
Yaron Inger - Enlight - Inside the app of the year
tlv-ios-dev
 
jQTouch – Mobile Web Apps with HTML, CSS and JavaScript
jQTouch – Mobile Web Apps with HTML, CSS and JavaScriptjQTouch – Mobile Web Apps with HTML, CSS and JavaScript
jQTouch – Mobile Web Apps with HTML, CSS and JavaScript
Philipp Bosch
 
iOS Programming 101
iOS Programming 101iOS Programming 101
iOS Programming 101
rwenderlich
 
Intro to jQuery for Drupal
Intro to jQuery for DrupalIntro to jQuery for Drupal
Intro to jQuery for Drupal
jhamiltoorion
 
Style guide driven development
Style guide driven developmentStyle guide driven development
Style guide driven development
Arvid Torset
 
ios_summit_2016_korhan
ios_summit_2016_korhanios_summit_2016_korhan
ios_summit_2016_korhan
Korhan Bircan
 
Сергій Міськів, «SwiftUI: Animations»
Сергій Міськів, «SwiftUI: Animations»Сергій Міськів, «SwiftUI: Animations»
Сергій Міськів, «SwiftUI: Animations»
Sigma Software
 
Introducing collection views - Mark Pospesel
Introducing collection views - Mark PospeselIntroducing collection views - Mark Pospesel
Introducing collection views - Mark Pospesel
Jigar Maheshwari
 
storyboard時代のInterfaceBuilder
storyboard時代のInterfaceBuilderstoryboard時代のInterfaceBuilder
storyboard時代のInterfaceBuilder
Hiroyuki Fujikawa
 
Make your Backbone Application dance
Make your Backbone Application danceMake your Backbone Application dance
Make your Backbone Application dance
Nicholas Valbusa
 
Conductor vs Fragments
Conductor vs FragmentsConductor vs Fragments
Viper on Android
Viper on AndroidViper on Android

Similar to #pragma conf 2013 - UIKit dynamics (20)

iOS UIkit Dynamic
iOS UIkit DynamiciOS UIkit Dynamic
iOS UIkit Dynamic
 
NinjaScript 2010-10-14
NinjaScript 2010-10-14NinjaScript 2010-10-14
NinjaScript 2010-10-14
 
jQTouch and Titanium
jQTouch and TitaniumjQTouch and Titanium
jQTouch and Titanium
 
Ui kit dynamics(1)
Ui kit dynamics(1)Ui kit dynamics(1)
Ui kit dynamics(1)
 
Using Advanced Technology to Provide Enhanced, Device-based User Support
Using Advanced Technology to Provide Enhanced, Device-based User SupportUsing Advanced Technology to Provide Enhanced, Device-based User Support
Using Advanced Technology to Provide Enhanced, Device-based User Support
 
Win8 development lessons learned jayway
Win8 development lessons learned jaywayWin8 development lessons learned jayway
Win8 development lessons learned jayway
 
Flexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework WorldFlexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework World
 
Flexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework WorldFlexible UI Components for a Multi-Framework World
Flexible UI Components for a Multi-Framework World
 
Yaron Inger - Enlight - Inside the app of the year
 Yaron Inger - Enlight - Inside the app of the year  Yaron Inger - Enlight - Inside the app of the year
Yaron Inger - Enlight - Inside the app of the year
 
jQTouch – Mobile Web Apps with HTML, CSS and JavaScript
jQTouch – Mobile Web Apps with HTML, CSS and JavaScriptjQTouch – Mobile Web Apps with HTML, CSS and JavaScript
jQTouch – Mobile Web Apps with HTML, CSS and JavaScript
 
iOS Programming 101
iOS Programming 101iOS Programming 101
iOS Programming 101
 
Intro to jQuery for Drupal
Intro to jQuery for DrupalIntro to jQuery for Drupal
Intro to jQuery for Drupal
 
Style guide driven development
Style guide driven developmentStyle guide driven development
Style guide driven development
 
ios_summit_2016_korhan
ios_summit_2016_korhanios_summit_2016_korhan
ios_summit_2016_korhan
 
Сергій Міськів, «SwiftUI: Animations»
Сергій Міськів, «SwiftUI: Animations»Сергій Міськів, «SwiftUI: Animations»
Сергій Міськів, «SwiftUI: Animations»
 
Introducing collection views - Mark Pospesel
Introducing collection views - Mark PospeselIntroducing collection views - Mark Pospesel
Introducing collection views - Mark Pospesel
 
storyboard時代のInterfaceBuilder
storyboard時代のInterfaceBuilderstoryboard時代のInterfaceBuilder
storyboard時代のInterfaceBuilder
 
Make your Backbone Application dance
Make your Backbone Application danceMake your Backbone Application dance
Make your Backbone Application dance
 
Conductor vs Fragments
Conductor vs FragmentsConductor vs Fragments
Conductor vs Fragments
 
Viper on Android
Viper on AndroidViper on Android
Viper on Android
 

Recently uploaded

(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
Priyanka Aash
 
Feature sql server terbaru performance.pptx
Feature sql server terbaru performance.pptxFeature sql server terbaru performance.pptx
Feature sql server terbaru performance.pptx
ssuser1915fe1
 
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
Kief Morris
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
Tatiana Al-Chueyr
 
Data Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining DataData Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining Data
Safe Software
 
CiscoIconsLibrary cours de réseau VLAN.ppt
CiscoIconsLibrary cours de réseau VLAN.pptCiscoIconsLibrary cours de réseau VLAN.ppt
CiscoIconsLibrary cours de réseau VLAN.ppt
moinahousna
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
Shiv Technolabs
 
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
Muhammad Ali
 
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptxDublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Kunal Gupta
 
How Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdfHow Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdf
HackersList
 
IPLOOK Remote-Sensing Satellite Solution
IPLOOK Remote-Sensing Satellite SolutionIPLOOK Remote-Sensing Satellite Solution
IPLOOK Remote-Sensing Satellite Solution
IPLOOK Networks
 
Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...
chetankumar9855
 
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
Edge AI and Vision Alliance
 
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
maigasapphire
 
Choose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presenceChoose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presence
rajancomputerfbd
 
Google I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged SlidesGoogle I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged Slides
Google Developer Group - Harare
 
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
sunilverma7884
 
Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024
aakash malhotra
 
July Patch Tuesday
July Patch TuesdayJuly Patch Tuesday
July Patch Tuesday
Ivanti
 
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptxIntroduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
313mohammedarshad
 

Recently uploaded (20)

(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
(CISOPlatform Summit & SACON 2024) Digital Personal Data Protection Act.pdf
 
Feature sql server terbaru performance.pptx
Feature sql server terbaru performance.pptxFeature sql server terbaru performance.pptx
Feature sql server terbaru performance.pptx
 
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
[Talk] Moving Beyond Spaghetti Infrastructure [AOTB] 2024-07-04.pdf
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
 
Data Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining DataData Integration Basics: Merging & Joining Data
Data Integration Basics: Merging & Joining Data
 
CiscoIconsLibrary cours de réseau VLAN.ppt
CiscoIconsLibrary cours de réseau VLAN.pptCiscoIconsLibrary cours de réseau VLAN.ppt
CiscoIconsLibrary cours de réseau VLAN.ppt
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
 
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
Litestack talk at Brighton 2024 (Unleashing the power of SQLite for Ruby apps)
 
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptxDublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
Dublin_mulesoft_meetup_Mulesoft_Salesforce_Integration (1).pptx
 
How Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdfHow Social Media Hackers Help You to See Your Wife's Message.pdf
How Social Media Hackers Help You to See Your Wife's Message.pdf
 
IPLOOK Remote-Sensing Satellite Solution
IPLOOK Remote-Sensing Satellite SolutionIPLOOK Remote-Sensing Satellite Solution
IPLOOK Remote-Sensing Satellite Solution
 
Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...Amul milk launches in US: Key details of its new products ...
Amul milk launches in US: Key details of its new products ...
 
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
“Deploying Large Language Models on a Raspberry Pi,” a Presentation from Usef...
 
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
Girls Call Churchgate 9910780858 Provide Best And Top Girl Service And No1 in...
 
Choose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presenceChoose our Linux Web Hosting for a seamless and successful online presence
Choose our Linux Web Hosting for a seamless and successful online presence
 
Google I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged SlidesGoogle I/O Extended Harare Merged Slides
Google I/O Extended Harare Merged Slides
 
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
 
Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024Three New Criminal Laws in India 1 July 2024
Three New Criminal Laws in India 1 July 2024
 
July Patch Tuesday
July Patch TuesdayJuly Patch Tuesday
July Patch Tuesday
 
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptxIntroduction-to-the-IAM-Platform-Implementation-Plan.pptx
Introduction-to-the-IAM-Platform-Implementation-Plan.pptx
 

#pragma conf 2013 - UIKit dynamics

  • 1. UIKit Dynamics Renzo G. Pretto iOS Developer
  • 4. About me Renzo iOS Developer H-art ! #pragma mark founder renzo.pretto@pragmamark.org ! @rgpretto
  • 6. Today Agenda • Introduction and core concepts
  • 7. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors
  • 8. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors
  • 9. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts
  • 10. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem
  • 11. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View
  • 12. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View • Conclusion
  • 25. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator Reference view
  • 26. UIDynamicAnimator • Define the coordinate system • Wraps underline engine UIDynamicAnimator Reference view
  • 27. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors UIDynamicAnimator Reference view
  • 28. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors • Run and optimize the animation UIDynamicAnimator Reference view
  • 29. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators
  • 30. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators UIDynamicAnimator *dynamicAnimator; ! dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; ! dynamicAnimator.delegate = self; ... ! [dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
  • 31. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators UIDynamicAnimator *dynamicAnimator; ! dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; ! dynamicAnimator.delegate = self; ... ! [dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
  • 32. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators UIDynamicAnimator *dynamicAnimator; ! dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; ! dynamicAnimator.delegate = self; ... ! [dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
  • 33. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators UIDynamicAnimator *dynamicAnimator; ! dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; ! dynamicAnimator.delegate = self; ... ! [dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
  • 34. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end
  • 35. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end • Notify pausing and resuming of UIKit Dynamic animator
  • 38. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times
  • 39. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times • Usually associated to a view or a set of view
  • 40. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View UIDynamicBehavior View • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times • Usually associated to a view or a set of view • Composed
  • 41. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View UIDynamicBehavior View • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times • Usually associated to a view or a set of view • Composed • Can be subclassed
  • 42. Behaviors Common characteristics • Initialized with items to animate
  • 43. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times
  • 44. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times • Behaviour can be configured before or after add to an animator
  • 45. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times • Behaviour can be configured before or after add to an animator • Behavior influence stops when behaviour is removed
  • 49. Default Behaviors UIDynamicBehavior • Gravity • Collisions UIGravityBehavior UICollisionBehavior
  • 50. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior
  • 51. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments • Snap UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior
  • 52. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior
  • 53. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior • Item properties UIDynamicItemBehavior
  • 57. UIGravityBehavior @interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! ! UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 58. UIGravityBehavior @interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! ! UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 59. UIGravityBehavior @interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! ! UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 60. UIGravityBehavior @interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! ! UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 61. UIGravityBehavior @interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! ! UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 62. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection;
  • 63. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
  • 64. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude; • Default vector is (0.0, 1.0) (0.0, 1.0)
  • 65. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude; • Default vector is (0.0, 1.0) Magnitude 1.0 accelerate view to 1000 points/s2 • (0.0, 1.0)
  • 66. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude; • Default vector is (0.0, 1.0) Magnitude 1.0 accelerate view to 1000 points/s2 • • Can add and remove items at any time - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item; (0.0, 1.0)
  • 70. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 71. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 72. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 73. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 74. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 75. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 76. UICollisionBehavior @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; ! UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end
  • 77. Collision Boundaries • Can specify different boundaries
  • 78. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
  • 79. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
  • 80. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets; • Segmentes - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
  • 81. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets; • Segmentes - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; • Bezier paths (approximated) - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
  • 82. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets; • Segmentes - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; • Bezier paths (approximated) - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
  • 83. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets; • Segmentes - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; • Bezier paths (approximated) - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath; • Boundaries don't have an existence on screen
  • 85. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
  • 86. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries
  • 87. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems
  • 88. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems • UICollisionBehaviorModeEverything (default)
  • 89. Tips
  • 90. Tips • Can use multiple collision behaviors
  • 91. Tips • Can use multiple collision behaviors • Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
  • 92. Tips • Can use multiple collision behaviors • Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item; • Collision detection have CPU cost
  • 93. UICollisionBehaviorDelegate • Methods that inform collision start / end between view
  • 94. UICollisionBehaviorDelegate • Methods that inform collision start / end between view - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
  • 95. UICollisionBehaviorDelegate • Methods that inform collision start / end between view - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2; • Methods that inform collision start /end between boundaries
  • 96. UICollisionBehaviorDelegate • Methods that inform collision start / end between view - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2; • Methods that inform collision start /end between boundaries - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;
  • 97. UICollisionBehaviorDelegate • Methods that inform collision start / end between view - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2; • Methods that inform collision start /end between boundaries - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;
  • 98. UICollisionBehaviorDelegate • Methods that inform collision start / end between view - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2; • Methods that inform collision start /end between boundaries - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p; - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier; ! • Reference view has nil identifier
  • 102. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 103. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 104. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 105. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 106. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 107. UIAttachmentBehavior @interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! @implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } ! - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
  • 110. UIAttachmentBehavior • View connected to an attachment point
  • 111. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
  • 112. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together
  • 113. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
  • 114. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2; • Specify connection point offset
  • 115. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2; • Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point;
  • 116. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2; • Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point; - (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2;
  • 118. Springs • Springs @property (readwrite, nonatomic) CGFloat damping;
  • 119. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 120. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 125. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 126. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 127. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 128. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 129. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 130. UISnapBehavior interface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end ! @implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! } self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! - (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
  • 131. UISnapBehavior • Snap view in place in non rotated state
  • 132. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
  • 133. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; • Customize the dumping effects
  • 134. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; • Customize the dumping effects @property (nonatomic, assign) CGFloat damping;
  • 139. UIPushBehavior ~ F = m ~ , apply force to views: a •
  • 140. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 141. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way:
  • 142. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;
  • 143. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
  • 144. UIPushBehavior • Customize where apply this force in the view
  • 145. UIPushBehavior • Customize where apply this force in the view
  • 146. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 147. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 148. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 149. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item; • Can add and remove items at any time
  • 150. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item; • Can add and remove items at any time - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
  • 152. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 153. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous
  • 154. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active
  • 155. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate
  • 156. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate •UIPushBehaviorModeInstantaneous
  • 157. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate •UIPushBehaviorModeInstantaneous • apply a very quick impulse
  • 158. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate •UIPushBehaviorModeInstantaneous • apply a very quick impulse • view immediately acquire velocity (no acceleration)
  • 159. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate •UIPushBehaviorModeInstantaneous • apply a very quick impulse • view immediately acquire velocity (no acceleration) • automatically disable itself after applying it
  • 160. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active • views accelerate •UIPushBehaviorModeInstantaneous • apply a very quick impulse • view immediately acquire velocity (no acceleration) • automatically disable itself after applying it • to re-enable: @property (nonatomic, readwrite) BOOL active;
  • 161. Example: force comparison ~ F =m~ a ~ F ~= a m
  • 165. Feel The Force! • Gravity • views accelerate with the same rate
  • 166. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode
  • 167. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more
  • 168. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more • Push behavior in instantaneous mode
  • 169. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more • Push behavior in instantaneous mode • view acquire velocity and then the velocity doesn’t change
  • 170. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more • Push behavior in instantaneous mode • view acquire velocity and then the velocity doesn’t change • the smaller views acquire more velocity
  • 171. Unit of Measure • Real world: Newton
  • 172. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 •
  • 173. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 • • UIKit: •  magnitude of 1.0 accelerate 100x100 point view to 100 points/s2
  • 174. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 • • UIKit: •  magnitude of 1.0 accelerate 100x100 point view to 100 points/s2 • “UIKit Newton”
  • 178. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;
  • 179. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;
  • 180. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;
  • 181. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) CGFloat CGFloat CGFloat CGFloat elasticity; friction; density; resistance;
  • 182. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat CGFloat CGFloat CGFloat CGFloat elasticity; friction; density; resistance; angularResistance;
  • 183. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation;
  • 184. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
  • 185. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item; • Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
  • 186. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item; • Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item; • Can add and remove items at any time
  • 187. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item; • Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item; • Can add and remove items at any time
  • 188. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item; • Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item; • Can add and remove items at any time
  • 190. Custom Behavior • Can subclass UIDynamicBehavior
  • 191. Custom Behavior • Can subclass UIDynamicBehavior • add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior; @property (nonatomic, readonly, copy) NSArray* childBehaviors;
  • 192. Custom Behavior • Can subclass UIDynamicBehavior • add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior; @property (nonatomic, readonly, copy) NSArray* childBehaviors; • No CPU cost or any runtime difference
  • 193. Example: gravity & collision
  • 194. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; ! UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 195. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; ! UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 196. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; ! UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 197. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; ! UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 198. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; ! UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 199. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 200. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 201. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 202. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 203. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 204. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 205. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 206. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 207. Example: gravity & collision @interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end ! ! @implementation DPGravityCollisionBehavior ! - (instancetype)initWithItems:(NSArray *)items { self = [super init]; ! ! } ! if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; } return self; @end
  • 208. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; ! ! ! ! ! !! ! NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } ! @end
  • 209. Example: gravity & collision @interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end ! ! @implementation DPGravityCollisionViewController ! - (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; ! ! ! ! ! ! ! NSArray *items = @[...]; DPGravityCollisionBehavior *gravityAndCollision; gravityAndCollision= [[DPGravityCollisionBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityAndCollision]; } ! @end
  • 210. Action Block • Can define per-step actions
  • 211. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void);
  • 212. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void); • UIDynamicAnimator invoke this block in each simulation step
  • 213. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void); • UIDynamicAnimator invoke this block in each simulation step • So performance are crucial
  • 215. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end
  • 216. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol
  • 217. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item
  • 218. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item • position: center
  • 219. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item • position: center • size: bounds
  • 220. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item • position: center • size: bounds • angle: transform (only 2D-transform)
  • 221. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit
  • 222. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
  • 223. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick
  • 224. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical
  • 225. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical • After grab the initial state every external change to center, bounds, and transform will be ignored
  • 226. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical • After grab the initial state every external change to center, bounds, and transform will be ignored • A dynamic item should always have a valid initial state
  • 227. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical • After grab the initial state every external change to center, bounds, and transform will be ignored • A dynamic item should always have a valid initial state • need a size
  • 228. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical • After grab the initial state every external change to center, bounds, and transform will be ignored • A dynamic item should always have a valid initial state • need a size • need a reasonable position
  • 229. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time • center and transform are set on every animation tick • methods performances are critical • After grab the initial state every external change to center, bounds, and transform will be ignored • A dynamic item should always have a valid initial state • need a size • need a reasonable position
  • 230. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol
  • 231. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol @interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
  • 232. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol @interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... } • UICollectionViewLayoutAttributes conforms to protocol @interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... }
  • 233. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol @interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... } • UICollectionViewLayoutAttributes conforms to protocol @interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... } • Custom class can conform to protocol @interface DPDynamicObject : NSObject < UIDynamicItem > { ... }
  • 236. Example 1: conform to UIDynamicItem @interface DPDynamicObject : NSObject <UIDynamicItem> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end ! ! @implementation ! DPDynamicObject - (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } ! - (CGPoint)center { return CGPointMake(50.0, 50.0); } ! - (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } ! - (CGAffineTransform)transform { return CGAffineTransformIdentity; } ! - (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } ! @end
  • 237. Example 1: conform to UIDynamicItem @interface DPDynamicObject : NSObject <UIDynamicItem> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end ! ! @implementation ! DPDynamicObject - (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } ! - (CGPoint)center { return CGPointMake(50.0, 50.0); } ! - (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } ! - (CGAffineTransform)transform { return CGAffineTransformIdentity; } ! - (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } ! @end
  • 238. Example 1: conform to UIDynamicItem @interface DPDynamicObject : NSObject <UIDynamicItem> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end ! ! @implementation ! DPDynamicObject - (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } ! - (CGPoint)center { return CGPointMake(50.0, 50.0); } ! - (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } ! - (CGAffineTransform)transform { return CGAffineTransformIdentity; } ! - (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } ! @end
  • 239. Example 1: conform to UIDynamicItem @interface DPDynamicObject : NSObject <UIDynamicItem> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end ! ! @implementation ! DPDynamicObject - (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } ! - (CGPoint)center { return CGPointMake(50.0, 50.0); } ! - (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } ! - (CGAffineTransform)transform { return CGAffineTransformIdentity; } ! - (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } ! @end
  • 240. Example 1: conform to UIDynamicItem @interface DPDynamicObject : NSObject <UIDynamicItem> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end ! ! @implementation ! DPDynamicObject - (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } ! - (CGPoint)center { return CGPointMake(50.0, 50.0); } ! - (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } ! - (CGAffineTransform)transform { return CGAffineTransformIdentity; } ! - (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } ! @end
  • 241. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 242. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 243. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 244. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 245. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 246. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 247. Example 1: conform to UIDynamicItem @interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end ! @implementation DPDynamicItemProtocolViewController ... ! - (void)viewDidLoad { [super viewDidLoad]; ! ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.dynamicObject = [[DPDynamicObject alloc] init]; UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
  • 248. Example 1: conform to UIDynamicItem
  • 249. Example 1: conform to UIDynamicItem 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 ! 18:58:05.598 18:58:05.609 18:58:05.611 18:58:05.626 18:58:05.629 18:58:05.642 18:58:05.645 18:58:05.659 18:58:05.661 18:58:05.675 18:58:05.677 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Animator is running Center = {50, 50.04797} Transform = [1, 0, -0, 1, Center = {50, 50.447464} Transform = [1, 0, -0, 1, Center = {50, 51.054173} Transform = [1, 0, -0, 1, Center = {50, 51.915657} Transform = [1, 0, -0, 1, Center = {50, 53.031506} Transform = [1, 0, -0, 1, 18:58:08.742 18:58:08.744 18:58:08.759 18:58:08.761 18:58:08.775 18:58:08.777 18:58:08.792 18:58:08.794 18:58:08.809 18:58:08.810 18:58:08.812 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Animator is stopped 0, 0] 0, 0] 0, 0] 0, 0] 0, 0] ... ! 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 0, 0] 0, 0] 0, 0] 0, 0] 0, 0]
  • 250. Example 1: conform to UIDynamicItem 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 ! 18:58:05.598 18:58:05.609 18:58:05.611 18:58:05.626 18:58:05.629 18:58:05.642 18:58:05.645 18:58:05.659 18:58:05.661 18:58:05.675 18:58:05.677 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Animator is running Center = {50, 50.04797} Transform = [1, 0, -0, 1, Center = {50, 50.447464} Transform = [1, 0, -0, 1, Center = {50, 51.054173} Transform = [1, 0, -0, 1, Center = {50, 51.915657} Transform = [1, 0, -0, 1, Center = {50, 53.031506} Transform = [1, 0, -0, 1, 18:58:08.742 18:58:08.744 18:58:08.759 18:58:08.761 18:58:08.775 18:58:08.777 18:58:08.792 18:58:08.794 18:58:08.809 18:58:08.810 18:58:08.812 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Animator is stopped 0, 0] 0, 0] 0, 0] 0, 0] 0, 0] ... ! 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 0, 0] 0, 0] 0, 0] 0, 0] 0, 0]
  • 251. UIDynamicItem Use Case • Can use a single dynamic item to animate different views
  • 252. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else
  • 253. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else • To “animate” something that isn’t a view or a collection view use a UIDynamicItem
  • 254. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else • To “animate” something that isn’t a view or a collection view use a UIDynamicItem
  • 255. Example 2: remap center property
  • 256. Example 2: remap center property @protocol ResizableDynamicItem <UIDynamicItem> ! ! @interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> ! - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; ! @end ! ! @protocol ResizableDynamicItem <UIDynamicItem> ! @property (nonatomic, readwrite) CGRect bounds; ! @end
  • 257. Example 2: remap center property @protocol ResizableDynamicItem <UIDynamicItem> ! ! @interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> ! - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; ! @end ! ! @protocol ResizableDynamicItem <UIDynamicItem> ! @property (nonatomic, readwrite) CGRect bounds; ! @end
  • 258. Example 2: remap center property @protocol ResizableDynamicItem <UIDynamicItem> ! ! @interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> ! - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; ! @end ! ! @protocol ResizableDynamicItem <UIDynamicItem> ! @property (nonatomic, readwrite) CGRect bounds; ! @end
  • 259. Example 2: remap center property #import "APLPositionToBoundsMapping.h" ! @interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end ! @implementation ! APLPositionToBoundsMapping - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } ! - (CGRect)bounds { return self.target.bounds; } // Pass through ! - (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } ! - (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } ! - (CGAffineTransform)transform { return self.target.transform; // Pass through } ! - (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
  • 260. Example 2: remap center property #import "APLPositionToBoundsMapping.h" ! @interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end ! @implementation ! APLPositionToBoundsMapping - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } ! - (CGRect)bounds { return self.target.bounds; } // Pass through ! - (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } ! - (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } ! - (CGAffineTransform)transform { return self.target.transform; // Pass through } ! - (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
  • 261. Example 2: remap center property #import "APLPositionToBoundsMapping.h" ! @interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end ! @implementation ! APLPositionToBoundsMapping - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } ! - (CGRect)bounds { return self.target.bounds; } // Pass through ! - (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } ! - (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } ! - (CGAffineTransform)transform { return self.target.transform; // Pass through } ! - (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
  • 262. Example 2: remap center property #import "APLPositionToBoundsMapping.h" ! @interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end ! @implementation ! APLPositionToBoundsMapping - (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } ! - (CGRect)bounds { return self.target.bounds; } // Pass through ! - (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } ! - (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } ! - (CGAffineTransform)transform { return self.target.transform; // Pass through } ! - (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
  • 263. Example 2: remap center property @import UIKit; ! ! @interface APLCustomDynamicItemViewController : UIViewController @end ! ! @interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end ! ! @implementation APLCustomDynamicItemViewController ! - (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } ! // ... continue ! @end
  • 264. Example 2: remap center property @import UIKit; ! ! @interface APLCustomDynamicItemViewController : UIViewController @end ! ! @interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end ! ! @implementation APLCustomDynamicItemViewController ! - (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } ! // ... continue ! @end
  • 265. Example 2: remap center property ! @implementation APLCustomDynamicItemViewController ! ... ! - (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! ! APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; [animator addBehavior:pushBehavior]; self.animator = animator; } @end
  • 266. Example 2: remap center property ! @implementation APLCustomDynamicItemViewController ! ... ! - (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! ! APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; [animator addBehavior:pushBehavior]; self.animator = animator; } @end