10 ByteCoin

36393 ワード


プロジェクトから学んだこと

UIPickerView , JSON Parsing , Protocol , delegate , extension

UIPickerView


今回のプロジェクトで初めて学んだスキルです.Pickerは上のGIFでも見ることができ、それは底の選択部分を意味する.さらにiOSでは、UIPCkerViewによってPickerを制御することができます.
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        currencyPicker.dataSource = self // 중요
        currencyPicker.delegate = self   // 중요
        coinManager.delegate = self
    }
    
    // 구성요소 수 세팅
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        // 이건 아마도 카테고리 같다.
        // 우린 그냥 각 화폐단위를 보여줄꺼니까 카테고리는 한개
        return 1
    }
    
    // 얘는 반환을 Int 로 하고
    // Picker에 보여지는 개수를 출력하는 듯 하다.
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        // 아마도 코인 개수를 의미하는 듯 하다.
        return coinManager.currencyArray.count
    }
    
    // 얘는 반환을 String으로 한다.
    // Picker에 보여지는 화폐단위를 return한다.
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        // 아래 코드는 아마도, 해당 열의 화폐단위를 세팅하는 듯 하다.
        return coinManager.currencyArray[row]
    }
    
    // 선택했을때 해당 인덱스가 반환되는 pickerView
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let selectCurrencyArray = coinManager.currencyArray[row]
        // 선택한 화폐단위의 가치를 가져오는 메서드
        coinManager.getCoinPrice(for: selectCurrencyArray)
    }
}
    

UIPickerViewDataSource, UIPickerViewDelegate


使用
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
UIPickerViewDataSource:UIIPickerでデータを変更するためのプロトコルUIPickerViewDelegate:UIIPickerビュー用Delegate

numberOfComponents


使用
func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
アップルの公式文書によると、コンポーネントを定義する場所だという.コンポーネントは、私から見ればカテゴリを指すかもしれません.通常、これらのコンポーネントを指定する方法はTable Viewでも見られます.その時もカテゴリのように分かれているのが見えますが、これもそうです.
上のコードは各国通貨単位のPickerを使う必要がありますが、特定のカテゴリは必要ないので1つに設定します.

pickerView(_ pickerView:component:) -> Int


定義#テイギ#
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        // 아마도 코인 개수를 의미하는 듯 하다.
        return coinManager.currencyArray.count
    }
上記のメソッドには戻りタイプがあります.Intで割引します.
上記の方法はPickerViewで使用されるインデックスの数を定義する方法のようです.
先ほどのメソッドでカテゴリが指定されている場合、これはカテゴリ内のインデックスの個数定義です.

pickerView(_ pickerView:row:component:) -> String?


定義#テイギ#
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        // 아래 코드는 아마도, 해당 열의 화폐단위를 세팅하는 듯 하다.
        return coinManager.currencyArray[row]
    }
上記の方法は、戻りタイプも存在するが、上記とは異なるStringタイプである.
先ほどの数を返すと、各インデックスに表示される通貨単位が返されます.(ドル、KDなど)

pickerView(_ pickerView:row:component: Int)

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let selectCurrencyArray = coinManager.currencyArray[row]
        // 선택한 화폐단위의 가치를 가져오는 메서드
        coinManager.getCoinPrice(for: selectCurrencyArray)
    }
上記の方法はPickerViewから選択したときにインデックスを取得する方法です.
しかし、私たちの目的はインデックス番号を返すことではありません.その数で、インデックスに位置する通貨単位をその価値を決定できる方法getCoinPriceに渡します.

JSON Parsing


JSONパーティションは、ViewControllerではなく、他のsweetファイルで行います.
CoinManagerに入りましょう
protocol CoinManagerDelegate {
    func didFailWithError(error: Error)
    func didSelectedCoin(coin: CoinModel)
    
}

struct CoinManager {
    let baseURL = "https://rest.coinapi.io/v1/exchangerate/BTC"
    let apiKey = "YOUR_API_KEYS"
    
    let currencyArray = ["AUD", "BRL","CAD","CNY","EUR","GBP","HKD","IDR",
    			 "ILS","INR","JPY","MXN","NOK","NZD","PLN","RON",
                 	 "RUB","SEK","SGD","USD","ZAR"]
    
    var delegate: CoinManagerDelegate?
    
    func getCoinPrice(for currency: String) {
        let urlString = "\(baseURL)/\(currency)?apikey=\(apiKey)"
        performRequest(with: urlString)
    }
上のコードを見ると、さっき使っていたgetCoinPriceが見えます.先ほど述べたように、このコードは、選択した通貨単位で現在のビット通貨値を取得する方法である.
したがって、上記の予め定められたAPI URLを組み合わせて、必要な通貨単位情報を受信できるリンクを作成し、performRequestに送信する.

performRequest

func performRequest(with urlString: String) {
    if let url = URL(string: urlString) {
        // 2. URL 세션 만들기
        // URLSession메서드는 우리가 크롬상에서 보던 JSON 과 같은 형식으로 만들어주는 역할을 한다.
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: url) { (data, response, error ) in
            if error != nil {
                self.delegate?.didFailWithError(error: error!)
                return
            }
            if let safeData = data {
                // 내 입맛대로 땡겨온 데이터를
                if let coin = self.parseJSON(safeData) {
                    // ViewController에서 사용해야하니 얘한테 옮김
                    self.delegate?.didSelectedCoin(coin: coin)
                }
            }
        }
        task.resume()
    }
}
JSONパケットコアともいえるPerformRequestを見てみましょう
まず、上で作成したurlをiflet構文に移動させ、セッションを作成します.
このとき、URLSessionを使用して、クロムで見たJSONと同じ形式で作成します.
その後、私はあなたにDataTaskを提供して、セッションで作成したJSONデータをtask定数に保存します.エンクロージャ定義情報を使用して問題が発生した場合、またはその他の機能を使用したい場合の定義.
以上のコードはdata,response,error3個のハンドルで操作し、エンクロージャ内部に入ると
if error != nil {
    self.delegate?.didFailWithError(error: error!)
    return
}
最初にエラーがなければnilが返されます.ただし、エラーが発生し、エラーハンドルに一定の値が含まれている場合は、上記のコードを実行できます.
if let safeData = data {
    // 내 입맛대로 땡겨온 데이터를
    if let coin = self.parseJSON(safeData) {
    // ViewController에서 사용해야하니 얘한테 옮김
    self.delegate?.didSelectedCoin(coin: coin)
    }
}
エラーが発生していない場合に実行されるコード.まず、dataハンドルがオープンに設定される.したがってif let文でunlappingを行った後,parsingを継続する.parseJSONメソッドにデータを移動し(以下、このメソッドについて説明する)、受信したデータをViewControllerに再移動する.
task.resume()
そして最後の行は必ずこのコードを書かなければなりません.終わったら締め切りボタンを押さないように...?そう思えばいい.まだ任務がある.なぜstart()ではなく履歴書()なのかを考える人もいます.私もよくわかりませんが、中にフィルタリングエラーのコードがあっても、エラーはいつでも存在する可能性があるので、履歴書()で中に発生するエラーを防止するために、エラーが発生したら停止できるのを覚えています.△実はよくわかりませんが、知っている人がいたらメッセージを残してください.

parseJSON

// 파싱해온 정보 데이터화 시키기
// 원하는 데이터만 골라 먹기 하는 parseJSON 메서드
func parseJSON(_ coinData: Data) -> CoinModel? {
    // JSON을 디코딩할 수 있는 객체
    let decoder = JSONDecoder()
    do {
        // 디코더로 땡겨와서
        let decodedData = try decoder.decode(CoinData.self, from: coinData)
        // 여기서 원하는 정보들 변수로 저장시키고
        let lastPrice = decodedData.rate
        let name = decodedData.asset_id_quote
        // 모델 파일에 원하는것들만 추가시키고 리턴
        let coin = CoinModel(rate: lastPrice, asset_id_quote: name)
        return coin
    } catch {
        delegate?.didFailWithError(error: error)
            return nil
        }
    }
上のコードは、performRequestから割り当てられてアンインストールされたJSONデータをSWIFTで有効に使用するコードです.parseJSONの戻りタイプから見るとCoinModel?で、それはCoinModelで、JSONファイルの中で私が必要とするものを単独で収集する構造体swiftファイルです.
struct CoinData: Codable {
    let time: String
    let rate: Double
    let asset_id_quote: String
}

struct CoinModel {
    let rate: Double
    let asset_id_quote: String
}
このように2つの構造体が存在している.CoinDataは、実際のJSONファイルからデータを取得するのは初めてです(この場合、定数の名前とタイプはJSONで提供されている名前とタイプと同じでなければパーティション化できません).CoinModelの場合、持参したデータから必要なものだけを抽出しました.
そこで、JSONファイルでCoinDataと定義されているものを配布してから、私が欲しいものをCoinModelに移します.
要するにdo-catch構文を用いて,まずdo構文に用いるコードを見る.
// JSON을 디코딩할 수 있는 객체
let decoder = JSONDecoder()
do {
    // 디코더로 땡겨와서
    let decodedData = try decoder.decode(CoinData.self, from: coinData)
    // 여기서 원하는 정보들 변수로 저장시키고
    let lastPrice = decodedData.rate
    let name = decodedData.asset_id_quote
    // 모델 파일에 원하는것들만 추가시키고 리턴
    let coin = CoinModel(rate: lastPrice, asset_id_quote: name)
    return coin
} 
JSONDecoder()はJSONを復号できるオブジェクトです.
復号とは,先ほど述べたJSONファイルをswiftで利用できるようにする動作である.
次にdo文を開き、復号可能な情報をデコーダ定数に書き、decodedDataCoinDataと指定された名前に対応する情報を引き出します.
そして、私が後で持ってきた情報の中で、私が使うものだけが定数として保存され、CoinModelを初期化します.
そして、CoinModelを返却すれば、私たちが希望する各国の相場に基づいてビットコインの相場を確認することができます.

Protocol

protocol CoinManagerDelegate {
    func didFailWithError(error: Error)
    func didSelectedCoin(coin: CoinModel)
}
合意とは、約束や制約のようなものです.「このプロトコルを追加するなら、少なくともこれくらいは!そう教えてくれた感じ.必要な要素を入れるのは良い機能です.
上記のコードを例にとると,上記のコードは各国通貨単位でビットコイン相場を表示するアプリケーションを開発しているプロトコルである.その時に必要な最小の方法は、選択した通貨単位で計算された相場であり、エラーが発生した場合の行為は約2つの方法である.したがって,以上のコードではこのように指定されており,メソッドのほかに定数,変数,構造体,クラスなどが宣言できる.
また、ClassまたはExtensionでプロトコルを選択する場合、この2つのプロトコルは実装されなければならない.

extension

// exction 으로 리펙토링
extension ViewController: CoinManagerDelegate {
    // 프로토콜로 추가한 두개의 메서드를 정의
    func didFailWithError(error: Error) {
        print(error)
    }
    
    // 매개변수는 하나면 충분
    func didSelectedCoin(coin: CoinModel) {
        DispatchQueue.main.async {
            // 큐 돌리면서 앱 비동기 방식으로 하나하나~
            self.bitcoinLabel.text = String(format: "%.2f", coin.rate)
            self.currencyLabel.text = coin.asset_id_quote
        }
    }
}
extensionは,既存の機能を付与したり,上記のように単独で再構成したりすることができる.このような利点は、コードが読みやすく、既存の機能で他の機能を使用できることです.
上のコードは、さっき宣言したプロトコルを実現したコードです.didFailWithErrorを例にとると、エラーが発生した場合にアプリケーションが実行すべき操作について議論していますが、印刷()のみです.didSelectedCoinでは、JSON Parsingで受信したデータをアプリケーションラベルに転送してユーザに見せる機能を実現すべきである.
したがって、DispatchQueueを使用して、データを1つずつ受信し、過負荷を回避するためにデータを処理する.このようにラベルを更新します.
またExtensionを使用する際の注意点もあります.
var coinManager = CoinManager()
override func viewDidLoad() {
        super.viewDidLoad()
        currencyPicker.dataSource = self
        currencyPicker.delegate = self
        coinManager.delegate = self
    }
上のコードはViewControllerviewDidLoad()メソッドです.ここでは先ほど拡張と宣言したCoinManagerの依頼をselfにバインドする必要があります.このようにしてこそ、拡張されたすべてのコードが正常に動作します.
私の考えでこのコードの意味を説明すると、コードはViewControllerに接続して正常に動作する必要がありますか?最初、依頼はエージェントの役割を果たし、エージェントが依頼人なしでは何もできないようにselfを指定してこそコードが行われると思います.

プロジェクト、体験、学習


これはAPIの使い方が難しすぎて、講義を聞き直してから再開する挑戦のためです.今回の挑戦の過程で,ある程度のAPIパケットが可能になるようである.実際、~Model~Dataファイルの意味がよくわかりませんが、分封自体が難しすぎると思いますが、コードをゆっくり観察してアップルの公式ファイルを探している間にじっくり味わってみましたが、難しくないと思います.なんだ.他のAPIを使うことでしか知られていないようです.
拡張、プロトコルの基礎的な構成方法も徐々に得られるプロジェクトです.このアプリケーションから、APIがより容易なきっかけになることを願っています.