UI以外の処理と例外処理の対応
Pixabay API を例にして具体的にSwiftではどのようにして Web APIと通信するかの処理を考えていきましょう。そのときに、UI以外の処理とエラーが派生した場合の例外処理の方法など、事前に注意しておくべき処理について学びます。
サンプルの作成
プロジェクトを作成し、画面にボタンを配置します。その後に、ContentView.swiftを次のように編集してください。
struct ContentView: View { // Pixabay API key let api_key = "xxxxxxxxxxxxxx" var body: some View { VStack { Button("Button") { Task { do { let urlStr = "https://pixabay.com/api/?key=\(api_key)&q=ねこ" let url = URL(string: urlStr.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!)! let (data, response) = try await URLSession.shared.data(from: url) print(response) print(data) } catch { print("エラー発生") print(error) } } } Text("Hello, world!") .padding() } } }
定数 api_key に Pixabay API の key の値を記述します。検索キーワードを「ねこ」としてねこの素材を検索します。以降、ボタンの処理、URLオブジェクトの生成、do – catch文、tryについて説明します。
await、async、タプルに関しては次の節で説明します。
ボタンの処理とURLの生成
SwiftUIはその名前の通り、UIを管理するフレームワークです。したがってUIの処理とデバッグ以外の処理を作成する場合には、UI以外の処理であることを明確にするために TaskブロックでUI以外の処理を囲みます。
サンプルでは、ボタンを押したときに Pixabay API から値を取得するというUI以外の処理を行いますので、ボタンを押した後の処理すべてを Task ブロックで囲っています。
Button("Button") { Task { // 処理 } }
URL構造体のインスタンス生成に関しては、8.1 Web APIの利用 で学んだ通りです。
let urlStr = "https://pixabay.com/api/?key=\(api_key)&q=ねこ" let url = URL(string: urlStr.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!)!
Swiftでは文字列の中に変数を埋め込むことができます。文字列を定義するときに「\( )」で変数を囲うと、アプリを実行するときに、その部分は自動的に変数の値に置き換えられます。
ここでは、Pixabay API の key を定数「api_key」で定義していますので、api_keyを文字列に埋め込んでいます。
addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) メソッドは、日本語や中国語のようなマルチバイトの全角文字をURLに用いるときに、Swiftが正常にURLを解釈できるようにするメソッドです。このメソッドもオプショナル型に対応しているので、「!」を後ろつにけてオブジェクトが確実に存在することを明記しています。
do – catch 文と try
ボタンを押した後に実行される Task ブロックでは、APIから値を取得する処理を行なっています。
Button("Button") { Task { do { let urlStr = "https://pixabay.com/api/?key=\(api_key)&q=ねこ" let url = URL(string: urlStr.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!)! let (data, response) = try await URLSession.shared.data(from: url) print(response) print(data) } catch { print("エラー発生") print(error) } } }
生成したURL構造体を引数にURLSession構造体からAPIの値を得る処理を定義しています。
そのときに、処理自体を do – catch 文で囲って、URLSession構造体のdataメソッドの前には「try」があります。
これはエラーが起きるかもしれない処理を行う場合に、エラーが起きた場合に備えるSwiftの書き方です。
APIから値を得るためには、APIとHTTPによる通信を行います。このときに何らかの原因で通信ができなくなった場合のエラーに備えて do – catch 文を利用して正常に処理が行われた場合とエラーが起きた場合の処理を定義して、エラーによってアプリが異常終了しないようにしています。
do – catch 文の書式は次のとおりです。
do { // エラーが起きるかもしれない処理 } catch { // エラーが起きた場合の処理 // エラー内容は 変数 error に格納される }
このようにしてエラーが起きた場合の対策を行うことができます。前回説明した変数のオプショナル型では、NullPointerExceptionという1つのエラー対応でした。do – catch 文では、あらゆるエラー処理に対応したものだと覚えてください。
エラーを起こさない処理を正常処理、エラーを起こした処理を例外処理と呼びます。
do – catch 文によるエラー処理は、使える処理が決まっています。
URLSession構造体のdataメソッドのドキュメントを参照すると次の書式で定義されています。
https://developer.apple.com/documentation/foundation/urlsession/3767352-data
func data(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)
メソッドの定義の部分に「throws」と記述があります。「throws」はエラーが発生する可能性のある処理を定義する書式です。「throws」の記述のあるメソッドを実行する際には、メソッドの前に「try」をつけて実行します。
そしてこの「try」をつけてメソッドを実行する場合のみ、do – catch 文によるエラー処理を行うことができます。
2段階の定義があって若干手間がかかりますが、エラーが発生するかもしれない処理に対応する処理を作成するときのために、do – catch 文と try のことを覚えておいてください。