jsonデータの取得

import Foundation 
import CryptoSwift 

struct JsonSample : Codable {
    var high : Double
    var open : Double
    var bid : Double
    var currencyPairCode : String
    var ask : Double
    var low: Double 
} 

let listUrl = "https://www.gaitameonline.com/rateaj/getrate"

let url = URL(string: listUrl)

URLSession.shared.dataTask(with: url) { (data, response, error) in
    if error != nil {
        print(error!.localizedDescription)
    }

    guard let data = data else { return }

    let json = try? JSONDecoder().decode([JsonSample].self, from: data)
    
}.resume()
print(json.bid)

エラーになる。何故だ。。。
/tmp/EA9CF30B-2A75-422F-B05F-493561545E26.sMmRoI/main.swift:19:34: error: value of optional type ‘URL?’ not unwrapped; did you mean to use ‘!’ or ‘?’?
URLSession.shared.dataTask(with: url) { (data, response, error) in
^
!
/tmp/EA9CF30B-2A75-422F-B05F-493561545E26.sMmRoI/main.swift:29:7: error: use of unresolved identifier ‘json’
print(json.bid)

なんかうまくいかない。

let url:URL = URL(string: "")!
let task = URLSession.shared.dataTask(with: url){ data, response, error in
	if let error = error{
		print(error.localizedDescription)
		return
	}
	if let response = response as? HTTPURLResponse {
		print("response.statusCode = \(response.statusCode)")
	}
}
task.resume()

json

jasonを表示する

@IBAction func getJson(_ sender: Any) {
        let jsonString: String = "{\"id\":1, \"name\":\"Suzuki\"}"
        // JSON文字列をData型に変換
        var personalData: Data =  jsonString.data(using: String.Encoding.utf8)!
        
        do {
            // パースする
            let items = try JSONSerialization.jsonObject(with: personalData) as! Dictionary<String, Any>
            let cast = items["name"] as! String // メンバid Intにキャスト
            self.viewCenter.text = "\(cast)"
        } catch {
            print(error)
        }
        
    }

x-code:jsonデータを使ってドル円計算する

まず、foundatationをimportします。

import UIKit
import Foundation

続いて、jsonを用意します。

let jsonString:String = "{\"dollaryen\":109, \"euroen\":110}"
    var code:Int = 0

prepareでjsonを取得して計算します。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let identifier = segue.identifier else {
            return
        }
        let personalData: Data = self.jsonString.data(using: String.Encoding.utf8)!
        do {
            let items = try JSONSerialization.jsonObject(with: personalData) as! Dictionary<String,Any>
            self.code = items["dollaryen"] as! Int
        } catch {
            self.code = 1
        }
        
        
        if identifier == "showResult" {
            let CalcVC = segue.destination as! CalcViewController
            CalcVC.mySales = Int(Double(self.sales.text!)! / Double(self.code))
            CalcVC.myProfit = Int(Double(self.profit.text!)! / Double(self.code))
            CalcVC.myPrice = Int(self.price.text!)!
            CalcVC.myEPS = Double(self.eps.text!)!
        }
    }

あれ、エラーが出まくってる。。。
2018-06-03 18:42:56.527314+0900 account[17768:334563] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /Users/mac/Library/Developer/CoreSimulator/Devices/EA305F63-7A92-4933-9E03-89D80DFE7553/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2018-06-03 18:42:56.539423+0900 account[17768:334563] [MC] Reading from private effective user settings.
2018-06-03 18:42:58.597654+0900 account[17768:334563] [Common] _BSMachError: port 8c03; (os/kern) invalid capability (0x14) “Unable to insert COPY_SEND”
2018-06-03 18:43:12.349999+0900 account[17768:338350] XPC connection interrupted

buildはsucceedするが、うまくいかないです。

swiftのjson読み込み

Foundationに含まれているJSONSerializationを使う

JSON文字列をパースするには、JSONSerialization.jsonObjectを使用する。

JSONSerializationJ .jsonObject(with JSONデータ: Data, options オプション)

import Foundation 
import CryptoSwift 

let jsonString: String = "{\"id\":3932, \"company\":\"Akatsuki\"}"

var personalData: Data = jsonString.data(using: String.Encoding.utf8)!

do {
    let items = try JSONSerialization.jsonObject(with: personalData) as! Dictionary<String,Any>
    print(items["id"] as! Int)
    print(items["company"] as! String)
} catch {
    print(error)
}

3932
Akatsuki

書き方を変える。

let jsonString: String = "{\"id\":3932, \"company\":\"Akatsuki\"}"

var personalData: Data = jsonString.data(using: String.Encoding.utf8)!
let items = try JSONSerialization.jsonObject(with: personalData) as! Dictionary<String,Any>
var code:Int = items["id"] as! Int
print(code)

3932

ではXcodeに当てはめましょう。
そもそも、import Foundationって、xcodeに使えるのか?

swift foundation
https://github.com/apple/swift-corelibs-foundation
The Foundation framework defines a base layer of functionality that is required for almost all applications. It provides primitive classes and introduces several paradigms that define functionality not provided by either the Objective-C runtime and language or Swift standard library and language.

よくわかりませんが、やってみましょう。

Info.plistとは

Info.plist
—————-
アプリで共通的な設定をInfo.plistという設定ファイルで行う。
Info.plistのファイル名は、「<プロジェクト名>Info.plist」という名前になっている。

http通信で、App Transport Security Settingsの下にAllow Arbitrary Loadsを追加する。

swift: intを浮動小数点数で割る時

CalcVC.mySales = Int(self.sales.text!)! / 109
            CalcVC.myProfit = Int(self.profit.text!)! / 109.53
            CalcVC.myPrice = Int(self.price.text!)!
            CalcVC.myEPS = Double(self.eps.text!)!

Int(self.profit.text!)! / 109.53 とすると、エラーになるが、Int(self.profit.text!)! / 109に変えるとエラーが消える。為替の世界だと、109.00と109.53は全く違うので、Int(self.profit.text!)の方の型を変えないといけない。

あれ、さらにエラーが出た

Replace 'Double(self.sales.text!)! / 109.53' with 'Int(Double(self.sales.text!)! / 109.53)'

なるほど。受け取り側の型に合わせるのね。賢すぎ。

intでcastします。

if identifier == "showResult" {
            let CalcVC = segue.destination as! CalcViewController
            CalcVC.mySales = Int(Double(self.sales.text!)! / 109.53)
            CalcVC.myProfit = Int(Double(self.profit.text!)! / 109.53)
            CalcVC.myPrice = Int(self.price.text!)!
            CalcVC.myEPS = Double(self.eps.text!)!
        }

なるほど

109.53で割った数がintで表示されます。

ドル円の値をjsonで取得したい。(いよいよ趣旨に少しづつ近づいて来ました。)

swiftのDouble(浮動小数型)

swiftでDouble(浮動小数型)を使う。sales, profit, stockpriceはint, epsはdoubleで定義する。

    var mySales:Int = 0
    var myProfit:Int = 0
    var myPrice:Int = 0
    var myEPS:Double = 0.0

outletでconnectする。

@IBOutlet weak var salesLabel: UILabel!
    @IBOutlet weak var profitLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!
    @IBOutlet weak var epsLabel: UILabel!

ResultViewController.swift
遷移先のViewControllerに値をセットする。

if identifier == "showResult" {
            let CalcVC = segue.destination as! CalcViewController
            CalcVC.mySales = Int(self.sales.text!)!
            CalcVC.myProfit = Int(self.profit.text!)!
            CalcVC.myPrice = Int(self.price.text!)!
            CalcVC.myEPS = Double(self.eps.text!)!
        }

CalcViewController.swift
データを受け取り、textで表示する。

override func viewDidLoad() {
        super.viewDidLoad()
        self.salesLabel.text = "\(self.mySales)"
        self.profitLabel.text = "\(self.myProfit)"
        self.priceLabel.text = "\(self.myPrice)"
        self.epsLabel.text = "\(self.myEPS)"

        // Do any additional setup after loading the view.
    }

さあ、compileしてみましょう。

textfieldに入力した値がcalcViewController.swiftに渡っています。

売り上げ(sales)と経常利益(profit)はドルで表示したい。
円からドル円(109.529025)で割ってみましょう。

shouldPerformSeguedでalertをだす

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
        if identifier == "showResult" {
            guard self.sales.text != "" else{
                let alertController = UIAlertController(title: "Error", message: "Please enter your name", preferredStyle: .alert)
                let defaultAction = UIAlertAction(title:"OK", style: .default, handler: nil)
                alertController.addAction(defaultAction)
                self.present(alertController, animated: true, completion: nil)
                return false
            }
            return true
        }
        return true
    }

初期

text fieldがnilの時

textfieldの値をviewControllerに送る

オプショナル型とは変数にnilの代入を許容するデータ型で、反対に非オプショナル型はnilを代入できません。オプショナル型の変数にはデータ型の最後に「?」か「!」をつける。

textFieldの値をvarで宣言し、飛び先のview controllerでも変数を初期化する。segue.destionationで飛び先のviewcontrollerを取り、変数にsetする。

resultViewController.swift

@IBOutlet weak var sales: UITextField!

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let CalcVC = segue.destination as! CalcViewController
        CalcVC.mySales = Int(self.sales.text!)!
    }

segueの値がshowResultの時のみ、変数に値を渡す。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let identifier = segue.identifier else {
            return
        }
        if identifier == "showResult" {
            let CalcVC = segue.destination as! CalcViewController
            CalcVC.mySales = Int(self.sales.text!)!
        }
    }