[iOSアプリ開発] ByteCoin交換レート計算アプリ

iPhoneで動く「ByteCoin交換レート計算アプリ」を作成してみませんか?

複数の通貨が記載されたUIPickerがあり、通貨を選択するとByteCoinとの交換レートを表示してくれるアプリを作成します。

目次

概要

この講座で学習する内容
  • ByteCoin交換レート計算アプリを作成

アプリを作成する過程で、以下の内容を学習できます。

  • プロトコルを使用したデリゲートデザインパターン
  • JSONデータのパースについて
  • Extension
  • UIPickerViewの使い方

MVCデザインパターンを適用しています。
Model(M)、View(V)、Controller(C
記事中、M、V、Cの略を使用しています。

参考にした講座】iOS & Swift – The Complete iOS App Development Bootcamp (Udemy)
 (Section14) Networking and API Challenge

この講座で作成するアプリの概要

ByteCoinとの交換レートを入手し、画面に表示するアプリです。アプリ内のデータの流れの概要は以下の通りです。

  1. 画面下部にあるUIPickerより交換したいレートを選択します。
  2. 交換レートを入手するためのURLを作成します。
  3. CoinAPI.io(https://www.coinapi.io)からAPIを使用して、交換レートを含んだJSONデータを入手します。
  4. JSONデータのパースにより、交換レート、通貨名の情報を取り出します。
  5. UIPickerが更新されると、デリゲートデザインパターンが発動し、取り出した交換レート、通貨の情報がUIに送られます。
  6. UIに交換レート、通貨名が表示されます。
アプリの開発環境(2023年5月2日現在)
  • Xcode: Version 14.3
  • macOS: Venture: Version 13.3.1
  • iOS: 16.4.1
GitHubからプロジェクトを入手したい方はこちら
Xcodeのインストールが未了の方はこちら

UIの設定

開始プロジェクトをクローンして起動した状態を確認してみましょう。

開始プロジェクトの確認

開始プロジェクトの確認
  1. 階層図より、
    Modelフォルダ:CoinManagerファイル
    Viewフォルダ:Main.storyboardファイル
    Controllerフォルダ:ViewControllerファイル
    があることがわかります。
  2. Mainには、上からByteCoinラベル、CoinView、UIPickerViewがあります。
  3. CoinManagerファイルにはすでに通貨の配列がある構造体が作成されています。

UIとコードのリンク

UIPickerから交換レートを取得する

プロトコル(UIPickerViewDataSource)の実装

ViewControllerにUIPickerViewの情報を表示できるようにするため、プロトコル(UIPickerViewDataSource)を実装します。

プロトコル(UIPickerViewDataSource)の実装
//「UIPickerViewDataSource」の実装
class ViewController: UIViewController, 
    UIPickerViewDataSource {
    
    let coinManager = CoinManager()

    override func viewDidLoad() {
        super.viewDidLoad()

// 「UIPickerViewDataSource」の受信者
        currencyPicker.dataSource = self
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
//列は1を設定
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, 
        numberOfRowsInComponent component: Int) -> Int {
 //配列(currencyArray)に含まれている通貨数を設定       
        return coinManager.currencyArray.count
    }
}
  • //「UIPickerViewDataSource」プロトコルの実装
  • //「UIPickerViewDataSource」の受信者

プロトコル(UIPickerViewDelegate)の実装

PickerViewが更新されたことを検知するため、プロトコル(UIPickerViewDelegate)を実装します。

「UIPickerViewDelegate」の実装
//「UIPickerViewDelegate」の実装
class ViewController: UIViewController, 
    UIPickerViewDelegate {
       
    override func viewDidLoad() {
        super.viewDidLoad()

// 「UIPickerViewDelegate」の受信者        
        currencyPicker.delegate = self
    }
    
//UIPickerが更新されると、titleForRowが発動し、更新データ(通貨)を受信
    func pickerView(_ pickerView: UIPickerView, 
        titleForRow row: Int, forComponent component: Int) -> String? {
        return coinManager.currencyArray[row]
    }
}
  • //「UIPickerViewDelegate」プロトコルの実装
  • //「UIPickerViewDelegate」の受信者
  • //UIPickerが更新されると、titleForRowが発動し、更新データ(通貨)を受信

UIPickerViewで選択した通貨を出力

UIPickerViewで選択した通貨が出力されるように赤枠のコードを追記します。

UIPickerView(C)で選択した通貨情報をCoinManager(M)へ送信

UIPickerView(C)で選択した通貨情報をCoinManager(M)へ送信されるように、getCoinPriceメソッドをCoinManager構造体の中に作成します。

UIPickerView(C)
class ViewController: UIViewController, 
    UIPickerViewDataSource, UIPickerViewDelegate {

    func pickerView(_ pickerView: UIPickerView, 
        didSelectRow row: Int, inComponent component: Int) {

        let selectCurrency = coinManager.currencyArray[row]
        coinManager.getCoinPrice(for: selectCurrency)
    }
}
CoinManager(M)
struct CoinManager {
    func getCoinPrice(for currency: String) {       
    }
}

交換レートを取得する

交換レートは、CoinAPI.io(https://www.coinapi.io)からAPIを使用して以下の順序で入手します。

  • URL作成
  • URLセッション作成
  • セッションにタスクを付与
  • タスクの開始

入手したタスクデータは、エンコード(.utf8)して出力しました。

CoinManager(M)
struct CoinManager {
    
    let baseURL = "https://rest.coinapi.io/v1/exchangerate/BTC"
//???にはAPIキーの数値を入力
    let apiKey = "???"
    
    let currencyArray = ["AUD", "BRL","CAD","CNY","EUR","GBP",
        "HKD","IDR","ILS","INR","JPY","MXN","NOK","NZD","PLN",
        "RON","RUB","SEK","SGD","USD","ZAR"]
    
    func getCoinPrice(for currency: String) {
        let urlString = "\(baseURL)/\(currency)?apikey=\(apiKey)"

        //1. URL作成
        if let url = URL(string: urlString) {

            //2. URLセッション作成
            let session = URLSession(configuration: .default)
            
            //3. セッションにタスクを付与
            let task = session.dataTask(with: url) { 
            (data, response, error) in
                if error != nil {
                    print(error!)
                    return
                }
                
                let dataAsString = String(data: data!, encoding: .utf8)
                print(dataAsString)
            }
            
            //4. タスクの開始
            task.resume()
        }
    }
}

BTCとEURの交換レートが26784.***であることがわかります。

UIPickerから交換レートをUIに表示する

JSONデータのパース

取得したJSONデータをSwiftオブジェクトに変換し、交換レートを入手します。

CoinData(M)
import Foundation

struct CoinData: Decodable {
    let rate: Double
}

JSONデータの階層を確認し、”rate”を格納する「CoinData」structを作成

CoinManager(M):parseJSON
func parseJSON(_ data: Data) -> Double? {
        
    let decoder = JSONDecoder()
    do {
//CoinData構造体からデータのデコード
        let decodedData = 
        try decoder.decode(CoinData.self, from: data)
            
//交換レートを取得
        let lastPrice = decodedData.rate
        return lastPrice
            
    } catch {
        print(error)
        return nil
    }
}

交換レートをUIに表示

CoinManager(M-1)において、APIを使用して交換レートが更新されると、
ViewController(C)が、更新された交換レートを入手する仕組み

デリゲートデザインパターン

を実装します。

CoinManager(M-1)
//プロトコルの定義
protocol CoinManagerDelegate {
    func didUpdatePrice(price: String, currency: String)
    func didFailWithError(error: Error)
}

struct CoinManager {

//「CoinManagerDelegate」の司令塔
    var delegate: CoinManagerDelegate?
    func getCoinPrice(for currency: String) {

    if let safeData = data {
            if let bitcoinPrice = self.parseJSON(safeData) {
                        
                let priceString = String(format: "%.2f", bitcoinPrice)
                        
//交換レートが更新されると、didUpdatePriceが発動し、更新データを送付
                self.delegate?.didUpdatePrice(price: priceString, 
                currency: currency)
            }
    }
}
  • //「CoinManagerDelegate」プロトコルの定義
  • //「CoinManagerDelegate」の司令塔
  • //交換レートが更新されると、didUpdatePriceが発動し、更新データを送付
ViewController(C)
//「CoinManagerDelegate」の実装
class ViewController: UIViewController, CoinManagerDelegate {
    var coinManager = CoinManager()

    override func viewDidLoad() {
        super.viewDidLoad()

// 「CoinManagerDelegate」の受信者      
        coinManager.delegate = self
    }

//交換データが更新されると、didUpdatePriceが発動し、更新データを受信
    func didUpdatePrice(price: String, currency: String) { 
        DispatchQueue.main.async {
            self.bitcoinLabel.text = price
            self.currencyLabel.text = currency
        }
    }
  • //「CoinManagerDelegate」の実装
  • // 「CoinManagerDelegate」の受信者
  • //交換データが更新されると、didUpdatePriceが発動し、更新データを受信

交換データ更新後、CADとの交換レートがUIに表示されました。

ViewControllerの機能拡張を分割して整理する

ViewControllerには、「CoinManagerDelegate」、「UIPickerViewDataSource」、「UIPickerViewDelegate」というプロトコルがあります。これらを分割して整理してみましょう。

UIViewController(C)
class ViewController: UIViewController {
    //略
}

//MARK: - CoinManagerDelegate
extension ViewController: CoinManagerDelegate {
    func didUpdatePrice(price: String, currency: String) {
        
        DispatchQueue.main.async {
            self.bitcoinLabel.text = price
            self.currencyLabel.text = currency
        }
    }
    
    func didFailWithError(error: Error) {
        print(error)
    }
}

//MARK: - UIPickerViewDataSource, UIPickerViewDelegate
extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, 
        numberOfRowsInComponent component: Int) -> Int {
        return coinManager.currencyArray.count
    }
    
    func pickerView(_ pickerView: UIPickerView, 
        titleForRow row: Int, forComponent component: Int) -> String? {
        return coinManager.currencyArray[row]
    }

    func pickerView(_ pickerView: UIPickerView, 
        didSelectRow row: Int, inComponent component: Int) {
        let selectCurrency = coinManager.currencyArray[row]
        coinManager.getCoinPrice(for: selectCurrency)
    }

}

これで、アプリ完成です。

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次