What s New in imessage Apps

Similar documents
imessage Apps and Stickers, Part 2

Using and Extending the Xcode Source Editor

What s New in MapKit. App Frameworks #WWDC17. Fredrik Olsson

Advanced Notifications

Enhancing your apps for the next dimension of touch

Data Delivery with Drag and Drop

What s New in watchos

Mastering UIKit on tvos

Mastering Drag and Drop

Modern User Interaction on ios

Extending Your Apps with SiriKit

Media and Gaming Accessibility

What s New in tvos #WWDC16. App Frameworks. Session 206. Hans Kim tvos Engineer

What s New in tvos 12

View Controller Advancements for ios8

Getting the Most out of Playgrounds in Xcode

Quick Interaction Techniques for watchos

What s New in Cocoa for macos

Leveraging Touch Input on ios

What s New in Core Data?

What s New in NSCollectionView Session 225

Introducing Password AutoFill for Apps

Implementing UI Designs in Interface Builder

lecture 10 UI/UX and Programmatic Design cs : spring 2018

Introduction to Siri Shortcuts

Engineering for Testability

Core ML in Depth. System Frameworks #WWDC17. Krishna Sridhar, Core ML Zach Nation, Core ML

Announcements. Today s Topics

Managing Documents In Your ios Apps

Cocoa Touch Best Practices

Core Data Best Practices

Creating Audio Apps for watchos

Building Apps with Dynamic Type

Monetize and Promote Your App with iad

Getting the Most Out of HealthKit

Creating Complications with ClockKit Session 209

Using Grouped Notifications

Building for Voice with Siri Shortcuts

Accessibility on ios. Developing for everyone. Frameworks #WWDC14. Session 210 Clare Kasemset ios Accessibility

Designing for Apple Watch

Mysteries of Auto Layout, Part 1

What's New in UIKit Dynamics and Visual Effects Session 229

Touch Bar Fundamentals

Apple Watch Design Tips and Tricks

Advanced Scrollviews and Touch Handling Techniques

What s New in Testing

Stanford CS193p. Developing Applications for ios. Spring CS193p. Spring 2016

Building Watch Apps #WWDC15. Featured. Session 108. Neil Desai watchos Engineer

What s New in SiriKit

ios Accessibility Developing for everyone Session 201 Ian Fisch ios Accessibility

ios Memory Deep Dive #WWDC18 Kyle Howarth, Software Engineer James Snee, Software Engineer Kris Markel, Software Engineer

App Extension Best Practices

What s New in ARKit 2

New Ways to Work with Workouts

Enabling Your App for CarPlay

WatchKit In-Depth, Part 2

Designing Great Apple Watch Experiences

Introducing the Photos Frameworks

What s New in Xcode App Signing

Stanford CS193p. Developing Applications for ios. Winter CS193p. Winter 2017

Stanford CS193p. Developing Applications for ios. Spring CS193p. Spring 2016

Building Visually Rich User Experiences

Introduction to WatchKit. CS193W - Spring Lecture 1

View Controller Lifecycle

Build Cross Platform Video Chat Apps With Xamarin

Adopting Advanced Features of the New UI

Swift API Design Guidelines

What s New in SpriteKit

What s New in Notifications

Writing Energy Efficient Apps

What s New in HomeKit

Integrating Apps and Content with AR Quick Look

What's New in Core Spotlight

Stanford CS193p. Developing Applications for ios. Winter CS193p. Winter 2017

Advances in AVFoundation Playback

Accessibility on OS X

Creating Content with iad JS

What s New in Foundation for Swift Session 207

Introducing the Modern WebKit API

Understanding Undefined Behavior

Introducing PDFKit on ios

New UIKit Support for International User Interfaces

CloudKit Tips And Tricks

Your Apps and the Future of macos Security

Seamless Linking to Your App

CarPlay Audio and Navigation Apps

Stanford CS193p. Developing Applications for ios. Fall Stanford CS193p. Fall 2011

Event Delivery: The Responder Chain

Building Faster in Xcode

Multitasking Support on the ios Platform

What s New in Core Bluetooth

Finding Bugs Using Xcode Runtime Tools

Stanford CS193p. Developing Applications for ios. Fall CS193p. Fall

Stanford CS193p. Developing Applications for ios. Winter CS193p! Winter 2015

Introducing SiriKit. Hey Siri, say hello to apps #WWDC16. App Frameworks. Session 217

What s New in Audio. Media #WWDC17. Akshatha Nagesh, AudioEngine-eer Béla Balázs, Audio Artisan Torrey Holbrook Walker, Audio/MIDI Black Ops

Introducing On Demand Resources

Vision Framework. Building on Core ML. Media #WWDC17. Brett Keating, Apple Manager Frank Doepke, He who wires things together

CSE 438: Mobile Application Development Lab 2: Virtual Pet App

Stanford CS193p. Developing Applications for ios. Fall CS193p. Fall

Transcription:

Session App Frameworks #WWDC17 What s New in imessage Apps 234 Eugene Bistolas, Messages Engineer Jay Chae, Messages Engineer Stephen Lottermoser, Messages Engineer 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

What s New in Messages Direct Send Live Message Layouts Best Practices

What s New in Messages Direct Send Live Message Layouts Best Practices

What s New in Messages Direct Send Live Message Layouts Best Practices

What s New in Messages Direct Send Live Message Layouts Best Practices

What s New in Messages Direct Send Live Message Layouts Best Practices

imessage App Fundamentals

imessage App Fundamentals imessage Apps and Stickers Part 2 WWDC 2016

What s New in Messages

Direct Send NEW

// imessage App Insert Draft API open func insert(_ message: MSMessage, completionhandler: ((Error?) -> Void)? = nil) open func insert(_ sticker: MSSticker, completionhandler: ((Error?) -> Void)? = nil) open func inserttext(_ text: String, completionhandler: ((Error?) -> Void)? = nil) open func insertattachment(_ URL: URL, withalternatefilename filename: String?, completionhandler: ((Error?) -> Void)? = nil)

// imessage App Direct Send API open func send(_ message: MSMessage, completionhandler: ((Error?) -> Void)? = nil) open func send(_ sticker: MSSticker, completionhandler: ((Error?) -> Void)? = nil) open func sendtext(_ text: String, completionhandler: ((Error?) -> Void)? = nil) open func sendattachment(_ URL: URL, withalternatefilename filename: String?, completionhandler: ((Error?) -> Void)? = nil)

Choosing a Send API Insert draft API Insert is recommended for most imessage apps Best for rich message composition Append comments Send with effects, full screen moments Allow user confirmation for sent content

Choosing a Send API Direct send API Provides quick fire and forget user experience Great for flows where inserting message, then sending, adds extra step Maintain trust in your app Clearly indicate to user what content will be sent Clearly denote UI elements that trigger a send

imessage App Direct Send API requirements Messages enforces requirements for API use App must be visible App can send one message per user interaction No further messages can be sent until next interaction New error codes

imessage App Direct Send API requirements Messages enforces requirements for API use App must be visible App can send one message per user interaction No further messages can be sent until next interaction New error codes // MSMessage Error Codes public enum MSMessageErrorCode: Int { // New ios 11 Error Codes @available(ios 11.0, *) case sendwithoutrecentinteraction } @available(ios 11.0, *) case sendwhilenotvisible

Direct Send New fast and easy send experience For some apps, direct send provides excellent alternative to staging drafts Consider which API is best for your app

NEW Live Message Layouts Stephen Lottermoser, Messages Engineer

NEW

NEW

NEW

NEW

NEW

Demo

Live Message Layouts How do they work? imessage app MSMessagesAppViewController.compact

Live Message Layouts How do they work? imessage app MSMessagesAppViewController.compact MSMessagesAppViewController.transcript

Live Message Layouts How do they work? imessage app

Live Message Layouts How do they work? imessage app MSMessagesAppViewController.transcript

Live Message Layouts How do they work? imessage app MSMessagesAppViewController.transcript MSMessagesAppViewController.transcript

Live Message Layouts How do they work? imessage app MSMessagesAppViewController.transcript MSMessagesAppViewController.transcript MSMessagesAppViewController.transcript

Live Message Layouts Sending and receiving messages Jay Chae, Messages Engineer

MSMessageLayout MSMessageTemplateLayout

MSMessageLayout MSMessageTemplateLayout MSMessageLiveLayout

// MSMessageLiveLayout @available(ios 11.0, *) open class MSMessageLiveLayout : MSMessageLayout { public init(alternatelayout: MSMessageTemplateLayout) } open var alternatelayout: MSMessageTemplateLayout { get }

MSMessageLiveLayout Alternate layout Used on: Devices without your imessage app installed Devices running ios 10 Devices running watchos 3 or macos Sierra and later

MSMessageLiveLayout Alternate layout imessage app not installed imessage app installed

// Composing a Message, Sample code let alternatelayout = MSMessageTemplateLayout() alternatelayout.caption = summarytext alternatelayout.subcaption = readabledateformatter.string(from: event.date) alternatelayout.image = UIImage(named: event.fallbackimagename) let layout = MSMessageLiveLayout(alternateLayout: alternatelayout) let message = MSMessage() message.layout = layout conversation.send(message, completionhandler: nil)

// Composing a Message, Sample code let alternatelayout = MSMessageTemplateLayout() alternatelayout.caption = summarytext alternatelayout.subcaption = readabledateformatter.string(from: event.date) alternatelayout.image = UIImage(named: event.fallbackimagename) let layout = MSMessageLiveLayout(alternateLayout: alternatelayout) let message = MSMessage() message.layout = layout conversation.send(message, completionhandler: nil)

// Composing a Message, Sample code let alternatelayout = MSMessageTemplateLayout() alternatelayout.caption = summarytext alternatelayout.subcaption = readabledateformatter.string(from: event.date) alternatelayout.image = UIImage(named: event.fallbackimagename) let layout = MSMessageLiveLayout(alternateLayout: alternatelayout) let message = MSMessage() message.layout = layout conversation.send(message, completionhandler: nil)

// Composing a Message, Sample code let alternatelayout = MSMessageTemplateLayout() alternatelayout.caption = summarytext alternatelayout.subcaption = readabledateformatter.string(from: event.date) alternatelayout.image = UIImage(named: event.fallbackimagename) let layout = MSMessageLiveLayout(alternateLayout: alternatelayout) let message = MSMessage() message.layout = layout conversation.send(message, completionhandler: nil)

MSMessagesAppViewController

MSMessagesAppViewController

MSMessagesAppViewController

MSMessagesAppViewController MSMessagesAppViewController

// Configuring a MSMessagesAppViewController subclass for display public enum MSMessagesAppPresentationStyle : UInt { case compact case expanded @available(ios 11.0, *) case transcript }

// Configuring a MSMessagesAppViewController subclass for display public enum MSMessagesAppPresentationStyle : UInt { case compact case expanded @available(ios 11.0, *) case transcript }

MSMessagesAppViewController Configuring for display When willbecomeactive(with:) is called, you have enough information to configure your view controller presentationstyle activeconversation?.selectedmessage

MSMessagesAppViewController Configuring for display When willbecomeactive(with:) is called, you have enough information to configure your view controller presentationstyle activeconversation?.selectedmessage MSMessagesAppViewController.transcript Transcript Child View Controller (selectedmessage)

MSMessagesAppViewController Configuring for display When willbecomeactive(with:) is called, you have enough information to configure your view controller presentationstyle activeconversation?.selectedmessage MSMessagesAppViewController.transcript MSMessagesAppViewController.compact Transcript Child View Controller (selectedmessage) Compact Child View Controller (selectedmessage)

// Configuring a MSMessagesAppViewController subclass for display override func willbecomeactive(with conversation: MSConversation) { super.willbecomeactive(with: conversation) let message = activeconversation?.selectedmessage switch presentationstyle { case.compact: presentsummaryviewcontroller(for: message) case.expanded: presentdetailviewcontroller(for: message) }

// Configuring a MSMessagesAppViewController subclass for display override func willbecomeactive(with conversation: MSConversation) { super.willbecomeactive(with: conversation) let message = activeconversation?.selectedmessage switch presentationstyle { case.compact: presentsummaryviewcontroller(for: message) case.expanded: presentdetailviewcontroller(for: message) case.transcript: presenttranscriptviewcontroller(for: message) } }

// Configuring a MSMessagesAppViewController subclass for display override func willbecomeactive(with conversation: MSConversation) { super.willbecomeactive(with: conversation) let message = activeconversation?.selectedmessage switch presentationstyle { case.compact: presentsummaryviewcontroller(for: message) case.expanded: presentdetailviewcontroller(for: message) case.transcript: presenttranscriptviewcontroller(for: message) } }

// Configuring a MSMessagesAppViewController subclass for display public enum MSMessagesAppPresentationStyle : UInt { case compact case expanded @available(ios 11.0, *) case transcript } @available(ios 11.0, *) public protocol MSMessagesAppTranscriptPresentation { public func contentsizethatfits(_ size: CGSize) -> CGSize }

// Configuring a MSMessagesAppViewController subclass for display public enum MSMessagesAppPresentationStyle : UInt { case compact case expanded @available(ios 11.0, *) case transcript } @available(ios 11.0, *) public protocol MSMessagesAppTranscriptPresentation { public func contentsizethatfits(_ size: CGSize) -> CGSize }

Displaying a Message Sizing your content override func contentsizethatfits(_ size: CGSize) -> CGSize { let contentheight: CGFloat = 217.0 let titlefont = EventCountdownTranscriptView.titleFont let titleheight = titlefont.lineheight } let totalheight = contentheight + titleheight return CGSize(width: size.width, height: totalheight)

Displaying a Message Sizing your content override func contentsizethatfits(_ size: CGSize) -> CGSize { let contentheight: CGFloat = 217.0 let titlefont = EventCountdownTranscriptView.titleFont let titleheight = titlefont.lineheight } let totalheight = contentheight + titleheight return CGSize(width: size.width, height: totalheight)

Displaying a Message Sizing your content override func contentsizethatfits(_ size: CGSize) -> CGSize { let contentheight: CGFloat = 217.0 let titlefont = EventCountdownTranscriptView.titleFont let titleheight = titlefont.lineheight 235 pts } let totalheight = contentheight + titleheight return CGSize(width: size.width, height: totalheight)

Displaying a Message Sizing your content override func contentsizethatfits(_ size: CGSize) -> CGSize { let contentheight: CGFloat = 217.0 let titlefont = EventCountdownTranscriptView.titleFont let titleheight = titlefont.lineheight } let totalheight = contentheight + titleheight return CGSize(width: size.width, height: totalheight) 244 pts

Code Demo

Live Message Layouts Interaction and more Stephen Lottermoser, Messages Engineer

Demo Adding interaction

Interaction Keep views lightweight Simple buttons or tap gestures Limit use of scroll views No keyboard input

Interaction Use other presentation styles for complex interactions requestpresentationstyle(.expanded)

Lifecycle

Lifecycle Extension callbacks In ios 10, these methods referred to the extension s lifecycle class MSMessagesAppViewController { open func willbecomeactive(with conversation: MSConversation) open func didresignactive(with conversation: MSConversation) }

Lifecycle Extension callbacks In ios 10, these methods referred to the extension s lifecycle class MSMessagesAppViewController { open func willbecomeactive(with conversation: MSConversation) open func didresignactive(with conversation: MSConversation) }

Lifecycle Extension callbacks In ios 11, these methods referred to the view controller s lifecycle class MSMessagesAppViewController { open func willbecomeactive(with conversation: MSConversation) open func didresignactive(with conversation: MSConversation) }

Lifecycle Extension callbacks Observe extension notifications for extension lifecycle events public static let NSExtensionHostWillEnterForeground: NSNotification.Name public static let NSExtensionHostDidEnterBackground: NSNotification.Name public static let NSExtensionHostWillResignActive: NSNotification.Name public static let NSExtensionHostDidBecomeActive: NSNotification.Name

View Controller Lifecycle Live message layout When presenting a transcript presentation style view controller, methods will be called in this order class MSMessagesAppViewController { }

View Controller Lifecycle Live message layout When presenting a transcript presentation style view controller, methods will be called in this order class MSMessagesAppViewController { public init(nibname nibnameornil: String?, bundle nibbundleornil: Bundle?) open func viewdidload() }

View Controller Lifecycle Live message layout When presenting a transcript presentation style view controller, methods will be called in this order class MSMessagesAppViewController { public init(nibname nibnameornil: String?, bundle nibbundleornil: Bundle?) open func viewdidload() open func willbecomeactive(with conversation: MSConversation) open func didbecomeactive(with conversation: MSConversation) }

View Controller Lifecycle Live message layout When presenting a transcript presentation style view controller, methods will be called in this order class MSMessagesAppViewController { public init(nibname nibnameornil: String?, bundle nibbundleornil: Bundle?) open func viewdidload() open func willbecomeactive(with conversation: MSConversation) open func didbecomeactive(with conversation: MSConversation) open func viewwillappear(_ animated: Bool) open func viewdidappear(_ animated: Bool) }

View Controller Lifecycle Live message layout When presenting a transcript presentation style view controller, methods will be called in this order class MSMessagesAppViewController { } public init(nibname nibnameornil: String?, bundle nibbundleornil: Bundle?) open func viewdidload() open func willbecomeactive(with conversation: MSConversation) open func didbecomeactive(with conversation: MSConversation) open func viewwillappear(_ animated: Bool) open func viewdidappear(_ animated: Bool) open func contentsizethatfits(_ size: CGSize) -> CGSize

View Controller Lifecycle Live message layout When willbecomeactive is called, you have enough information to configure your view controller class MSMessagesAppViewController { public init(nibname nibnameornil: String?, bundle nibbundleornil: Bundle?) open func viewdidload() open func willbecomeactive(with conversation: MSConversation) open func didbecomeactive(with conversation: MSConversation) open func viewwillappear(_ animated: Bool) open func viewdidappear(_ animated: Bool) } open func contentsizethatfits(_ size: CGSize) -> CGSize

View Controller Lifecycle Live message layout contentsizethatfits() is called last It may be called multiple times in response to events in Messages open func contentsizethatfits(_ size: CGSize) -> CGSize

Pending Messages

open class MSMessage: NSObject, NSCopying, NSSecureCoding { } @available(ios 11.0, *) open var ispending: Bool { get }

Live Message Layouts Interactive imessage apps in the transcript! Same MSMessagesAppViewController base class New layout: MSMessageLiveLayout New presentation style:.transcript

Best Practices Eugene Bistolas, Messages Engineer

imessage App Area Insets Updated insets for Messages app area Insets can be determined via [UIView safeareainsets] UIViewController top/bottomlayoutguide Autolayout Legacy apps get old insets

imessage App Area Insets Updated insets for Messages app area Insets can be determined via [UIView safeareainsets] UIViewController top/bottomlayoutguide Autolayout Legacy apps get old insets

Message Summary Text Succinct message summary Provide summary for each message Visible in notifications and conversation list // MSMessage open var summarytext: String?

Stickers Preferred format: PNG / APNG Optimizations Sticker pixel size Frame rate File size Adhering to guidelines ensures fast launch, quick sends For more info, reference Messages Human Interface Guidelines

MFMessageComposeViewController MSMessage API Match user experience between imessage app and parent app Template and Live layout support Received messages can open in imessage app or parent app // MFMessageComposeViewController /// This property sets the initial interactive message. @available(ios 10.0, *) @NSCopying open var message: MSMessage?

Best Practices Use layout margins Set summarytext on all MSMessages Consider sticker size, frame rate, for faster stickers Send app balloons from MFMessageComposeViewController

Summary What s New in Messages Direct Send Live Message Layouts Best Practices

More Information https://developer.apple.com/wwdc17/234

Related Sessions Introducing Business Chat Hall 3 Friday 10:00AM Design Studio Shorts 3 Executive Ballroom Friday 11:00AM

Labs imessage Apps and Business Chat Lab Technology Lab B Fri 11:00AM 2:00PM