SwiftMessages
Overview
SwiftMessages is a very flexible view and view controller presentation library for iOS.
Message views and view controllers can be displayed at the top, bottom, or center of the screen, or behind navigation bars and tab bars. There are interactive dismiss gestures including a fun, physics-based one. Multiple background dimming modes. And a lot more!
In addition to the numerous configuration options, SwiftMessages provides several good-looking layouts and themes. But SwiftMessages is also designer-friendly, which means you can fully and easily customize the view:
- Copy one of the included nib files into your project and change it.
- Subclass
MessageView
and add elements, etc. - Or just supply an arbitrary instance of
UIView
.
Try exploring the demo app via appetize.io to get a feel for the extensive configurability of SwiftMessages.
View Controllers
SwiftMessages can present view controllers using the SwiftMessagesSegue
custom modal segue!
SwiftMessagesSegue
is a subclass of UIStoryboardSegue
that integrates directly into Interface Builder as a custom modal segue, enabling view controllers to take advantage of SwiftMessages layouts, animations and more. SwiftMessagesSegue
works with any UIKIt project — storyboards are not required. Refer to the View Controllers readme below for more information.
View Controllers Readme
And check out our blog post Elegant Custom UIViewController Transitioning to learn a great technique you can use to build your own custom segues that utilize UIViewControllerTransitioningDelegate
and UIViewControllerAnimatedTransitioning
.
Installation
Swift Package Manager
Go to File | Swift Packages | Add Package Dependency...
in Xcode and search for "SwiftMessages". If multiple results are found, select the one owned by SwiftKick Mobile.
CocoaPods
Add the following line to your Podfile:
pod 'SwiftMessages'
Carthage
Add the following line to your Cartfile:
github "SwiftKickMobile/SwiftMessages"
If the Carthage build fails, try using the script.
Manual
- Put SwiftMessages repo somewhere in your project directory.
- In Xcode, add
SwiftMessages.xcodeproj
to your project. - On your app's target, add the SwiftMessages framework:
- as an embedded binary on the General tab.
- as a target dependency on the Build Phases tab.
Usage
Basics
SwiftMessages.show(view: myView)
Although you can show any instance of UIView
, SwiftMessages provides a MessageView
class
and assortment of nib-based layouts that should handle most cases:
// Instantiate a message view from the provided card view layout. SwiftMessages searches for nib
// files in the main bundle first, so you can easily copy them into your project and make changes.
let view = MessageView.viewFromNib(layout: .cardView)
// Theme message elements with the warning style.
view.configureTheme(.warning)
// Add a drop shadow.
view.configureDropShadow()
// Set message title, body, and icon. Here, we're overriding the default warning
// image with an emoji character.
let iconText = ["🤔", "😳", "🙄", "😶"].randomElement()!
view.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: iconText)
// Increase the external margin around the card. In general, the effect of this setting
// depends on how the given layout is constrained to the layout margins.
view.layoutMarginAdditions = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
// Reduce the corner radius (applicable to layouts featuring rounded corners).
(view.backgroundView as? CornerRoundingView)?.cornerRadius = 10
// Show the message.
SwiftMessages.show(view: view)
You may wish to use the view provider variant show(viewProvider:)
to ensure that
your UIKit code is executed on the main queue:
SwiftMessages.show {
let view = MessageView.viewFromNib(layout: .cardView)
// ... configure the view
return view
}
The SwiftMessages.Config
struct provides numerous configuration options that can be passed to show()
:
var config = SwiftMessages.Config()
// Slide up from the bottom.
config.presentationStyle = .bottom
// Display in a window at the specified window level.
config.presentationContext = .window(windowLevel: .statusBar)
Note that, as of iOS 13, it is no longer possible to cover the status bar
regardless of the window level. A workaround is to hide the status bar instead.
config.prefersStatusBarHidden = true
// Disable the default auto-hiding behavior.
config.duration = .forever
// Dim the background like a popover view. Hide when the background is tapped.
config.dimMode = .gray(interactive: true)
// Disable the interactive pan-to-hide gesture.
config.interactiveHide = false
// Specify a status bar style to if the message is displayed directly under the status bar.
config.preferredStatusBarStyle = .lightContent
// Specify one or more event listeners to respond to show and hide events.
config.eventListeners.append() { event in
if case .didHide = event { print("yep") }
}
SwiftMessages.show(config: config, view: view)
Specify default configuration options:
SwiftMessages.defaultConfig.presentationStyle = .bottom
// Show message with default config.
SwiftMessages.show(view: view)
// Customize config using the default as a base.
var config = SwiftMessages.defaultConfig
config.duration = .forever
SwiftMessages.show(config: config, view: view)
Accessibility
SwiftMessages provides excellent VoiceOver support out-of-the-box.
-
The title and body of the message are combined into a single announcement when the message is shown. The
MessageView.accessibilityPrefix
property can be set to prepend additional clarifying text to the announcement.Sometimes, a message may contain important visual cues that aren't captured in the title or body. For example, a message may rely on a yellow background to convey a warning rather than having the word "warning" in the title or body. In this case, it might be helpful to set
MessageView.accessibilityPrefix = "warning"
. -
If the message is shown with a dim view using
config.dimMode
, elements below the dim view are not focusable until the message is hidden. Ifconfig.dimMode.interactive == true
, the dim view itself will be focusable and read out "dismiss" followed by "button". The former text can be customized by setting theconfig.dimModeAccessibilityLabel
property.
See the AccessibleMessage
protocol for implementing proper accessibility support in custom views.
Keyboard Avoidance
The KeyboardTrackingView
class can be used to cause the message view to avoid the keyboard by sliding up when the keyboard gets too close.
var config = SwiftMessages.defaultConfig
config.keyboardTrackingView = KeyboardTrackingView()
You can incorporate KeyboardTrackingView
into your app even when you're not using SwiftMessages. Install into your view hierarchy by pinning KeyboardTrackingView
to the bottom, leading, and trailing edges of the screen. Then pin the bottom of your content that should avoid the keyboard to the top KeyboardTrackingView
. Use an equality constraint to strictly track the keyboard or an inequality constraint to only move when the keyboard gets too close. KeyboardTrackingView
works by observing keyboard notifications and adjusting its height to maintain its top edge above the keyboard, thereby pushing your content up. See the comments in KeyboardTrackingView
for configuration options.
Message Queueing
You can call SwiftMessages.show()
as many times as you like. SwiftMessages maintains a queue and shows messages one at a time. If your view implements the Identifiable
protocol (like MessageView
), duplicate messages will be removed automatically. The pause between messages can be adjusted:
SwiftMessages.pauseBetweenMessages = 1.0
There are a few ways to hide messages programatically:
// Hide the current message.
SwiftMessages.hide()
// Or hide the current message and clear the queue.
SwiftMessages.hideAll()
// Or for a view that implements `Identifiable`:
SwiftMessages.hide(id: someId)
// Or hide when the number of calls to show() and hideCounted(id:) for a
// given message ID are equal. This can be useful for messages that may be
// shown from multiple code paths to ensure that all paths are ready to hide.
SwiftMessages.hideCounted(id: someId)
Multiple instances of SwiftMessages
can be used to show more than one message at a time. Note that the static SwiftMessages.show()
and other static APIs on SwiftMessage
are just convenience wrappers around the shared instance SwiftMessages.sharedInstance
). Instances must be retained, thus it should be a property of something (e.g. your view controller):
class SomeViewController: UIViewController {
let otherMessages = SwiftMessages()
func someMethod() {
SwiftMessages.show(...)
otherMessages.show(...)
}
}
Retrieving Messages
There are several APIs available for retrieving messages that are currently being shown, hidden, or queued to be shown. These APIs are useful for updating messages
when some event happens without needing to keep temporary references around.
See also eventListeners
.
// Get a message view with the given ID if it is currently
// being shown or hidden.
if let view = SwiftMessages.current(id: "some id") { ... }
// Get a message view with the given ID if is it currently
// queued to be shown.
if let view = SwiftMessages.queued(id: "some id") { ... }
// Get a message view with the given ID if it is currently being
// shown, hidden or in the queue to be shown.
if let view = SwiftMessages.currentOrQueued(id: "some id") { ... }
Customization
SwiftMessages can display any UIView
. However, there are varying degrees of customization that can be done to the bundled views.
Nib Files
All of the message designs bundled with SwiftMessages have associated nib files. You are encouraged to copy any of these nib files into your project and modify them to suit your needs. SwiftMessages will load your copy of the file instead of the original. Nib files may be copied in Xcode using drag-and-drop.
To facilitate the use of nib-based layouts, MessageView
provides some type-safe convenience methods for loading the bundled nibs:
let view = MessageView.viewFromNib(layout: .cardView)
In addition, the SwiftMessages
class provides some generic loading methods:
// Instantiate MessageView from a named nib.
let view: MessageView = try! SwiftMessages.viewFromNib(named: "MyCustomNib")
// Instantiate MyCustomView from a nib named MyCustomView.nib.
let view: MyCustomView = try! SwiftMessages.viewFromNib()
MessageView Class
MessageView
is a light-weight view that all of the bundled designs use. It primarily consists of the following optional @IBOutlet
properties:
Element | Declaration | Description |
---|---|---|
Title | titleLabel: UILabel? |
The message title. |
Message body | bodyLabel: UILabel? |
The body of the message. |
Image icon | iconImageView: UIImageView? |
An image-based icon. |
Text icon | iconLabel: UILabel? |
A text-based (emoji) alternative to the image icon. |
Button | button: UIButton? |
An action button. |
The SwiftMessages nib file use MessageView
as the top-level view with content connected to these outlets. The layouts are done using stack views, which means that you can remove an element by simply hiding it:
view.titleLabel.isHidden = true
A common mistake is attempting to remove an element by setting the corresponding outlet to nil
. This does not work because it does not remove the element from the view hierarchy.
Configuration
MessageView
provides numerous methods that follow the configure*
naming convention:
view.configureTheme(.warning)
view.configureContent(title: "Warning", body: "Consider yourself warned.", iconText: "🤔")
All of these methods are shortcuts for quickly configuring the underlying view properties. SwiftMessages strives to avoid doing any internal magic in these methods, so you do not need to call them. You can configure the view properties directly or combine the two approaches.
Interaction
MessageView
provides an optional block-based tap handler for the button and another for the view itself:
// Hide when button tapped
messageView.buttonTapHandler = { _ in SwiftMessages.hide() }
// Hide when message view tapped
messageView.tapHandler = { _ in SwiftMessages.hide() }
Extending
The suggested method for starting with MessageView
as a base and adding new elements, such as additional buttons, is as follows:
- Copy one of the bundled nib files into your project or create a new one from scratch.
- Add new elements to the nib file.
- Sublcass
MessageView
and create outlets for the new elements. - Assign the top-level view in the nib file to the subclass.
- Connect outlets between the nib file and the subclass.
- (recommended) override the implementation of
Identifiable
as needed to incorporate new elements into the message's identity. - (recommended) override the implementation of
AccessibleMessage
as needed to incorporate new elements into Voice Over. - Use one of the nib-loading methods above to load the view.
BaseView Class
BaseView
is the superclass of MessageView
and provides numerous options that aren't specific to the "title + body + icon + button" design of MessageView
. Custom views that are significantly different from MessageView
, such as a progress indicator, should subclass BaseView
.
CornerRoundingView Class
CornerRoundingView
is a custom view that messages can use for rounding all or a subset of corners with squircles (the smoother method of rounding corners that you see on app icons). The nib files that feature rounded corners have backgroundView
assigned to a CornerRoundingView
. It provides a roundsLeadingCorners
option to dynamically round only the leading corners of the view when presented from top or bottom (a feature used for the tab-style layouts).
Animator Protocol
Animator
is the protocol that SwiftMessages uses for presentation and dismissal animations. Custom animations can be done through the SwiftMessages.PresentationStyle.custom(animator:)
. Some related components:
TopBottomAnimation
is a sliding implementation ofAnimator
used internally by.top
and.bottom
presentation styles. It provides some customization options.PhysicsAnimation
is a scaling + opacity implementation ofAnimator
used internally by the.center
presentation style. It provides a fun physics-based dismissal gesture and provides customization options including.top
and.bottom
placement.PhysicsPanHandler
provides the physics-based dismissal gesture forPhysicsAnimation
and can be incorporated into otherAnimator
implementations.
High-quality PRs for cool Animator
implementations are welcome!
MarginAdjustable Protocol
MarginAdjustable
is a protocol adopted by BaseView
. If the view being presented adopts MarginAdjustable
, SwiftMessages takes ownership of the view's layout margins to ensure ideal spacing across the full range of presentation contexts.
BackgroundViewable Protocol
BackgroundViewable
is a protocol adopted by BaseView
and requires that a view provide a single backgroundView
property. BaseView
initializes backgroundView = self
, which you can freely re-assign to any subview.
If the view being presented adopts BackgroundViewable
, SwiftMessages will ignore touches outside of backgroundView
. This is important because message views always span the full width of the device. Card and tab-style layouts appear inset from the edges of the device because the message view's background is transparent and backgroundView
is assigned to a subview constrained to the layout margins. In these layouts, touches in the transparent margins should be ignored.
Identifiable Protocol
Identifiable
is a protocol adopted by MessageView
and requires that a view provide a single id
property, which SwiftMessages uses for message deduplication.
MessageView
computes the id
based on the message content, but id
can also be set explicitly as needed.
AccessibleMessage Protocol
AccessibleMessage
is a protocol adopted by MessageView
. If the view being presented adopts AccessibleMessage
, SwiftMessages provides improved Voice Over.
About SwiftKick Mobile
We build high quality apps! Get in touch if you need help with a project.
License
SwiftMessages is distributed under the MIT license. See LICENSE for details.
Github
link |
Stars: 5928 |
You may find interesting
Releases
- 2021-01-17T20:23:40
Features
- #447 Add the ability to show view controller in a new window with
SwiftMessagesSegue
. This capability is available when usingSwiftMessagesSegue
programmatically by supplying an instance ofWindowViewController
as the segue's source view controller.
Fixes
- #451 Fix app extension crash
Changes
- This release has minor breaking changes in the
WindowViewController
initializers. ThewindowLevel
is no longer accepted as an argument because theconfig
parameter should specify the window level in thepresentationContext
property.
- 2020-12-20T17:52:04
Fixes
- #446 Restore previous key window on dismissal if the message assumed key window status.
- 2020-12-15T15:21:28
Features
- #442 Added
MarginAdjustable.respectSafeArea
option to exclude safe area from layout margins. - #430 Support disable
becomeKeyWindow
from SwiftMessages.Config. This is a workaround for potential issues with apps that display additional windows.
Fixes
- #437 Revert to explicitly specifying "SwiftMessages" as the module in nib files.
- #440 Fix crash when using SwiftMessages in app extension
SPM Support - 2020-10-25T21:21:05
Features
- Full support for Swift Package Manager
Fixes
- #328 ignoreDuplicates is not working
- #412 Fix deployment target on nib files to match target
SPM Partial Support for Xcode 11 - 2020-08-18T21:49:30
Changes
- #395 Add preliminary support for Swift Package Manager.
Long overdue - 2020-07-09T19:10:40
Sorry for taking so long to release this.
Changes
- Add
SwiftMessages.PresentationContext.windowScene
option for targeting a specific window scene. - Changed the behavior of the default
presentationContext
,.automatic
. Previously, if the root view controller was presenting, the message would only be displayed over the presented view controller if themodalPresentationStyle
wasfullScreen
oroverFullScreen
. Now, messages are always displayed over presented view controllers. - Made
showDuraton
andhideDuration
onAnimator
non-optional. - Made
showDuraton
andhideDuration
writable options onTopBottomAnimation
andPhysicsAnimation
.
Fixes
- #365 Fix an issue with customized
TopBottomAnimation
where messages weren't properly displayed under navigation and tab bars. - #352 Fix accessibility for view controllers presented with
SwiftMessagesSegue
. - #355 Update card view layout to support centering of pure textual content
- #354 Support
overrideUserInterfaceStyle
when view presented in its own window - #360 Fix touch handing issue in iOS 13.1.3
- #382 Fix warnings in Xcode 11.4
iOS 13 - 2019-09-19T14:48:23
Changes
- Support iOS 13.
Features
- #335 Add option to hide status bar when view is displayed in a window. As of iOS 13, windows can no longer cover the status bar. The only alternative is to set
Config.prefersStatusBarHidden = true
to hide it.
No more warnings - 2019-05-23T14:40:34
Changes
- Swift 5
- Remove deprecated APIs
Features
- #313 Improved sizing on iPad
SwiftMessagesSegue
provides default view controller sizing based on device, with width on iPad being limited to 500pt max. However, it is recommended that you explicitly specify size appropriate for your content using one of the following methods.
- Define sufficient width and height constraints in your view controller such that it sizes itself.
- Set the
preferredContentSize
property (a.k.a "Use Preferred Explicit Size" in Interface Builder's attribute inspector). Zeros are ignored, e.g.CGSize(width: 0, height: 350)
only affects the height.- Add explicit width and/or height constraints to
segue.messageView.backgroundView
.Note that
Layout.topMessage
andLayout.bottomMessage
are always full screen width. For other layouts, the there is a maximum 500pt width on for regular horizontal size class (iPad) at 950 priority. This limit can be overridden by adding higher-priority constraints.
- #275 Add ability to avoid the keyboard.
The
KeyboardTrackingView
class can be used to cause the message view to avoid the keyboard by sliding up when the keyboard gets too close.// Message view var config = SwiftMessages.defaultConfig config.keyboardTrackingView = KeyboardTrackingView() // Or view controller segue.keyboardTrackingView = KeyboardTrackingView()
You can incorporate
KeyboardTrackingView
into your app even when you're not using SwiftMessages. Install into your view hierarchy by pinningKeyboardTrackingView
to the bottom, leading, and trailing edges of the screen. Then pin the bottom of your content that should avoid the keyboard to the topKeyboardTrackingView
. Use an equality constraint to strictly track the keyboard or an inequality constraint to only move when the keyboard gets too close.KeyboardTrackingView
works by observing keyboard notifications and adjusting its height to maintain its top edge above the keyboard, thereby pushing your content up. See the comments inKeyboardTrackingView
for configuration options.
- #276 Add ability to hide message without animation
- #272 Add duration for
SwiftMessagesSegue
- #278 Make pan gesture recognizers public
- 2018-12-26T23:15:47
Swift 4.2 - 2018-09-20T14:12:32
Fix Demo app - 2018-09-03T15:57:28
Fixes
- Remove debug code that broke the view controller's section of the Demo app.
View Controllers - 2018-08-29T14:15:37
Breaking Changes
- Removed support for iOS 8.
Features
- Add support for modal view controller presentation using
SwiftMessagesSegue
custom segue subclass. Try it out in the "View Controllers" section of the Demo app. In addition to the class documentation, more can be found in the View Controllers readme. - Update nib files to be more visually consistent with iPhone X:
- Introduce
CornerRoundingView
, which provides configurable corner rounding using squircles (the smoother method of rounding corners that you see on app icons). Nib files that feature rounded corners have theirbackgroundView
assigned to aCornerRoundingView
.CornerRoundingView
provides aroundsLeadingCorners
option to dynamically round only the leading corners of the view when presented from top or bottom (a feature used for the tab-style layouts). - Increased the default corner radius to 20. Corner radius can be changed by either modifying the nib file or
- Introduce
- Reworked the
MarginAdjustable
to improve configurability of layout margins. - Add rubber-banding to the interactive dismissal gesture. Rubber banding is automatically applied for views where
backgroundView
is inset from the message view's edges. - Added
showDuration
andhideDuration
properties to theAnimator
protocol (with default implementation that returnsnil
). These values enable animations to work for view controller presentation.
Fixes
- #202 bodyLabel should set textAlignment to .natural
- #200 Automatic Presentation Context Broken
- Fix default value of
TopBottomAnimation.closePercentThreshold
Whoops - 2018-05-25T14:15:38
Bug Fixes
- Fix #191 Prevent usage of UIApplication.shared when building for extensions
Improvements
- #192 Add a way to test compilation with app extension
Support Extensions - 2018-05-23T21:39:46
Features
- #183 Added iOS app extension support at compile time.
Bug Fixes
- Fix #185 Incorrect margin adjustments in landscape
- Fix #188 Physics animation visual glitch
Swift 4.1 - 2018-04-02T19:11:18
4.1.2
Features
- Updates for Swift 4.1
- #164 Added an optional
windowViewController
property toSwiftMessages.Config
for supplying a custom subclass ofWindowViewController
.
Bug Fixes
- Custom presentation styles using
TopBottomAnimation
now display properly under top and bottom bars.
- 2017-11-15T14:45:02
Features
- Fix #134 add support for
CenterAnimation
displayed on top or bottom instead of center (renamed toPhysicsAnimation
).
Fixes
- Fix #128 move icons out of asset catalog to prevent mysterious crash
- Fix #129 adjust layout margins on orientation change to preserve layout when iOS hides status bar in landscape.
- Fix #131 by always completing hide/show animations if application isn't active.
iOS 11 and iPhone X - 2017-09-21T00:26:13
Features
-
Swift 4.0 syntax
-
Added support for iOS 11 and iPhone X. From the readme:
SwiftMessages 4 supports iOS 11 out-of-the-box with built-in support for safe areas. To ensur that message view layouts look just right when overlapping safe areas, views that adopt the
MarginAdjustable
protocol (likeMessageView
) will have their layout margins automatically adjusted by SwiftMessages. However, there is no one-size-fits-all adjustment, so the following properties were added toMarginAdjustable
to allow for additional adjustments to be made to the layout margins:public protocol MarginAdjustable { ... /// Safe area top adjustment in iOS 11+ var safeAreaTopOffset: CGFloat { get set } /// Safe area bottom adjustment in iOS 11+ var safeAreaBottomOffset: CGFloat { get set } }
If you're using using custom nib files or view classes and your layouts don't look quite right, try adjusting the values of these properties.
BaseView
(the super class ofMessageView
) declares these properties to be@IBDesignable
and you can find sample values in the nib files included with SwiftMessages.
Bug Fixes
- Fix #100 memory leak.
- Change
Layout
enum capitalization to current Swift conventions.
- 2017-09-12T15:20:34
Bug Fixes
- Undo change that broke
MessageView
class reference on nib files copied out of the SwiftMessages framework.
3.5.0 - 2017-09-06T14:27:15
Features
-
Added
SwiftMessages.hideCounted(id:)
method of hiding. The counted method hides when the number of calls toshow()
andhideCounted(id:)
for a given message ID are equal. This can be useful for messages that may be shown from multiple code paths to ensure that all paths are ready to hide.Also added
SwiftMessages.count(id:)
to get the current count andSwiftMessages.set(id:count:)
to set the current count. -
Added ways to retrieve message views currently being shown, hidden, or queued to be shown.
// Get a message view with the given ID if it is currently // being shown or hidden. if let view = SwiftMessages.current(id: "some id") { ... } // Get a message view with the given ID if is it currently // queued to be shown. if let view = SwiftMessages.queued(id: "some id") { ... } // Get a message view with the given ID if it is currently being // shown, hidden or in the queue to be shown. if let view = SwiftMessages.currentOrQueued(id: "some id") { ... }
Bug Fixes
- Fix #116 for message views that don't adopt the
Identifiable
protocol by using the memory address as the ID. - Fix #113 MessageView not hiding
- Fix #87 Support manual install
Centered Messages - 2017-07-01T16:41:43
- Added
.center
presentation style with a physics-based dismissal gesture. - Added
.custom(animator:)
presentation style, where you provide an instance of theAnimator
protocol. TheTopBottomAnimation
andCenterAnimation
animations both implementAnimator
and may be subclassed (configuration options will be added in a future release). You may use thePhysicsPanHandler
class to incorporate a physics-based dismissal gesture into any custom animator. - Added
.centered
message view layout with elements centered and arranged vertically. - Added
configureBackgroundView(width:)
andconfigureBackgroundView(sideMargin:)
convenience methods toMessageView
.
Add .blur Dim Mode - 2017-06-14T15:29:03
- 2017-03-31T19:53:12
Voice Over Improvements - 2017-03-27T16:05:38
Improvements
-
MessageView
is smarter about including additional accessibility views for cases where you've added accessible elements to the view. Previously only thebutton
was included. Now all views whereisAccessibilityElement == true
are included.Note that all nib files now have
isAccessibilityElement == false
fortitleLabel
,bodyLabel
andiconLabel
(titleLabel
andbodyLabel
are read out as part of the overall message view's text). If any of these need to be directly accessible, then copy the nib file into your project and select "Enabled" in the Accessibility section of the Identity Inspector.
Hot Fix - 2017-03-13T14:48:16
Fix regression where the UI was being blocked when using DimMode.none
.
Voice Over - 2017-03-12T19:22:14
From the README:
SwiftMessages provides excellent VoiceOver support out-of-the-box.
-
The title and body of the message are combined into a single announcement when the message is shown. The
MessageView.accessibilityPrefix
property can be set to prepend additional clarifying text to the announcement.Sometimes, a message may contain important visual cues that aren't captured in the title or body. For example, a message may rely on a yellow background to convey a warning rather than having the word "warning" in the title or body. In this case, it might be helpful to set
MessageView.accessibilityPrefix = "warning"
. -
If the message is shown with a dim view using
config.dimMode
, elements below the dim view are not focusable until the message is hidden. Ifconfig.dimMode.interactive == true
, the dim view itself will be focusable and read out "dismiss" followed by "button". The former text can be customized by setting theconfig.dimModeAccessibilityLabel
property.
See the AccessibleMessage
protocol for implementing proper accessibility support in custom views.
Hot Fix - 2017-03-06T12:19:04
Bug Fixes
- Fix infinite loop bug introduced in 3.2.0.
Indefinite Duration - 2017-03-05T18:01:46
Features
-
Added the ability to display messages for an indefinite duration while enforcing a minimum duration using
Duration.indefinite(delay:minimum)
.This option is useful for displaying a message when a process is taking too long but you don't want to display the message if the process completes in a reasonable amount of time.
For example, if a URL load is expected to complete in 2 seconds, you may use the value
unknown(delay: 2, minimum 1)
to ensure that the message will not be displayed most of the time, but will be displayed for at least 1 second if the operation takes longer than 2 seconds. By specifying a minimum duration, you can avoid hiding the message too fast if the operation finishes right after the delay interval.
Bug Fixes
- Prevent views below the dim view from receiving accessibility focus.
- Prevent taps in the message view from hiding when using interactive dim mode.
- Fix memory leak of single message view