Let’s Build with Swift - 1: Maps and App Structure

1312
3
05-17-2023 12:08 PM
Ting
by Esri Contributor
Esri Contributor
4 3 1,312

arcgis-maps-sdk.png

Build Your First SwiftUI Mapping App With ArcGIS Maps SDK for Swift

 

Welcome! In a series of bite-sized articles, we'll guide you through building an app using ArcGIS Maps SDK for Swift with Apple's latest SwiftUI framework. Whether you are an experienced Runtime SDK user, or a first-time adopter of our new SDK, you will learn the key concepts of SwiftUI and how to implement the mapping workflows with the latest technology. It's easier than ever to create performant, beautiful apps!

ArcGIS Maps SDK for Swift (200.x) builds upon the capabilities and proven architecture of ArcGIS Runtime SDK for iOS (100.15). It adds support for the latest developer platforms, frameworks, and tooling, utilizing out of the box support for features, such as:

  • SwiftUI
  • Swift Concurrency and Networking
  • Native Swift features
    • Default parameters
    • Enumerations with associated values
    • Measurement
    • Protocols
    • Value types
  • Native Swift collections and data types

… and much more!

To take advantage of recent advances in the Swift language, we have released the brand new ArcGIS Maps SDK for Swift (referred to as the Swift Maps SDK or the ArcGIS framework later in the blog).

If you already have an app built upon ArcGIS Runtime SDK, there is a Migration topics to help you transition to the new programming patterns.

 

Prerequisites

 

ArcGIS Maps SDK for Swift has a target SDK version of 15.0, meaning that it can run on devices with iOS and iPadOS 15.0 or newer.

 

Topics In This Post

 

  • Create a project with SwiftUI and ArcGIS Maps SDK for Swift
  • Use Swift Package Manager to manage dependencies
  • Add a map view to your app
  • Configure your app with API key and license strings

 

Creating a SwiftUI Project

 

Let's start with creating a new iOS app project, Mapper. In the Interface menu, select SwiftUI.

Creating a new project in XcodeCreating a new project in Xcode

SwiftUI provides you with easy to learn declarative syntax code for you to design your UI. Watch your code execute in real-time using the live preview. No need to build. No more complex Storyboard (Interface Builder), constraints, auto layout issues, segue management, and view hierarchy difficulties!

 

Adding Swift Maps SDK using Swift Package Manager

 

First things first, add the ArcGIS framework to your project dependencies using Swift Package Manager. Select File > Add Packages. Paste in the GitHub repository URL for the Swift Maps SDK: https://github.com/Esri/arcgis-maps-sdk-swift, and select Add Package.

Adding the ArcGIS Maps SDK for Swift packageAdding the ArcGIS Maps SDK for Swift package

Swift Package Manager is an open-source tool built and maintained by Apple for managing dependencies in Swift projects. It is integrated within Xcode, so you don't need to install a 3rd party program to use it.

As a Swift package, the Swift Maps SDK is much easier to integrate, compared to the older dependency management tools such as CocoaPods or Carthage, which cause conflicts from time to time. It also benefits from other enhanced Swift package capabilities, such as semantic versioning with auto update, offline installation as a local Swift package, etc.

 

Creating a Map View

 

In ContentView.swift, you'll see a ContentView struct. You may already know that the body property is where all the views need to go. Replace the prefilled "hello world" text and image views in the VStack with the following code…

 

import ArcGIS

struct ContentView: View {
    @State private var map = Map(basemapStyle: .arcGISTopographic)

    var body: some View {
        MapView(map: map)
    }
}

 

and you are all set - it's super simple!

Xcode interface with SwiftUI live previewXcode interface with SwiftUI live preview

On the preview canvas on the right side, you should be able to see the preview of ContentView, specifically, a blank view with a "Powered By Esri" attribution bar. If you don't see the preview pane, go to Editor > Canvas. Xcode will display an up-to-date preview as you make changes to the view's code. Make sure the Live Preview (the play button) on the lower left corner of the preview pane is selected, so you can interact with the preview in real time.

Swift Maps SDK requires an API key to access various services including the basemaps. Go to MapperApp.swift, and add the code to set the API key.

 

import ArcGIS

// In the MapperApp struct.
init() {
    ArcGISEnvironment.apiKey = APIKey("<#your-API-key#>")
}

 

Later in the App Structure Demystified section, we'll discuss the App protocol and the entry point to your app in detail.

At this point, you should be able to see the live preview of a map view, as seen in the screenshot above. Pan and zoom around the map, and you'll find the familiar map view experience, just like our previous ArcGIS Runtime SDK, or any other maps SDK you may have used before.

Voilà! Write 2 lines of code, and you have access to the powerful ArcGIS mapping capabilities. Isn't that amazing? 🤩

 

SwiftUI vs UIKit: A Comparison

 

SwiftUI was introduced back in 2019 with iOS 13 as the next generation UI framework for Apple cross-platform development. Compared to its predecessor UIKit, SwiftUI has many advantages, including but not limited to…

  • All UI is written in code. No more Interface Builder merge conflicts!
  • Views update automatically when state changes. No more 2-way bindings or notification-triggered UI updates!
  • Automatic adaptive layout made easy. Do you still remember the hassle to configure constraints and Auto Layout in storyboard? In most cases, SwiftUI automatically finds the best fitting view size, so that the views are snapped right to the edges of various layout guides. Best of all, you get these layout and sizing behaviors for free!
  • Live previews enable real-time UI feedback. Now you don't need to build the entire project to view a single change to a `UILabel`. Instead, it appears on the screen instantly when you make the change.
  • SwiftUI is a cross-platform framework. Developers can deploy the app to multiple platforms (iOS, macOS, watchOS, tvOS) with minimal changes in the codebase.

So far, you may have noticed that the SwiftUI declarative framework is completely unlike the UIKit imperative programming patterns. In subsequent blog posts, we will discuss various conceptual differences between them. Here, let's take a look at the view hierarchy.

Go back to ContentView.swift. ContentView is a structure that conforms to the View protocol. A view defines one or more visual elements that appear somewhere on a screen. A view is typically made up of other views, creating a view hierarchy. It has a computed property body, where all the subviews should be implemented.

In the section above, we put a MapView in the body. By default, the view is centered. In terms of sizing, there are 3 typical sizes for a view:

1-View-frames.png

  • Flexible: The view tries to take up as much space as it can on the screen. Think of a rectangle Shape. The MapView falls in this category.
  • Fixed: The view has a fixed frame, such as an image, or a view with specified fixed frame.
  • Adaptive: Depending on its content, the view negotiates its size with its neighbors. Think of a Text, whose size is influenced by font, line break, line spacing, word wrapping, etc. ArcGIS callout on a map view is an example.

 

Wireframe showing the basic layout concepts in SwiftUIWireframe showing the basic layout concepts in SwiftUITo construct your custom view layout, use the HStack, VStack and ZStack layout containers. These are more powerful than the UIStackView and allow you to group collections of views horizontally, vertically, or stacked on top of each other. They are the building blocks that you can put inside other container views, such as List and ScrollView. These three kinds of stacks, with their alignment and spacing properties, view modifiers, and Spacer views, allow extensive layout flexibility.

Views in SwiftUI are descriptions of what to display for a given state, rather than an instance that you have direct access. So at this point, you may wonder - how do I access the MapView? How can I set the viewpoint, change the map, add layers and graphics to the map view, etc.?

Later in the series, you'll gradually realize that in SwiftUI world, the map view doesn't need to be directly accessed. There are exceptions such identifying features and setting viewpoint with animation, which we'll talk about in detail later, along with various view modifiers.

One thing to highlight: ArcGIS Maps SDK for Swift is a pioneering first-class mapping framework that builds upon SwiftUI and Swift natively. Instead of porting legacy code using UIViewRepresentable, we built everything from scratch with SwiftUI-thinking in mind. This gives you a hassle-free, fluent developer experience with Apple's latest technologies.

 

App Structure Demystified

 

As an iOS developer, you may be familiar with the UIApplicationDelegate protocol and AppDelegate.application(_:didFinishLaunchingWithOptions:) method as your app's entry point. In the new SwiftUI application lifecycle, the idea is similar, but the App protocol and method names are significantly simplified.

Let's take a look at MapperApp.swift. With the above changes, it should look this…

 

import SwiftUI
import ArcGIS

@main
struct MapperApp: App {
    init() {
        ArcGISEnvironment.apiKey = APIKey("<#your-API-key#>")
    }
    
    var body: some SwiftUI.Scene {
        WindowGroup {
            ContentView()
                .ignoresSafeArea()
        }
    }
}

 

  • The main attribute provides the entry point to your app. App protocol provides a default implementation of the main() method to launch your app.
  • In the init() method, you can configure various prerequisites prior to your app's first screen being shown. For our use case, it is a great place to set the API Key or apply license strings, if necessary.
  • The app's body conforms to the SwiftUI.Scene protocol. A scene acts as a container for a view hierarchy that you want to display to the user. You know what you are looking at if you are familiar with UISceneDelegate.
  • WindowGroup is a container for a view hierarchy presented by your app. For a typical app that runs within 1 single window, this is where the root view of the app should go.

Additional side notes:

  1. You will need to import ArcGIS in order to set the API key and license strings. Please see the links at the bottom of the page for further details.
  2. Due to the namespace conflict between SwiftUI.Scene and ArcGIS.Scene (the 3D globe model in ArcGIS), you have to specify SwiftUI.Scene to make the app compile. Alternatively, you can limit the ArcGIS imports to the types being used, such as:

 

import enum ArcGIS.ArcGISEnvironment
import struct ArcGIS.APIKey

 

Coming Up Next

 

🎉Congratulations, hopefully you understand the structure of a SwiftUI-based app and how to integrate ArcGIS Maps SDK for Swift into your app.

In the next post, we'll discuss how you manage states and data flow using SwiftUI to make your app better structured and production-ready. Stay tuned!

 

Links

3 Comments