LoginSignup
0
2

SwiftUIで郵便番号検索APIを使う

Posted at

読んでほしい人

  • SwiftUIを勉強している人
  • 郵便番号検索APIを使ってみたい人

補足情報

こちらのサイトのAPIを使って今回はアプリを作っていこうと思います。
https://zipcloud.ibsnet.co.jp/doc/api

記事の内容

SwiftUIでAPIを使ったアプリの学習をしていて、アウトプットのために色々作ってみたいなと思い入門レベルの郵便番号検索ができるアプリを作ってみました。

今回はこんな構造のJSONに合わせて、structを定義します。

{
	"message": null,
	"results": [
		{
			"address1": "東京都",
			"address2": "三鷹市",
			"address3": "",
			"kana1": "トウキョウト",
			"kana2": "ミタカシ",
			"kana3": "",
			"prefcode": "13",
			"zipcode": "1810000"
		}
	],
	"status": 200
}

モデルを作成する。構造体をネストして、JSONがresults: [{}]ネストしている構造に合わせて、2個作成する。

struct ZipCode: Codable {
    var message: String?
    var results: [Result]
    var status: Int
}

struct Result: Codable {
    var address1: String
    var address2: String
    var address3: String
    var kana1: String
    var kana2: String
    var kana3: String
    var prefcode: String
    var zipcode: String
}

View側に今回は、ロジックも書いてます。練習用のアプリということで、メソッドをクラスに書いて分けるのまではやってないです。検索Formがあって、郵便番号-なしの7桁ではなかったら、エラーメッセージを表示する正規表現を使っております。入力してボタンを押すと、検索をするメソッドが実行されます。

struct ContentView: View {
    @State private var zipCode = ""
    @State private var results = [Result]()
    @State private var errorMessage = ""
    
    var body: some View {
        VStack {
            TextField("郵便番号を入力してください", text: $zipCode)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
            
            Button(action: {
                if validate(zipCode: zipCode) {
                    fetchResults()
                }
            }) {
                Text("Search")
            }
            
            if !errorMessage.isEmpty {
                Text(errorMessage)
                    .foregroundColor(.red)
            }
            
            List(results, id: \.zipcode) { result in
                VStack(alignment: .leading) {
                    Text("郵便番号: \(result.zipcode + result.prefcode)")
                    Text("都道府県コード: \(result.prefcode)")
                    Text("住所カナ: \(result.kana1 + result.kana2 + result.kana3)")
                    Text("住所: \(result.address1 + result.address2 + result.address3)")
                }
            }
        }
    }
    
    func validate(zipCode: String) -> Bool {
        let zipCodePattern = "^[0-9]{3}-?[0-9]{4}$"
        let zipCodePredicate = NSPredicate(format: "SELF MATCHES %@", zipCodePattern)
        let isValid = zipCodePredicate.evaluate(with: zipCode)
        if !isValid {
            errorMessage = "郵便番号は-なしで7桁で入力してください!"
        } else {
            errorMessage = ""
        }
        return isValid
    }
    
    func fetchResults() {
        guard let url = URL(string: "https://zipcloud.ibsnet.co.jp/api/search?zipcode=\(zipCode)") else {
            return
        }
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let decodedData = try JSONDecoder().decode(ZipCode.self, from: data)
                    DispatchQueue.main.async {
                        self.results = decodedData.results
                    }
                } catch {
                    print("Failed to decode JSON: \(error.localizedDescription)")
                }
            }
        }.resume()
    }
}

こちらが全体のコード

import SwiftUI

struct ZipCode: Codable {
    var message: String?
    var results: [Result]
    var status: Int
}

struct Result: Codable {
    var address1: String
    var address2: String
    var address3: String
    var kana1: String
    var kana2: String
    var kana3: String
    var prefcode: String
    var zipcode: String
}

struct ContentView: View {
    @State private var zipCode = ""
    @State private var results = [Result]()
    @State private var errorMessage = ""
    
    var body: some View {
        VStack {
            TextField("郵便番号を入力してください", text: $zipCode)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
            
            Button(action: {
                if validate(zipCode: zipCode) {
                    fetchResults()
                }
            }) {
                Text("Search")
            }
            
            if !errorMessage.isEmpty {
                Text(errorMessage)
                    .foregroundColor(.red)
            }
            
            List(results, id: \.zipcode) { result in
                VStack(alignment: .leading) {
                    Text("郵便番号: \(result.zipcode + result.prefcode)")
                    Text("都道府県コード: \(result.prefcode)")
                    Text("住所カナ: \(result.kana1 + result.kana2 + result.kana3)")
                    Text("住所: \(result.address1 + result.address2 + result.address3)")
                }
            }
        }
    }
    
    func validate(zipCode: String) -> Bool {
        let zipCodePattern = "^[0-9]{3}-?[0-9]{4}$"
        let zipCodePredicate = NSPredicate(format: "SELF MATCHES %@", zipCodePattern)
        let isValid = zipCodePredicate.evaluate(with: zipCode)
        if !isValid {
            errorMessage = "郵便番号は-なしで7桁で入力してください!"
        } else {
            errorMessage = ""
        }
        return isValid
    }
    
    func fetchResults() {
        guard let url = URL(string: "https://zipcloud.ibsnet.co.jp/api/search?zipcode=\(zipCode)") else {
            return
        }
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let decodedData = try JSONDecoder().decode(ZipCode.self, from: data)
                    DispatchQueue.main.async {
                        self.results = decodedData.results
                    }
                } catch {
                    print("Failed to decode JSON: \(error.localizedDescription)")
                }
            }
        }.resume()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

最後に

今回は、郵便番号検索アプリを作ってAPIの使い方について学習してみました。ご興味あるかたは参考にして使ってみてください。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2