SlideShare a Scribd company logo
1 of 384
Download to read offline
UIKit Dynamics
Let the physics flow

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
Chi siamo
programmatori e imprenditori, ma soprattutto appassionati
Cosa
creare una community di sviluppatori iOS e OS X
Perché
sentivamo l’esigenza di condividere e confrontarci
Dove
nel mondo virtuale, ma soprattutto nel mondo reale
Come
attraverso incontri periodici, eventi formativi e conferenze
Associazione
dal Settembre siamo ufficialmente un’associazione culturale
Associazione
dal Settembre siamo ufficialmente un’associazione culturale

Marco
Paolo

Matteo

Renzo
Francesco

Massimo

Stefano
Giuseppe
Statuto
Statuto
 L’associazione senza fini di lucro #pragma mark ha lo
scopo di svolgere attività di “community of practice, ovvero
di condivisione delle conoscenze ed esperienze tra persone
la cui professionalità ruota intorno le tecnologie
informatiche e iOS in particolare, fornendo un nuovo
modello per connetterle nello spirito dell’apprendimento,
della conoscenza condivisa e della collaborazione sia come
individui sia come gruppi”
152 partecipanti
16 speaker
15 sponsor
8 organizzatori
16 sessioni tecniche
10 ore di conferenza
2 track tematiche
20 gadget, licenze e coupon
Comunità
Ottobre 2013
la comunità è cresciuta molto, oggi siamo in 150
Partecipanti
più di 300 persone hanno seguito i nostri eventi
Social
205 iscritti al gruppo su facebook e 122 follower su twitter
Eventi
svolti 9 eventi
Dove
Brescia, Bergamo,Verona,Venezia, Milano 

e presto a Treviso e Roma
follow us @pragmamarkorg
join to fb.com/groups/pragmamark/
subscribe on pragmamark.org
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
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
• Initialised with items to animate
Behaviors Common characteristics
• Initialised with items to animate
• Items can be added to behavior at any times
Behaviors Common characteristics
• Initialised 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
• Initialised 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
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior
@interface DPCollisionsViewController : 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];

}
...
@end

[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:gravityBehavior];
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
• 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
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
• 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
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

~ =m~
F
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
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;

• 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
• 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
• 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
• 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: 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
• 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
Long Story Short
• Identify the type of dynamic items you want to animate
Long Story Short
• Identify the type of dynamic items you want to animate
• Define container or reference view
Long Story Short
• Identify the type of dynamic items you want to animate
• Define container or reference view
• Create the behaviours
Long Story Short
• Identify the type of dynamic items you want to animate
• Define container or reference view
• Create the behaviours
• Add items to behaviours
Long Story Short
• Identify the type of dynamic items you want to animate
• Define container or reference view
• Create the behaviours
• Add items to behaviours
• Configure, add or remove behaviors to an animator
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
• 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 isnt’a 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 isnt’a 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
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics
Hackatron - UIKit Dynamics

More Related Content

Similar to Hackatron - UIKit Dynamics

Thoughts on Component Resuse
Thoughts on Component ResuseThoughts on Component Resuse
Thoughts on Component ResuseJustin Edelson
 
Delegateless Coordinator
Delegateless CoordinatorDelegateless Coordinator
Delegateless CoordinatorTales Andrade
 
Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Tales Andrade
 
#pragma conf 2013 - UIKit dynamics
#pragma conf 2013  - UIKit dynamics#pragma conf 2013  - UIKit dynamics
#pragma conf 2013 - UIKit dynamicsRenzo G. Pretto
 
Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Melania Andrisan (Danciu)
 
JavaScript for ASP.NET programmers (webcast) upload
JavaScript for ASP.NET programmers (webcast) uploadJavaScript for ASP.NET programmers (webcast) upload
JavaScript for ASP.NET programmers (webcast) uploadRuss Fustino
 
NinjaScript and Mizugumo 2011-02-05
NinjaScript and Mizugumo 2011-02-05NinjaScript and Mizugumo 2011-02-05
NinjaScript and Mizugumo 2011-02-05lrdesign
 
Medium TechTalk — iOS
Medium TechTalk — iOSMedium TechTalk — iOS
Medium TechTalk — iOSjimmyatmedium
 
Building maintainable app #droidconzg
Building maintainable app #droidconzgBuilding maintainable app #droidconzg
Building maintainable app #droidconzgKristijan Jurković
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your appsJuan C Catalan
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIVisual Engineering
 
How We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFHow We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFSeanGraham5
 
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015Innomatic Platform
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Elyse Kolker Gordon
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom componentsJeremy Grancher
 
End-user Development of Mashups: Models, Composition Paradigms and Tools
End-user Development of Mashups: Models, Composition Paradigms and ToolsEnd-user Development of Mashups: Models, Composition Paradigms and Tools
End-user Development of Mashups: Models, Composition Paradigms and ToolsMatteo Picozzi
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React NativeEric Deng
 
Microservices Chaos Testing at Jet
Microservices Chaos Testing at JetMicroservices Chaos Testing at Jet
Microservices Chaos Testing at JetC4Media
 

Similar to Hackatron - UIKit Dynamics (20)

Viper on Android
Viper on AndroidViper on Android
Viper on Android
 
Thoughts on Component Resuse
Thoughts on Component ResuseThoughts on Component Resuse
Thoughts on Component Resuse
 
Delegateless Coordinator
Delegateless CoordinatorDelegateless Coordinator
Delegateless Coordinator
 
Delegateless Coordinators - take 2
Delegateless Coordinators - take 2Delegateless Coordinators - take 2
Delegateless Coordinators - take 2
 
#pragma conf 2013 - UIKit dynamics
#pragma conf 2013  - UIKit dynamics#pragma conf 2013  - UIKit dynamics
#pragma conf 2013 - UIKit dynamics
 
Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017
 
JavaScript for ASP.NET programmers (webcast) upload
JavaScript for ASP.NET programmers (webcast) uploadJavaScript for ASP.NET programmers (webcast) upload
JavaScript for ASP.NET programmers (webcast) upload
 
NinjaScript and Mizugumo 2011-02-05
NinjaScript and Mizugumo 2011-02-05NinjaScript and Mizugumo 2011-02-05
NinjaScript and Mizugumo 2011-02-05
 
Medium TechTalk — iOS
Medium TechTalk — iOSMedium TechTalk — iOS
Medium TechTalk — iOS
 
Building maintainable app
Building maintainable appBuilding maintainable app
Building maintainable app
 
Building maintainable app #droidconzg
Building maintainable app #droidconzgBuilding maintainable app #droidconzg
Building maintainable app #droidconzg
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your apps
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
 
How We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFHow We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADF
 
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom components
 
End-user Development of Mashups: Models, Composition Paradigms and Tools
End-user Development of Mashups: Models, Composition Paradigms and ToolsEnd-user Development of Mashups: Models, Composition Paradigms and Tools
End-user Development of Mashups: Models, Composition Paradigms and Tools
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native
 
Microservices Chaos Testing at Jet
Microservices Chaos Testing at JetMicroservices Chaos Testing at Jet
Microservices Chaos Testing at Jet
 

Recently uploaded

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

Hackatron - UIKit Dynamics

  • 1. UIKit Dynamics Let the physics flow Renzo G. Pretto iOS Developer
  • 4. About me Renzo iOS Developer H-art ! #pragma mark founder renzo.pretto@pragmamark.org ! @rgpretto
  • 5.
  • 6. Chi siamo programmatori e imprenditori, ma soprattutto appassionati
  • 7. Cosa creare una community di sviluppatori iOS e OS X
  • 8. Perché sentivamo l’esigenza di condividere e confrontarci
  • 9. Dove nel mondo virtuale, ma soprattutto nel mondo reale
  • 10. Come attraverso incontri periodici, eventi formativi e conferenze
  • 11. Associazione dal Settembre siamo ufficialmente un’associazione culturale
  • 12. Associazione dal Settembre siamo ufficialmente un’associazione culturale Marco Paolo Matteo Renzo Francesco Massimo Stefano Giuseppe
  • 14. Statuto  L’associazione senza fini di lucro #pragma mark ha lo scopo di svolgere attività di “community of practice, ovvero di condivisione delle conoscenze ed esperienze tra persone la cui professionalità ruota intorno le tecnologie informatiche e iOS in particolare, fornendo un nuovo modello per connetterle nello spirito dell’apprendimento, della conoscenza condivisa e della collaborazione sia come individui sia come gruppi”
  • 15.
  • 16. 152 partecipanti 16 speaker 15 sponsor 8 organizzatori
  • 17. 16 sessioni tecniche 10 ore di conferenza 2 track tematiche 20 gadget, licenze e coupon
  • 19. Ottobre 2013 la comunità è cresciuta molto, oggi siamo in 150
  • 20. Partecipanti più di 300 persone hanno seguito i nostri eventi
  • 21. Social 205 iscritti al gruppo su facebook e 122 follower su twitter
  • 23. Dove Brescia, Bergamo,Verona,Venezia, Milano 
 e presto a Treviso e Roma
  • 24. follow us @pragmamarkorg join to fb.com/groups/pragmamark/ subscribe on pragmamark.org
  • 25.
  • 26. Today Agenda • Introduction and core concepts
  • 27. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors
  • 28. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors
  • 29. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts
  • 30. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem
  • 31. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View
  • 32. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View • Conclusion
  • 45. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator Reference view
  • 46. UIDynamicAnimator • Define the coordinate system • Wraps underline engine UIDynamicAnimator Reference view
  • 47. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors UIDynamicAnimator Reference view
  • 48. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors • Run and optimize the animation UIDynamicAnimator Reference view
  • 49. 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
  • 50. 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]; ...
  • 51. 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]; ...
  • 52. 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]; ...
  • 53. 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]; ...
  • 54. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end
  • 55. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end • Notify pausing and resuming of UIKit Dynamic animator
  • 58. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times
  • 59. 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
  • 60. 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
  • 61. 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
  • 62. Behaviors Common characteristics • Initialised with items to animate
  • 63. Behaviors Common characteristics • Initialised with items to animate • Items can be added to behavior at any times
  • 64. Behaviors Common characteristics • Initialised with items to animate • Items can be added to behavior at any times • Behaviour can be configured before or after add to an animator
  • 65. Behaviors Common characteristics • Initialised 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
  • 69. Default Behaviors UIDynamicBehavior • Gravity • Collisions UIGravityBehavior UICollisionBehavior
  • 70. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior
  • 71. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments • Snap UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior
  • 72. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior
  • 73. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior • Item properties UIDynamicItemBehavior
  • 77. 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
  • 78. 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
  • 79. 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
  • 80. 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
  • 81. 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
  • 82. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection;
  • 83. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
  • 84. 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)
  • 85. 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)
  • 86. 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)
  • 89. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 90. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 91. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 92. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 93. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 94. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 95. UICollisionBehavior @interface DPCollisionsViewController : 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]; } ... @end [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior];
  • 96. Collision Boundaries • Can specify different boundaries
  • 97. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
  • 98. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
  • 99. 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;
  • 100. 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;
  • 101. 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;
  • 102. 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
  • 103. Collision Mode • Property collisionmode
  • 104. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
  • 105. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries
  • 106. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems
  • 107. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems • UICollisionBehaviorModeEverything (default)
  • 108. Tips • Can use multiple collision behaviors
  • 109. Tips • Can use multiple collision behaviors • Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
  • 110. 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
  • 111. UICollisionBehaviorDelegate • Methods that inform collision start / end between view
  • 112. 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;
  • 113. 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
  • 114. 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;
  • 115. 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;
  • 116. 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
  • 119. 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
  • 120. 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
  • 121. 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
  • 122. 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
  • 123. 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
  • 124. 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
  • 125. UIAttachmentBehavior • View connected to an attachment point
  • 126. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
  • 127. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together
  • 128. 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;
  • 129. 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
  • 130. 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;
  • 131. 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;
  • 133. Springs • Springs @property (readwrite, nonatomic) CGFloat damping;
  • 134. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 135. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 138. 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
  • 139. 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
  • 140. 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
  • 141. 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
  • 142. 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
  • 143. 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
  • 144. UISnapBehavior • Snap view in place in non rotated state
  • 145. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
  • 146. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; • Customize the dumping effects
  • 147. 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;
  • 150. UIPushBehavior ~ F = m ~ , apply force to views: a •
  • 151. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 152. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way:
  • 153. 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;
  • 154. 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;
  • 156. UIPushBehavior • Customize where apply this force in the view
  • 157. UIPushBehavior • Customize where apply this force in the view
  • 158. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 159. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 160. 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
  • 161. 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;
  • 162. 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;
  • 163. 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;
  • 164. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 165. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous
  • 166. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active
  • 167. 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
  • 168. 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
  • 169. 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
  • 170. 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)
  • 171. 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
  • 172. 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;
  • 173. Example: force comparison ~ F =m~ a ~ F ~= a m
  • 174. Example: force comparison ~ F =m~ a ~ F ~= a m
  • 178. Feel The Force! • Gravity • views accelerate with the same rate
  • 179. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode
  • 180. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more
  • 181. 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
  • 182. 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
  • 183. 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
  • 184. Unit of Measure • Real world: Newton
  • 185. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 •
  • 186. 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
  • 187. 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”
  • 190. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;
  • 191. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;
  • 192. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;
  • 193. 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;
  • 194. 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;
  • 195. 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;
  • 196. 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;
  • 197. 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;
  • 198. 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
  • 199. 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
  • 200. 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
  • 201. Long Story Short • Identify the type of dynamic items you want to animate
  • 202. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view
  • 203. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view • Create the behaviours
  • 204. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view • Create the behaviours • Add items to behaviours
  • 205. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view • Create the behaviours • Add items to behaviours • Configure, add or remove behaviors to an animator
  • 207. Custom Behavior • Can subclass UIDynamicBehavior
  • 208. Custom Behavior • Can subclass UIDynamicBehavior • add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior; @property (nonatomic, readonly, copy) NSArray* childBehaviors;
  • 209. 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
  • 210. Example: gravity & collision
  • 211. 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
  • 212. 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
  • 213. 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
  • 214. 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
  • 215. 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
  • 216. 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
  • 217. 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
  • 218. 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
  • 219. 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
  • 220. 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
  • 221. 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
  • 222. 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
  • 223. 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
  • 224. 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
  • 225. 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
  • 226. 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
  • 227. Action Block • Can define per-step actions
  • 228. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void);
  • 229. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void); • UIDynamicAnimator invoke this block in each simulation step
  • 230. 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
  • 232. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end
  • 233. 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
  • 234. 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
  • 235. 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
  • 236. 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
  • 237. 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)
  • 238. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit
  • 239. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
  • 240. 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
  • 241. 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
  • 242. 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
  • 243. 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
  • 244. 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
  • 245. 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
  • 246. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol
  • 247. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol @interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
  • 248. 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 > { ... }
  • 249. 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 > { ... }
  • 252. 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
  • 253. 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
  • 254. 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
  • 255. 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
  • 256. 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
  • 257. 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
  • 258. 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
  • 259. 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
  • 260. 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
  • 261. 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
  • 262. 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
  • 263. 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
  • 264. Example 1: conform to UIDynamicItem
  • 265. 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]
  • 266. 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]
  • 267. UIDynamicItem Use Case • Can use a single dynamic item to animate different views
  • 268. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else
  • 269. 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 isnt’a a view or a collection view use a UIDynamicItem
  • 270. 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 isnt’a a view or a collection view use a UIDynamicItem
  • 271. Example 2: remap center property
  • 272. 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
  • 273. 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
  • 274. 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
  • 275. 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
  • 276. 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
  • 277. 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
  • 278. 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
  • 279. 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
  • 280. 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