Press ESC to close

Swift Currency App (Part – 1)

Hello friends. In this article, we will release the same applications using different architectures on iOS level with you. For this, we first need to find a theme. I thought the currency application might be good for this. Then we will have to make a design. For this there will be a simple listing page and then an application that shows the type of the chosen install in terms of other currencies.

First, I will explain the processes we will do in each project here. Afterwards, we will learn about how to write applications with MVC, MVVM and VIPER. Since I learned while writing, I may have mistakes. We can correct it together by sending a comment or e-mail. Apart from that, you can find more detailed explanations here. I definitely recommend you to watch them all.

First, we need to open Xcode and create a workspace here. Because we will write the API layer separately. Thus, we can create a more reusable and more testable project. After creating the workspace, we need to create a new project into the workspace. After the new project, we need to add a framework for the API layer. After doing these processes, a workspace like this should be created.

In the API section, we will pull the data over the internet. We will use the https://fixer.io/ site to extract currency data. Of course, we need a token to use this service. We can obtain this token by registering on this site. We will then use Alamofire to pull data from the URL. You need to learn how to use the pod to install Alamofire. This article may give you some information. Frankly, I could not add pods to multiple projects here. Instead I added Alamofire with Swift Package Manager. You can find an article about it here. After adding this framework, we can start pulling data from the service.

First, we must model the data from the service in order to properly receive and use it. There are very good sites for converting incoming data into models. I am using this site. The model I have obtained is like this;

//
//  CurrencyModel.swift
//  CurrencyAppAPI
//
//  Created by Omer Sezer on 16.08.2020.
//  Copyright © 2020 Omer Sezer. All rights reserved.
//

import Foundation

public struct CurrencyModel: Codable {
    public var success: Bool?
    public var timestamp: Int?
    public var base, date: String?
    public var rates: [String: Double]?
}

If we get an error on the service side, I’m creating another model for us to handle it.

//
//  BaseErrorModel.swift
//  CurrencyAppAPI
//
//  Created by Omer Sezer on 16.08.2020.
//  Copyright © 2020 Omer Sezer. All rights reserved.
//

import Foundation

public struct BaseErrorModel: Codable {
    public var errorCode: Int?
    public let message: String?
    public let errors: [ErrorData]?
    
    public init(errorCode: Int?, message: String?, errors: [ErrorData]?) {
        self.message = message
        self.errors = errors
        self.errorCode = errorCode
    }
}

public struct ErrorData: Codable {
    public let field, message: String?
    
    public init(field: String?, message: String?) {
        self.field = field
        self.message = message
    }
}

Finally, I do the data extraction process from the service. For this, I create a class called Services and pull the data with Alamofire.

//
//  Services.swift
//  CurrencyAppAPI
//
//  Created by Omer Sezer on 16.08.2020.
//  Copyright © 2020 Omer Sezer. All rights reserved.
//

import Foundation
import Alamofire

public class Services {
    
    private let access_token = "2a908987315bf3a333c0d879c174a1e5"
    private var serviceURL = "http://data.fixer.io/api/latest?access_key="
    
    public init() {
        serviceURL += access_token
    }
    
    public func getCurrencies(successCompletion: @escaping ((_ json: CurrencyModel) -> Void), errorCompletion: @escaping ((_ message: BaseErrorModel) -> Void)) {
        print(serviceURL)
        AF.request(serviceURL, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil).response { (response) in
            switch response.result {
            case .success(let json):
                do {
                    let currencies = try JSONDecoder().decode(CurrencyModel.self, from: data)
                    successCompletion(currencies)
                } catch {
                    errorCompletion(BaseErrorModel(errorCode: nil, message: error.localizedDescription, errors: nil))
                }
                break
            case .failure(let error):
                errorCompletion(BaseErrorModel(errorCode: nil, message: error, errors: nil))
            }
        }
    }
}

When I run the service I see it works fine.

In the next article, we will display the data coming from the service on the screen with MVC architecture.

If you have questions, you can reach by e-mail or comment. Good work.

Leave a Reply

Your email address will not be published. Required fields are marked *