Logo

dev-resources.site

for different kinds of informations.

Creating an iOS Currency Exchange Rate Widget: A Step-by-Step Guide

Published at
5/8/2023
Categories
swift
ios
widget
Author
dimaportenko
Categories
3 categories in total
swift
open
ios
open
widget
open
Author
12 person written this
dimaportenko
open
Creating an iOS Currency Exchange Rate Widget: A Step-by-Step Guide

Introduction:

Widgets are a powerful way to provide users with a glanceable view of your app's information right on their iPhone's Home Screen or Today View. With iOS 14 and later, you can create your own custom widgets to provide useful information at a glance. In this tutorial, we'll walk you through creating a currency exchange rate widget that fetches data from an API and displays it on the widget. We'll be using the endpoint from PrivatBank to retrieve exchange rates for USD and EUR against UAH.

Prerequisites:

  • Xcode (latest version)
  • macOS with the latest version of SwiftUI
  • Basic understanding of SwiftUI and Swift programming language
  • An active Apple Developer account

Let's get started!

1. Create a new Xcode project:

Open Xcode and create a new project using the "App" template under "iOS." Give your project a name, such as "Private Exchange," and choose "SwiftUI" as the Interface and "Swift" as the Language. Set the minimum deployment target to iOS 14 or later, as widgets are not supported in earlier versions.

2. Add a new Widget Extension:

In the Xcode Project Navigator, click on "File" > "New" > "Target." Choose the "Widget Extension" template and click "Next." Give your widget extension a name, such as "PrivateExchangeWidget," and make sure the "Language" is set to "Swift." Click "Finish" to create the widget extension.

3. Create a data model for the currency rates:

In the widget extension folder, create a new Swift file called "CurrencyRate.swift" and define a CurrencyRate struct that conforms to the Decodable protocol. This struct will represent the currency rate data fetched from the API.

   struct CurrencyRate: Decodable {
       let ccy: String
       let base_ccy: String
       let buy: String
       let sale: String
   }
Enter fullscreen mode Exit fullscreen mode

4. Create a data fetcher to fetch currency rates from the API:

In the same folder, create another Swift file called "CurrencyRateFetcher.swift" and define a CurrencyRateFetcher class with a shared singleton instance. This class will be responsible for fetching currency rates from the API.

   import Foundation

   class CurrencyRateFetcher {
       static let shared = CurrencyRateFetcher()
       private let apiUrl = "https://api.privatbank.ua/p24api/pubinfo?exchange&coursid=5"

       func fetchRates(completion: @escaping ([CurrencyRate]?) -> Void) {
           guard let url = URL(string: apiUrl) else {
               completion(nil)
               return
           }

           let task = URLSession.shared.dataTask(with: url) { data, response, error in
               guard let data = data, error == nil else {
                   completion(nil)
                   return
               }

               let decoder = JSONDecoder()
               let currencyRates = try? decoder.decode([CurrencyRate].self, from: data)
               completion(currencyRates)
           }

           task.resume()
       }
   }
Enter fullscreen mode Exit fullscreen mode

5. Modify the widget's timeline provider to fetch data (continued):

Update the getTimeline(for:in:completion:) method to fetch currency rates from the API and pass them to the SimpleEntry.

   func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
       CurrencyRateFetcher.shared.fetchRates { currencyRates in
           let currentDate = Date()
           let entry = SimpleEntry(date: currentDate, currencyRates: currencyRates)
           let refreshDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
           let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
           completion(timeline)
       }
   }
Enter fullscreen mode Exit fullscreen mode

This code fetches the currency rates and creates a timeline entry with the current date and fetched rates. The timeline policy is set to .after(refreshDate), which will refresh the data every hour.

6. Update the widget's view to display currency rates:

Open the main Swift file for the widget (e.g., "Private_Exchange.swift") and modify the Private_ExchangeEntryView to display the currency rates in a SwiftUI view.

   struct Private_ExchangeEntryView : View {
       var entry: Provider.Entry

       private func currencySymbol(for code: String) -> String {
           switch code {
           case "EUR":
               return "€"
           case "USD":
               return "$"
           case "UAH":
               return "â‚´"
           default:
               return code
           }
       }

       var body: some View {
           VStack {
               if let currencyRates = entry.currencyRates {
                   ForEach(currencyRates, id: \.ccy) { rate in
                       HStack {
                           Text("\(currencySymbol(for: rate.ccy))")
                           Spacer()
                           Text("\(Double(rate.buy)?.rounded(toPlaces: 2) ?? 0) / \(Double(rate.sale)?.rounded(toPlaces: 2) ?? 0)")
                       }
                   }
               } else {
                   Text("Loading...")
               }
           }
           .padding()
       }
   }
Enter fullscreen mode Exit fullscreen mode

This code defines a currencySymbol(for:) function that returns the appropriate currency symbol for a given currency code. The view displays a list of currency rates using a VStack and ForEach, or a "Loading..." text if the rates are not yet available.

7. Test the widget:

Build and run the project on an iOS simulator or a physical device to see the currency exchange rate widget in action. You can add the widget to the Home Screen or Today View by following the standard process for adding widgets on iOS.

Conclusion:

In this tutorial, we've walked you through creating a custom currency exchange rate widget for iOS using SwiftUI and an API. You can now expand on this basic implementation to add more functionality, such as user-configurable currency pairs or different display styles for the widget. Happy coding!

widget Article's
30 articles in total
Favicon
Forex Ticker Widget: Simplifying Forex Monitoring for Users
Favicon
Passing variables from the static page to the widget
Favicon
How to launch a React Native app from the Lock Screen on iPhone
Favicon
Free Currency HTML-Widgets
Favicon
Integrating Live Forex Quotes into Your Trading Platform Seamlessly
Favicon
Implement a Secure, Dynamic Domain Approval System for Embeddable Widgets in Ruby on Rails
Favicon
The Future of Professional Networking on LinkedIn: How Businesses Can Adapt and Stay Ahead
Favicon
Embed JS Widgets with Rails: A Step-by-Step Guide
Favicon
Create embeddable widgets in react for static pages
Favicon
FloatyNavBar: Elevate Your Flutter App's Navigation
Favicon
Web music player with html-css-javascript
Favicon
Free Currency HTML-Widgets
Favicon
Building an embeddable Widget
Favicon
Video, Live Chat & Help Center widget for the website
Favicon
100 Common Flutter widget list
Favicon
Back to basic : Flutter widget lifecycle
Favicon
FlutterFlow has introduced this fantastic new draggable widget!
Favicon
Bigcommerce Widget Migration
Favicon
Simple Digital Clock Widget
Favicon
Exploring Simple Widgets II: Autocomplete
Favicon
Improved Data Point Graph Widget for Cumulocity IoT
Favicon
Enhancing Cumulocity IoT Capabilities: Map-Based Widgets
Favicon
The Journey of a Widget: Understanding the Lifecycle in Flutter
Favicon
flutter row widget example
Favicon
Flutter Column Widget Example
Favicon
Common Widgets in Flutter
Favicon
Creating an iOS Currency Exchange Rate Widget: A Step-by-Step Guide
Favicon
Flutter Custom Widget
Favicon
How to embed appointment scheduling widget on your website?
Favicon
How to screenshot a widget in the flutter

Featured ones: