SlideShare a Scribd company logo
3D Touch
Karol Kozub
2016-02-22
The device senses how much pressure you apply to the display
“An entirely new way to interact with your phone”
UITouch.force
public class UITouch : NSObject {
// …
// Force of the touch, where 1.0 represents the force of an average touch
public var force: CGFloat { get }
// Maximum possible force with this input mechanism
public var maximumPossibleForce: CGFloat { get }
// …
}
UITouch.force
public class UITouch : NSObject {
// …
// Force of the touch, where 1.0 represents the force of an average touch
public var force: CGFloat { get }
// Maximum possible force with this input mechanism
public var maximumPossibleForce: CGFloat { get }
// …
}
For some reason equal to 6.66…
on the iPhone 6s
UITouch.force
public class UITouch : NSObject {
// …
// Force of the touch, where 1.0 represents the force of an average touch
public var force: CGFloat { get }
// Maximum possible force with this input mechanism
public var maximumPossibleForce: CGFloat { get }
// …
}
Quick Actions
• Apps can have up to 4
• Added either through Info.plist
• Or dynamically in code
Quick Actions
Static Quick Actions
Static Quick Actions
Required
Static Quick Actions
Optional
Static Quick Actions
Type
Static Quick Actions
Title
Static Quick Actions
Subtitle
Static Quick Actions
Icon
Static Quick Actions
Icon
Static Quick Actions
User Info
System Icon Types
iOS 9.0
iOS 9.1
Dynamic Quick Actions
extension UIApplication {
// Register shortcuts to display on the home screen, or retrieve currently registered shortcuts.
@available(iOS 9.0, *)
public var shortcutItems: [UIApplicationShortcutItem]?
}
Dynamic Quick Actions
@available(iOS 9.0, *)
public class UIApplicationShortcutItem : NSObject, NSCopying, NSMutableCopying {
public init(type: String,
localizedTitle: String,
localizedSubtitle: String?,
icon: UIApplicationShortcutIcon?,
userInfo: [NSObject : AnyObject]?)
public convenience init(type: String,
localizedTitle: String)
// An application-specific string that identifies the type of action to perform.
public var type: String { get }
// Properties controlling how the item should be displayed on the home screen.
public var localizedTitle: String { get }
public var localizedSubtitle: String? { get }
@NSCopying public var icon: UIApplicationShortcutIcon? { get }
// Application-specific information needed to perform the action.
// Will throw an exception if the NSDictionary is not plist-encodable.
public var userInfo: [String : NSSecureCoding]? { get }
}
extension UIApplication {
// Register shortcuts to display on the home screen, or retrieve currently registered shortcuts.
@available(iOS 9.0, *)
public var shortcutItems: [UIApplicationShortcutItem]?
}
Dynamic Quick Actions
@available(iOS 9.0, *)
public class UIApplicationShortcutItem : NSObject, NSCopying, NSMutableCopying {
public init(type: String,
localizedTitle: String,
localizedSubtitle: String?,
icon: UIApplicationShortcutIcon?,
userInfo: [NSObject : AnyObject]?)
public convenience init(type: String,
localizedTitle: String)
// An application-specific string that identifies the type of action to perform.
public var type: String { get }
// Properties controlling how the item should be displayed on the home screen.
public var localizedTitle: String { get }
public var localizedSubtitle: String? { get }
@NSCopying public var icon: UIApplicationShortcutIcon? { get }
// Application-specific information needed to perform the action.
// Will throw an exception if the NSDictionary is not plist-encodable.
public var userInfo: [String : NSSecureCoding]? { get }
}
extension UIApplication {
// Register shortcuts to display on the home screen, or retrieve currently registered shortcuts.
@available(iOS 9.0, *)
public var shortcutItems: [UIApplicationShortcutItem]?
}
Required
Optional
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Dynamic Quick Actions
let iconTypeIcon = UIApplicationShortcutIcon(type: .Search)
let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item",
localizedTitle: "Search",
localizedSubtitle: "icon from an icon type",
icon: iconTypeIcon,
userInfo: nil)
let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle")
let templateItem = UIApplicationShortcutItem(type: "template-item",
localizedTitle: "Triangle",
localizedSubtitle: "icon from template image",
icon: templateIcon,
userInfo: nil)
let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore)
let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item",
localizedTitle: "Karol",
localizedSubtitle: "icon from real contact",
icon: contactStoreContactIcon,
userInfo: nil)
let temporaryContact = CNMutableContact()
temporaryContact.givenName = "Hiro";
temporaryContact.familyName = "Protagonist";
// this will be ignored
temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!)
let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact)
let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item",
localizedTitle: "Hiro",
localizedSubtitle: "icon from tmp contact",
icon: temporaryContactIcon,
userInfo: nil)
UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem,
contactStoreContactItem, temporaryContactItem]
Handling Quick Actions
public protocol UIApplicationDelegate : NSObjectProtocol {
// …
// Called when the user activates your application by
// selecting a shortcut on the home screen,
// except when -application:willFinishLaunchingWithOptions: or
// -application:didFinishLaunchingWithOptions returns NO.
@available(iOS 9.0, *)
optional public func application(application: UIApplication,
performActionForShortcutItem shortcutItem: UIApplicationShortcutItem,
completionHandler: (Bool) -> Void)
// …
}
Handling Quick Actions
public protocol UIApplicationDelegate : NSObjectProtocol {
// …
// Called when the user activates your application by
// selecting a shortcut on the home screen,
// except when -application:willFinishLaunchingWithOptions: or
// -application:didFinishLaunchingWithOptions returns NO.
@available(iOS 9.0, *)
optional public func application(application: UIApplication,
performActionForShortcutItem shortcutItem: UIApplicationShortcutItem,
completionHandler: (Bool) -> Void)
// …
}
Full-blown shortcut item
Handling Quick Actions
public protocol UIApplicationDelegate : NSObjectProtocol {
// …
// Called when the user activates your application by
// selecting a shortcut on the home screen,
// except when -application:willFinishLaunchingWithOptions: or
// -application:didFinishLaunchingWithOptions returns NO.
@available(iOS 9.0, *)
optional public func application(application: UIApplication,
performActionForShortcutItem shortcutItem: UIApplicationShortcutItem,
completionHandler: (Bool) -> Void)
// …
}
Call when finished
Peek and Pop
• Press to Peek at what’s inside
• Stop pressing to hide the preview
• Press harder to Pop into the view
Peek and Pop
Peek and Pop
extension UIViewController {
// Registers a view controller to participate with 3D Touch preview (peek) and commit (pop).
@available(iOS 9.0, *)
public func registerForPreviewingWithDelegate(delegate: UIViewControllerPreviewingDelegate,
sourceView: UIView) -> UIViewControllerPreviewing
@available(iOS 9.0, *)
public func unregisterForPreviewingWithContext(previewing: UIViewControllerPreviewing)
}
@available(iOS 9.0, *)
public protocol UIViewControllerPreviewingDelegate : NSObjectProtocol {
// If you return nil, a preview presentation will not be performed
@available(iOS 9.0, *)
public func previewingContext(previewingContext: UIViewControllerPreviewing,
viewControllerForLocation location: CGPoint) -> UIViewController?
@available(iOS 9.0, *)
public func previewingContext(previewingContext: UIViewControllerPreviewing,
commitViewController viewControllerToCommit: UIViewController)
}
Peek and Pop
class ViewController: UIViewController, UIViewControllerPreviewingDelegate {
@IBOutlet weak var sourceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
registerForPreviewingWithDelegate(self, sourceView: sourceView)
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
viewControllerForLocation location: CGPoint) -> UIViewController? {
return PreviewedViewController()
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
commitViewController viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit,
animated: false)
}
}
Peek and Pop
class ViewController: UIViewController, UIViewControllerPreviewingDelegate {
@IBOutlet weak var sourceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
registerForPreviewingWithDelegate(self, sourceView: sourceView)
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
viewControllerForLocation location: CGPoint) -> UIViewController? {
return PreviewedViewController()
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
commitViewController viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit,
animated: false)
}
}
Peek and Pop
public protocol UIViewControllerPreviewing : NSObjectProtocol {
// This gesture can be used to cause the previewing presentation
// to wait until one of your gestures fails or to allow simultaneous
// recognition during the initial phase of the preview presentation.
@available(iOS 9.0, *)
public var previewingGestureRecognizerForFailureRelationship: UIGestureRecognizer { get }
@available(iOS 9.0, *)
public var delegate: UIViewControllerPreviewingDelegate { get }
@available(iOS 9.0, *)
public var sourceView: UIView { get }
// This rect will be set to the bounds of sourceView before each call to
// -previewingContext:viewControllerForLocation:
@available(iOS 9.0, *)
public var sourceRect: CGRect { get set }
}
Peek and Pop
class ViewController: UIViewController, UIViewControllerPreviewingDelegate {
@IBOutlet weak var sourceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
registerForPreviewingWithDelegate(self, sourceView: sourceView)
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
viewControllerForLocation location: CGPoint) -> UIViewController? {
let rect = CGRectInset(previewingContext.sourceView.bounds, 20, 20)
previewingContext.sourceRect = rect
return PreviewedViewController()
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
commitViewController viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit,
animated: false)
}
}
Peek and Pop
class ViewController: UIViewController, UIViewControllerPreviewingDelegate {
@IBOutlet weak var sourceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
registerForPreviewingWithDelegate(self, sourceView: sourceView)
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
viewControllerForLocation location: CGPoint) -> UIViewController? {
return nil
}
func previewingContext(previewingContext: UIViewControllerPreviewing,
commitViewController viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit,
animated: false)
}
}
Peek Quick Actions
extension UIViewController {
public func previewActionItems() -> [UIPreviewActionItem]
}
public protocol UIPreviewActionItem : NSObjectProtocol {
public var title: String { get }
}
public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem {
public var handler: (UIPreviewActionItem, UIViewController) -> Void { get }
public convenience init(title: String,
style: UIPreviewActionStyle,
handler: (UIPreviewAction, UIViewController) -> Void)
}
public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem {
public convenience init(title: String,
style: UIPreviewActionStyle,
actions: [UIPreviewAction])
}
Peek Quick Actions
extension UIViewController {
public func previewActionItems() -> [UIPreviewActionItem]
}
public protocol UIPreviewActionItem : NSObjectProtocol {
public var title: String { get }
}
public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem {
public var handler: (UIPreviewActionItem, UIViewController) -> Void { get }
public convenience init(title: String,
style: UIPreviewActionStyle,
handler: (UIPreviewAction, UIViewController) -> Void)
}
public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem {
public convenience init(title: String,
style: UIPreviewActionStyle,
actions: [UIPreviewAction])
}
Peek Quick Actions
extension UIViewController {
public func previewActionItems() -> [UIPreviewActionItem]
}
public protocol UIPreviewActionItem : NSObjectProtocol {
public var title: String { get }
}
public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem {
public var handler: (UIPreviewActionItem, UIViewController) -> Void { get }
public convenience init(title: String,
style: UIPreviewActionStyle,
handler: (UIPreviewAction, UIViewController) -> Void)
}
public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem {
public convenience init(title: String,
style: UIPreviewActionStyle,
actions: [UIPreviewAction])
}
Peek Quick Actions
class PreviewedViewController: UIViewController {
override func previewActionItems() -> [UIPreviewActionItem] {
let defaultStyleAction = UIPreviewAction(title: "Default Style",
style: .Default) {action, controller in
}
let destructiveStyleAction = UIPreviewAction(title: "Destructive Style",
style: .Destructive) {action, controller in
}
let selectedStyleAction = UIPreviewAction(title: "Selected Style",
style: .Selected) {action, controller in
}
let actionGroup = UIPreviewActionGroup(title: "Group",
style: .Default,
actions: [defaultStyleAction, defaultStyleAction, defaultStyleAction])
return [defaultStyleAction, destructiveStyleAction,
selectedStyleAction, actionGroup]
}
}
Peek Quick Actions
class PreviewedViewController: UIViewController {
override func previewActionItems() -> [UIPreviewActionItem] {
let defaultStyleAction = UIPreviewAction(title: "Default Style",
style: .Default) {action, controller in
}
let destructiveStyleAction = UIPreviewAction(title: "Destructive Style",
style: .Destructive) {action, controller in
}
let selectedStyleAction = UIPreviewAction(title: "Selected Style",
style: .Selected) {action, controller in
}
return [defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction,
defaultStyleAction, destructiveStyleAction, selectedStyleAction]
}
}
Detecting 3D Touch
public class UITraitCollection : NSObject, NSCopying, NSSecureCoding {
// …
public var forceTouchCapability: UIForceTouchCapability { get }
// …
}
public enum UIForceTouchCapability : Int {
case Unknown
case Unavailable
case Available
}
Detecting 3D Touch
public class UITraitCollection : NSObject, NSCopying, NSSecureCoding {
// …
public var forceTouchCapability: UIForceTouchCapability { get }
// …
}
public enum UIForceTouchCapability : Int {
case Unknown
case Unavailable
case Available
}
/*! Trait environments expose a trait collection that describes their environment. */
public protocol UITraitEnvironment : NSObjectProtocol {
public var traitCollection: UITraitCollection { get }
/*! To be overridden as needed to provide
custom behavior when the environment's traits change. */
public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?)
}
Detecting 3D Touch
public class UITraitCollection : NSObject, NSCopying, NSSecureCoding {
// …
public var forceTouchCapability: UIForceTouchCapability { get }
// …
}
public enum UIForceTouchCapability : Int {
case Unknown
case Unavailable
case Available
}
/*! Trait environments expose a trait collection that describes their environment. */
public protocol UITraitEnvironment : NSObjectProtocol {
public var traitCollection: UITraitCollection { get }
/*! To be overridden as needed to provide
custom behavior when the environment's traits change. */
public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?)
}
The following interface classes adopt this protocol:
UIScreen, UIWindow, UIViewController, UIPresentationController, and UIView.
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Summary
• UITouch.force
• Static Quick Actions
• Dynamic Quick Actions
• Peek and Pop
• Peek Quick Actions
• Detecting 3D Touch
Thank you for listening

More Related Content

Viewers also liked (6)

3D Touch Implementation for Shortcuts and Peek/Pop Functionality
3D Touch Implementation for Shortcuts and Peek/Pop Functionality3D Touch Implementation for Shortcuts and Peek/Pop Functionality
3D Touch Implementation for Shortcuts and Peek/Pop Functionality
 
Android N's 3D Touch
Android N's 3D Touch Android N's 3D Touch
Android N's 3D Touch
 
3D Touch
3D Touch3D Touch
3D Touch
 
AUGMENTED REALITY Documentation
AUGMENTED REALITY DocumentationAUGMENTED REALITY Documentation
AUGMENTED REALITY Documentation
 
Seminar report on paper battery
Seminar report on paper batterySeminar report on paper battery
Seminar report on paper battery
 
Paper battery
Paper batteryPaper battery
Paper battery
 

Similar to 3D Touch by Karol Kozub, Macoscope

Flash Lite & Touch: build an iPhone-like dynamic list
Flash Lite & Touch: build an iPhone-like dynamic listFlash Lite & Touch: build an iPhone-like dynamic list
Flash Lite & Touch: build an iPhone-like dynamic list
Small Screen Design
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through Activities
Ahsanul Karim
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through Activities
Ahsanul Karim
 

Similar to 3D Touch by Karol Kozub, Macoscope (20)

Cocoaheads Montpellier Meetup : 3D Touch for iOS
Cocoaheads Montpellier Meetup : 3D Touch for iOSCocoaheads Montpellier Meetup : 3D Touch for iOS
Cocoaheads Montpellier Meetup : 3D Touch for iOS
 
Build 2017 - B8108 - App engagement in Windows Timeline and Cortana with User...
Build 2017 - B8108 - App engagement in Windows Timeline and Cortana with User...Build 2017 - B8108 - App engagement in Windows Timeline and Cortana with User...
Build 2017 - B8108 - App engagement in Windows Timeline and Cortana with User...
 
iOS Automation Primitives
iOS Automation PrimitivesiOS Automation Primitives
iOS Automation Primitives
 
Owasp orlando, april 13, 2016
Owasp orlando, april 13, 2016Owasp orlando, april 13, 2016
Owasp orlando, april 13, 2016
 
303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code
 
Flash Lite & Touch: build an iPhone-like dynamic list
Flash Lite & Touch: build an iPhone-like dynamic listFlash Lite & Touch: build an iPhone-like dynamic list
Flash Lite & Touch: build an iPhone-like dynamic list
 
What's new in iOS9
What's new in iOS9What's new in iOS9
What's new in iOS9
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through Activities
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through Activities
 
UIAutomation + Mechanic.js
UIAutomation + Mechanic.jsUIAutomation + Mechanic.js
UIAutomation + Mechanic.js
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
 
Advance UIAutomator : Documentaion
Advance UIAutomator : DocumentaionAdvance UIAutomator : Documentaion
Advance UIAutomator : Documentaion
 
KKBOX WWDC17 Notification and Autolayout - Jefferey
KKBOX WWDC17 Notification and Autolayout - JeffereyKKBOX WWDC17 Notification and Autolayout - Jefferey
KKBOX WWDC17 Notification and Autolayout - Jefferey
 
Lightning Talk - Xamarin
Lightning Talk - Xamarin Lightning Talk - Xamarin
Lightning Talk - Xamarin
 
[Droidcon NL 2013] Developing Cross-Platform Apps
[Droidcon NL 2013] Developing Cross-Platform Apps[Droidcon NL 2013] Developing Cross-Platform Apps
[Droidcon NL 2013] Developing Cross-Platform Apps
 
Hieu Xamarin iOS9, Android M 3-11-2015
Hieu Xamarin iOS9, Android M  3-11-2015Hieu Xamarin iOS9, Android M  3-11-2015
Hieu Xamarin iOS9, Android M 3-11-2015
 
Droidcon: Sean Owen: Driving Downloads via Intents- 29/10/2010
Droidcon: Sean Owen: Driving Downloads via Intents- 29/10/2010Droidcon: Sean Owen: Driving Downloads via Intents- 29/10/2010
Droidcon: Sean Owen: Driving Downloads via Intents- 29/10/2010
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragment
 
Migrating Objective-C to Swift
Migrating Objective-C to SwiftMigrating Objective-C to Swift
Migrating Objective-C to Swift
 
Custom view
Custom viewCustom view
Custom view
 

Recently uploaded

Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Peter Udo Diehl
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 

Recently uploaded (20)

Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 

3D Touch by Karol Kozub, Macoscope

  • 2. The device senses how much pressure you apply to the display
  • 3. “An entirely new way to interact with your phone”
  • 4. UITouch.force public class UITouch : NSObject { // … // Force of the touch, where 1.0 represents the force of an average touch public var force: CGFloat { get } // Maximum possible force with this input mechanism public var maximumPossibleForce: CGFloat { get } // … }
  • 5. UITouch.force public class UITouch : NSObject { // … // Force of the touch, where 1.0 represents the force of an average touch public var force: CGFloat { get } // Maximum possible force with this input mechanism public var maximumPossibleForce: CGFloat { get } // … } For some reason equal to 6.66… on the iPhone 6s
  • 6. UITouch.force public class UITouch : NSObject { // … // Force of the touch, where 1.0 represents the force of an average touch public var force: CGFloat { get } // Maximum possible force with this input mechanism public var maximumPossibleForce: CGFloat { get } // … }
  • 8. • Apps can have up to 4 • Added either through Info.plist • Or dynamically in code Quick Actions
  • 18. System Icon Types iOS 9.0 iOS 9.1
  • 19. Dynamic Quick Actions extension UIApplication { // Register shortcuts to display on the home screen, or retrieve currently registered shortcuts. @available(iOS 9.0, *) public var shortcutItems: [UIApplicationShortcutItem]? }
  • 20. Dynamic Quick Actions @available(iOS 9.0, *) public class UIApplicationShortcutItem : NSObject, NSCopying, NSMutableCopying { public init(type: String, localizedTitle: String, localizedSubtitle: String?, icon: UIApplicationShortcutIcon?, userInfo: [NSObject : AnyObject]?) public convenience init(type: String, localizedTitle: String) // An application-specific string that identifies the type of action to perform. public var type: String { get } // Properties controlling how the item should be displayed on the home screen. public var localizedTitle: String { get } public var localizedSubtitle: String? { get } @NSCopying public var icon: UIApplicationShortcutIcon? { get } // Application-specific information needed to perform the action. // Will throw an exception if the NSDictionary is not plist-encodable. public var userInfo: [String : NSSecureCoding]? { get } } extension UIApplication { // Register shortcuts to display on the home screen, or retrieve currently registered shortcuts. @available(iOS 9.0, *) public var shortcutItems: [UIApplicationShortcutItem]? }
  • 21. Dynamic Quick Actions @available(iOS 9.0, *) public class UIApplicationShortcutItem : NSObject, NSCopying, NSMutableCopying { public init(type: String, localizedTitle: String, localizedSubtitle: String?, icon: UIApplicationShortcutIcon?, userInfo: [NSObject : AnyObject]?) public convenience init(type: String, localizedTitle: String) // An application-specific string that identifies the type of action to perform. public var type: String { get } // Properties controlling how the item should be displayed on the home screen. public var localizedTitle: String { get } public var localizedSubtitle: String? { get } @NSCopying public var icon: UIApplicationShortcutIcon? { get } // Application-specific information needed to perform the action. // Will throw an exception if the NSDictionary is not plist-encodable. public var userInfo: [String : NSSecureCoding]? { get } } extension UIApplication { // Register shortcuts to display on the home screen, or retrieve currently registered shortcuts. @available(iOS 9.0, *) public var shortcutItems: [UIApplicationShortcutItem]? } Required Optional
  • 22. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 23. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 24. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 25. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 26. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 27. Dynamic Quick Actions let iconTypeIcon = UIApplicationShortcutIcon(type: .Search) let iconTypeItem = UIApplicationShortcutItem(type: "icon-type-item", localizedTitle: "Search", localizedSubtitle: "icon from an icon type", icon: iconTypeIcon, userInfo: nil) let templateIcon = UIApplicationShortcutIcon(templateImageName: "triangle") let templateItem = UIApplicationShortcutItem(type: "template-item", localizedTitle: "Triangle", localizedSubtitle: "icon from template image", icon: templateIcon, userInfo: nil) let contactStoreContactIcon = UIApplicationShortcutIcon(contact: contactFromContactStore) let contactStoreContactItem = UIApplicationShortcutItem(type: "real-contact-item", localizedTitle: "Karol", localizedSubtitle: "icon from real contact", icon: contactStoreContactIcon, userInfo: nil) let temporaryContact = CNMutableContact() temporaryContact.givenName = "Hiro"; temporaryContact.familyName = "Protagonist"; // this will be ignored temporaryContact.imageData = UIImagePNGRepresentation(UIImage(named: "triangle")!) let temporaryContactIcon = UIApplicationShortcutIcon(contact: temporaryContact) let temporaryContactItem = UIApplicationShortcutItem(type: "temporary-contact-item", localizedTitle: "Hiro", localizedSubtitle: "icon from tmp contact", icon: temporaryContactIcon, userInfo: nil) UIApplication.sharedApplication().shortcutItems = [iconTypeItem, templateItem, contactStoreContactItem, temporaryContactItem]
  • 28. Handling Quick Actions public protocol UIApplicationDelegate : NSObjectProtocol { // … // Called when the user activates your application by // selecting a shortcut on the home screen, // except when -application:willFinishLaunchingWithOptions: or // -application:didFinishLaunchingWithOptions returns NO. @available(iOS 9.0, *) optional public func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) // … }
  • 29. Handling Quick Actions public protocol UIApplicationDelegate : NSObjectProtocol { // … // Called when the user activates your application by // selecting a shortcut on the home screen, // except when -application:willFinishLaunchingWithOptions: or // -application:didFinishLaunchingWithOptions returns NO. @available(iOS 9.0, *) optional public func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) // … } Full-blown shortcut item
  • 30. Handling Quick Actions public protocol UIApplicationDelegate : NSObjectProtocol { // … // Called when the user activates your application by // selecting a shortcut on the home screen, // except when -application:willFinishLaunchingWithOptions: or // -application:didFinishLaunchingWithOptions returns NO. @available(iOS 9.0, *) optional public func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) // … } Call when finished
  • 32. • Press to Peek at what’s inside • Stop pressing to hide the preview • Press harder to Pop into the view Peek and Pop
  • 33. Peek and Pop extension UIViewController { // Registers a view controller to participate with 3D Touch preview (peek) and commit (pop). @available(iOS 9.0, *) public func registerForPreviewingWithDelegate(delegate: UIViewControllerPreviewingDelegate, sourceView: UIView) -> UIViewControllerPreviewing @available(iOS 9.0, *) public func unregisterForPreviewingWithContext(previewing: UIViewControllerPreviewing) } @available(iOS 9.0, *) public protocol UIViewControllerPreviewingDelegate : NSObjectProtocol { // If you return nil, a preview presentation will not be performed @available(iOS 9.0, *) public func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? @available(iOS 9.0, *) public func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) }
  • 34. Peek and Pop class ViewController: UIViewController, UIViewControllerPreviewingDelegate { @IBOutlet weak var sourceView: UIView! override func viewDidLoad() { super.viewDidLoad() registerForPreviewingWithDelegate(self, sourceView: sourceView) } func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { return PreviewedViewController() } func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { navigationController?.pushViewController(viewControllerToCommit, animated: false) } }
  • 35. Peek and Pop class ViewController: UIViewController, UIViewControllerPreviewingDelegate { @IBOutlet weak var sourceView: UIView! override func viewDidLoad() { super.viewDidLoad() registerForPreviewingWithDelegate(self, sourceView: sourceView) } func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { return PreviewedViewController() } func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { navigationController?.pushViewController(viewControllerToCommit, animated: false) } }
  • 36. Peek and Pop public protocol UIViewControllerPreviewing : NSObjectProtocol { // This gesture can be used to cause the previewing presentation // to wait until one of your gestures fails or to allow simultaneous // recognition during the initial phase of the preview presentation. @available(iOS 9.0, *) public var previewingGestureRecognizerForFailureRelationship: UIGestureRecognizer { get } @available(iOS 9.0, *) public var delegate: UIViewControllerPreviewingDelegate { get } @available(iOS 9.0, *) public var sourceView: UIView { get } // This rect will be set to the bounds of sourceView before each call to // -previewingContext:viewControllerForLocation: @available(iOS 9.0, *) public var sourceRect: CGRect { get set } }
  • 37. Peek and Pop class ViewController: UIViewController, UIViewControllerPreviewingDelegate { @IBOutlet weak var sourceView: UIView! override func viewDidLoad() { super.viewDidLoad() registerForPreviewingWithDelegate(self, sourceView: sourceView) } func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { let rect = CGRectInset(previewingContext.sourceView.bounds, 20, 20) previewingContext.sourceRect = rect return PreviewedViewController() } func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { navigationController?.pushViewController(viewControllerToCommit, animated: false) } }
  • 38. Peek and Pop class ViewController: UIViewController, UIViewControllerPreviewingDelegate { @IBOutlet weak var sourceView: UIView! override func viewDidLoad() { super.viewDidLoad() registerForPreviewingWithDelegate(self, sourceView: sourceView) } func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { return nil } func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { navigationController?.pushViewController(viewControllerToCommit, animated: false) } }
  • 39. Peek Quick Actions extension UIViewController { public func previewActionItems() -> [UIPreviewActionItem] } public protocol UIPreviewActionItem : NSObjectProtocol { public var title: String { get } } public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem { public var handler: (UIPreviewActionItem, UIViewController) -> Void { get } public convenience init(title: String, style: UIPreviewActionStyle, handler: (UIPreviewAction, UIViewController) -> Void) } public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem { public convenience init(title: String, style: UIPreviewActionStyle, actions: [UIPreviewAction]) }
  • 40. Peek Quick Actions extension UIViewController { public func previewActionItems() -> [UIPreviewActionItem] } public protocol UIPreviewActionItem : NSObjectProtocol { public var title: String { get } } public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem { public var handler: (UIPreviewActionItem, UIViewController) -> Void { get } public convenience init(title: String, style: UIPreviewActionStyle, handler: (UIPreviewAction, UIViewController) -> Void) } public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem { public convenience init(title: String, style: UIPreviewActionStyle, actions: [UIPreviewAction]) }
  • 41. Peek Quick Actions extension UIViewController { public func previewActionItems() -> [UIPreviewActionItem] } public protocol UIPreviewActionItem : NSObjectProtocol { public var title: String { get } } public class UIPreviewAction : NSObject, NSCopying, UIPreviewActionItem { public var handler: (UIPreviewActionItem, UIViewController) -> Void { get } public convenience init(title: String, style: UIPreviewActionStyle, handler: (UIPreviewAction, UIViewController) -> Void) } public class UIPreviewActionGroup : NSObject, NSCopying, UIPreviewActionItem { public convenience init(title: String, style: UIPreviewActionStyle, actions: [UIPreviewAction]) }
  • 42. Peek Quick Actions class PreviewedViewController: UIViewController { override func previewActionItems() -> [UIPreviewActionItem] { let defaultStyleAction = UIPreviewAction(title: "Default Style", style: .Default) {action, controller in } let destructiveStyleAction = UIPreviewAction(title: "Destructive Style", style: .Destructive) {action, controller in } let selectedStyleAction = UIPreviewAction(title: "Selected Style", style: .Selected) {action, controller in } let actionGroup = UIPreviewActionGroup(title: "Group", style: .Default, actions: [defaultStyleAction, defaultStyleAction, defaultStyleAction]) return [defaultStyleAction, destructiveStyleAction, selectedStyleAction, actionGroup] } }
  • 43. Peek Quick Actions class PreviewedViewController: UIViewController { override func previewActionItems() -> [UIPreviewActionItem] { let defaultStyleAction = UIPreviewAction(title: "Default Style", style: .Default) {action, controller in } let destructiveStyleAction = UIPreviewAction(title: "Destructive Style", style: .Destructive) {action, controller in } let selectedStyleAction = UIPreviewAction(title: "Selected Style", style: .Selected) {action, controller in } return [defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction, defaultStyleAction, destructiveStyleAction, selectedStyleAction] } }
  • 44. Detecting 3D Touch public class UITraitCollection : NSObject, NSCopying, NSSecureCoding { // … public var forceTouchCapability: UIForceTouchCapability { get } // … } public enum UIForceTouchCapability : Int { case Unknown case Unavailable case Available }
  • 45. Detecting 3D Touch public class UITraitCollection : NSObject, NSCopying, NSSecureCoding { // … public var forceTouchCapability: UIForceTouchCapability { get } // … } public enum UIForceTouchCapability : Int { case Unknown case Unavailable case Available } /*! Trait environments expose a trait collection that describes their environment. */ public protocol UITraitEnvironment : NSObjectProtocol { public var traitCollection: UITraitCollection { get } /*! To be overridden as needed to provide custom behavior when the environment's traits change. */ public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) }
  • 46. Detecting 3D Touch public class UITraitCollection : NSObject, NSCopying, NSSecureCoding { // … public var forceTouchCapability: UIForceTouchCapability { get } // … } public enum UIForceTouchCapability : Int { case Unknown case Unavailable case Available } /*! Trait environments expose a trait collection that describes their environment. */ public protocol UITraitEnvironment : NSObjectProtocol { public var traitCollection: UITraitCollection { get } /*! To be overridden as needed to provide custom behavior when the environment's traits change. */ public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) } The following interface classes adopt this protocol: UIScreen, UIWindow, UIViewController, UIPresentationController, and UIView.
  • 47. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 48. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 49. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 50. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 51. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 52. Summary • UITouch.force • Static Quick Actions • Dynamic Quick Actions • Peek and Pop • Peek Quick Actions • Detecting 3D Touch
  • 53. Thank you for listening