Updating from an API

The following is a snippet showing how to takes parts of a Lightwell document, update them with data from an api call, and trigger animations to preset a promotional popup.

This snippet uses the exported assets here, and presents the contents inside of a view controller. To try out the code download the assets and include them inside of an xcode project. For a detailed walkthrough of the snippet, check out the Updating from an API Walkthrough.

import UIKit
import LightwellKit

class ViewController: UIViewController {
    // 1) Initialize the loading context for the promo popup
    let context = LWKLoadingContext(screenName: "promo")

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        self.getRemoteData()
    }

    func getRemoteData() {
        guard let url = URL(string: "https://s3.amazonaws.com/lightwell/docs/sample/promo-api.json") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard let data = data, error == nil else {
                // Failed to get data
                if let error = error { print(error) }
                return
            }

            // Parse data
            guard let parsedData = try? JSONSerialization.jsonObject(with: data, options: []),
                let usableData = parsedData as? [String: String] else {
                // Failed to read data
                return
            }

            // Since we are updating the UI, this will need to be performed on the main thread.
            DispatchQueue.main.async {
                // Only grab the views we care about in the design from Lightwell.
                // 2) Add overlay to screen
                if let background = self.context?.view(for: "background") {
                    background.frame = self.view.bounds
                    self.view.addSubview(background)
                }
                // 3) Add popup to screen
                if let popup = self.context?.view(for: "popup") {
                    self.view.addSubview(popup)
                }

                // 4) Update contents based on response
                // Option 1 Update text ignoring style
                if let buttonTitle = usableData["button"] {
                    (self.context?.view(for: "button title") as? UILabel)?.text = buttonTitle
                }
                // Option 2 Manually update text preserving style
                if let title = usableData["title"] {
                    if let currentAttributes = (self.context?.view(for: "title") as? UILabel)?.attributedText {
                        let attributedText = NSMutableAttributedString(attributedString: currentAttributes)
                        attributedText.mutableString.setString(title)
                        (self.context?.view(for: "title") as? UILabel)?.attributedText = attributedText
                    }
                }
                // Option 3 Use a convenience function for updating text preserving style
                (self.context?.view(for: "copy") as? UILabel)?.setText(usableData["copy"], keepingAttributes: true)

                // 5) Add inputs to respond to promo
                self.context?.view(for: "background")?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dismissPopup)))
                self.context?.view(for: "button")?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.respondToButton)))

                if let rawImageURL = usableData["image url"], let imageUrl = URL(string: rawImageURL) {
                    let imageDownloadTask = URLSession.shared.dataTask(with: imageUrl) { (data, response, error) in
                        guard let data = data, let image = UIImage(data: data) else {
                            // Failed to get image
                            if let error = error { print(error) }
                            else { print("Unable to read data as image.") }
                            return
                        }

                        DispatchQueue.main.async {
                            // Update image content
                            (self.context?.view(for: "image") as? UIImageView)?.image = image

                            // 6.a) Show the popup by running the animation action
                            self.context?.action(for: "show popup")?.run()
                        }
                    }
                    imageDownloadTask.resume()
                } else {
                    // 6.b) Show the popup by running the animation action
                    self.context?.action(for: "show popup")?.run()
                }
            }
        }

        task.resume()
    }

    @objc
    func dismissPopup() {
        // Hide the popup and background
        context?.action(for: "dismiss popup")?.run()
    }

    @objc
    func respondToButton() {
        // Play 'success' animation
        context?.action(for: "follow button")?.delegate = self
        context?.action(for: "follow button")?.run()
    }
}

extension ViewController: LWKActionDelegate {
    func actionDidEnd(_ action: LWKAction, finished: Bool) {
        // Follow button
        print("decided to follow button")
    }
}

The API is currently in beta and everything inside of these docs will be changing to improve the SDK. If there is a change you’d like to see or have any feedback, please email us at dev@lightwell.pro.