Skip to main content
warning

The iOS SwiftUI SDK is currently in preview and does not include a full feature set. Major features supported.

iOS SwiftUI SDK (24.3.3)

Introduction

info

This guide only includes features introduced in the SwiftUI SDK. For a full SDK guide of the latest stable version, see iOS SDK guide.

The Atomic iOS SwiftUI SDK is a dynamic framework for integrating an Atomic stream container into your SwiftUI app, presenting cards from a stream to your end users.

The SwiftUI SDK is written in Swift and supports iOS 16.0 and above.

The latest stable release of the SwiftUI SDK is 24.3.3

Installation

The SDK can be installed using CocoaPods, Swift Package Manager, or manually.

CocoaPods

  1. Add the path to the SDK spec repo to your Podfile, along with the default specs repo:
source 'https://github.com/atomic-app/action-cards-ios-sdk-specs.git'
source 'https://github.com/CocoaPods/Specs.git'
  1. Add the SDK as a dependency.
pod 'AtomicCards', '24.3.3'
  1. Run pod update.

Alternative way to install Atomic SwiftUI SDK

Alternatively, you can install Atomic SDK directly through a git path. This will install the latest Atomic SwiftUI SDK.

pod 'AtomicCards', :git => 'https://github.com/atomic-app/action-cards-swiftui-sdk-releases.git'

Note: Currently you may face a known issue of a "Sandbox: rsync" failing message after integration. You can update your Xcode project build option ENABLE_USER_SCRIPT_SANDBOXING to 'No' to resolve this issue.

Swift Package Manager

  1. Open your Xcode project, and choose File > Add Packages.
  2. Enter https://github.com/atomic-app/action-cards-swiftui-sdk-releases in the upper right text field 'Search or Enter Package URL'.
  3. Set the dependency rule and click 'Add Package'.
  4. Add both AtomicSDK and AtomicSwiftUISDK to your target.

Manual Installation

  1. You can download releases of the SDK from the Releases page on Github.
  2. Once you've downloaded the version you need, navigate to your project in Xcode and select the "General" settings tab.
  3. Drag both AtomicSDK.xcframework and AtomicSwiftUISDK.xcframework from the directory where you unzipped the release, to the Embedded Binaries section.
  4. When prompted, ensure that "Copy items if needed" is selected, and then click "Finish".

Initializing the SDK

As per the standard iOS SDK you need to initialise the SDK before you can do anything else. With SwiftUI you can place it in the init function of your App subclass. For example:

import AtomicSDK

@main
struct SwiftUIBoilerplateApp: App {
init() {
AACSession.login(withEnvironmentId: "<your envid>", apiKey: "<your api key>", sessionDelegate: <your session delegate>, apiBaseUrl: <your api base URL>)
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

Displaying containers

Displaying a vertical container

To display a vertical Stream Container in your view, call StreamContainer within your views body by specifying the flag indicating its presence in a navigation stack, and providing the container Id. StreamContainer also accepts a configuration object that can be ignored by default.

For example:

var body: some View {
NavigationStack {
VStack {
NavigationLink {
ZStack {
StreamContainer(isInNavigationStack: true, containerId: "<stream container id>")
.navigationTitle("Atomic Stream")
}
} label: {
Text("Messages")
}
}
.padding()
.navigationTitle("Atomic Boilerplate")
.navigationBarTitleDisplayMode(.large)
}
}
NavigationStack Presence

Properly setting the isInNavigationStack flag is crucial. In SwiftUI, nested navigation stacks can lead to unexpected behaviors. As such, the container will not attempt to generate its own navigation stack if indicated that it is already within an existing navigation stack.

The configuration object is of type ContainerConfiguration and inherits most of the properties from AACConfiguration. The options have been adapted to align with SwiftUI conventions.

For example to set your configuration object in your view model you could do something like:

    var config = ContainerConfiguration()

init() {
config.setCustomValue("test", for: .cardListTitle)
}

This example sets the stream header title to "test".

To use the configuration you could pass it into the StreamContainer instance:

StreamContainer(isInNavigationStack: true, containerId: "1234", configuration: viewModel.config)

Displaying a Horizontal Container

The Atomic iOS SDK provides support for rendering a horizontal stream container within your host application. The horizontal view displays cards arranged from left to right.

To use this feature, instantiate a HorizontalContainer, which is a SwiftUI View configured similarly to a standard stream container. Upon initialization, please supply the following parameters:

  1. Stream Container ID: The identifier for the stream you wish to render.
  2. Card Width: The width of each card displayed (must be greater than 0).
  3. Configuration (optional): Defines the desired behavior and appearance of the horizontal container.

The available configuration options align with those of a standard stream container. However, please note that certain properties are not applicable to horizontal containers. For detailed information, refer to the definition file of ContainerConfiguration.

NavigationStack Presence

Please ensure the HorizontalContainer is placed within an existing NavigationStack. The HorizontalContainer itself does not generate a navigation stack to avoid putting navigation stacks inside a scroll view, which is a common parent of views like horizontal containers.

Additionally, please refrain from embedding the HorizontalContainer within lazy containers (LazyVStack or LazyHStack), as SwiftUI restricts navigation destinations within lazy-loading containers.

The following example illustrates how to place a horizontal container above a LazyVStack, using a card width of 350 and the default configuration.

var body: some View {
NavigationStack {
ScrollView {
VStack {
HorizontalContainer(containerId: "containerID", cardWidth: 350)
LazyVStack {
ForEach(0..<1000) { _ in Text("Placeholder") }
}
}
}
}
}

Note: Pull to refresh functionality and swipe gesture is disabled in horizontal containers.

Configuration options for a horizontal stream container

In addition to common properties from ContainerConfiguration, the following properties are specifically designed for horizontal containers:

  • horizontalTitleAlignment: Sets the alignment of the title in the horizontal header. Possible values:

    • center: Default value. Title is centered within the header.
    • leading: Title is aligned to the leading edge of the header.
  • horizontalEmptyStyle: Defines how the container appears when no cards are present. Possible values:

    • standard: Default value. Displays a UI indicating no cards are available.
    • shrink: The container shrinks when there are no cards.
  • horizontalScrollMode: Controls scrolling behavior in the container. Possible values:

    • snap: Available on iOS 17.0 and later. Default when available. Enables snapping, positioning each card in the center of the viewport upon scroll termination.
    • free: Default value for iOS 16. The container scrolls freely without snapping.
  • horizontalLastCardAlignment: Aligns the card when only one card is present in the container. Possible values:

    • leading: Default value. Aligns the card to the leading edge.
    • center: Aligns the card to the center of the container.

Displaying a single card container

The Atomic SwiftUI SDK also supports rendering a single card in your host app.

To create an instance of SingleCardContainer, which is configured in the same way as a vertical stream container, you supply the following parameters on instantiation:

  1. The ID of the stream container to render in the single card container. The single card container renders only the first card that appears in that stream container;
  2. A configuration object, which provides initial styling and presentation information to the SDK for the single card container.

The configuration options, supplied using the configuration object above, are the same as those for a stream container. But some properties are not applied to the single card container. For detailed information, refer to the definition file of ContainerConfiguration.

NavigationStack Presence

Please ensure the SingleCardContainer is placed within an existing NavigationStack. The SingleCardContainer itself does not generate a navigation stack to avoid putting navigation stacks inside a scroll view, which is a common parent of views like horizontal containers.

Additionally, please refrain from embedding the SingleCardContainer within lazy containers (LazyVStack or LazyHStack), as SwiftUI restricts navigation destinations within lazy-loading containers.

The code snippet below shows how to display a single card container with some configuration.

var body: some View {
var config = ContainerConfiguration()
config.enabledUIElements = [.cardListToast]
config.cardListRefreshInterval = 10
return NavigationStack {
ScrollView {
VStack {
Text("Header view")
SingleCardContainer(containerId: "containerID", configuration: config)
Text("Footer view")
}
}
}
}

Displaying a Modal Container (Preview)

The Atomic iOS SDK provides support for displaying a modal container within your host application. The modal is displayed as soon as there are cards present in the associated stream container, and displays the first card over a fullscreen overlay, preventing interactions with views behind it. Users may only exit the modal after removing all the presented cards.

To integrate this feature, attach the .modalContainer modifier to your SwiftUI view, providing the following parameters upon initialization:

  1. Stream Container ID: Identifier for the stream container you wish to display.
  2. Configuration (optional): Defines the desired appearance and behavior of the modal container.

The available configuration options align closely with those of a standard stream container; however, please note certain properties are not applicable to modal presentations. For detailed information, refer to the definition file of ContainerConfiguration.

View Hierarchy Considerations

Please note that attaching the .modalContainer modifier affects all subviews. As a result, the modal will be triggered even if the user has navigated to deeper subviews within your view hierarchy.

Several theme properties influence the modal container's appearance, including vertical alignment and padding. For further details, please refer to Modal Container Theme. Should the content within a card exceed the available screen height, the card will become vertically scrollable, ignoring any vertical alignment specified in the theme. Scrollable content is always aligned to the top of the scroll view.

The following example illustrates attaching a modal container to a SwiftUI view using the default configuration:

var body: some View {
Text("placeholder")
.modalContainer(containerId: "containerID")
}

Note: Swipe gestures are disabled within modal containers.

Maximum card width

You can specify a maximum width for each card within the vertical stream container or a single card view, with center alignment for the cards.

To set this, use the cardMaxWidth property in ContainerConfiguration to define the desired width, and apply this configuration when initializing the stream container or the single card view.

The default value for cardMaxWidth is 0, which means the card will automatically adjust its width to match that of the stream container.

However, there are a few considerations for using this property:

  • Setting a value below 200 display points is not recommended, as it may trigger layout constraint warnings when content cannot fit.

  • Negative values behave the same as 0 display points.

  • The padding between the card and container will always be at least 10 display points. For example, on a device with a 440-point screen, any card width exceeding 430 points will be ignored.

The following code snippet sets the maximum card width to 500.

var body: some View {
var configuration = ContainerConfiguration()
configuration.cardMaxWidth = 500
return NavigationStack {
VStack {
NavigationLink {
StreamContainer(isInNavigationStack: true, containerId: "<stream container id>", configuration: configuration)
} label: {
Text("Messages")
}
}
}
}

Third-party dependencies

Atomic iOS SwiftUI SDK contains one third-party dependency:

  • Font Awesome Free 5.15.4, an icon font that is used for card icons. This is distributed as an OTF font.

Atomic iOS SwiftUI SDK does not use any dependency managers, all dependencies are integrated manually.

The standard Atomic iOS SDK is also included within SwiftUI SDK. For more information on its third-party dependencies, see the iOS SDK Guide.

Major features supported in this version

  • Vertical stream container, horizontal container, single card container and modal container
    • including subviews and feedback options
  • Markdown support
  • Theming containers
  • Card actions via buttons, including links and payload options
  • Headline, Image, Text block and List controls
  • Category and Image banners
  • Custom fonts
  • Swipe to snooze and dismiss
  • Overflow menu, including snoozing, dismissing and voting
  • Text input element (Note: Keyboard avoidance is not yet fully implemented.)
  • Number input element
  • Switch element
  • Video element
  • Full support for button styles
  • Stepper element
  • Multiple image heights for banner and inline elements
  • Image linking
  • Checkbox element
  • Custom icons
  • Card max width
  • Accessibility