{
    "componentChunkName": "component---src-templates-blog-post-js",
    "path": "/blog/20210812/",
    "result": {"data":{"site":{"siteMetadata":{"title":"Juicy Blog 🍋"}},"markdownRemark":{"id":"42b8fd8e-ea23-5992-96d5-7924ab18d674","excerpt":"Swiftという言語に慣れていないのか、決して情報が少なくないわけでもないのですが、なかなかReactで書くようにすんなりできずにいました。\nやはりサーバーサイドをずっとやってきた身としてはスタンドアロンよりはサーバーと通信させたいです。\nJavaScriptではHTTP通信のクライアントにAxiosやFetch…","html":"<p>Swiftという言語に慣れていないのか、決して情報が少なくないわけでもないのですが、なかなかReactで書くようにすんなりできずにいました。\nやはりサーバーサイドをずっとやってきた身としてはスタンドアロンよりはサーバーと通信させたいです。\nJavaScriptではHTTP通信のクライアントにAxiosやFetchなどが使えますが、同じ感覚で使うには少々難しい。</p>\n<p>Swiftにも<a href=\"https://github.com/Alamofire/Alamofire\">Alamofire</a>というHTTP通信用のライブラリがありました。\nこのライブラリがデファクトなのかなと思いきや、いざ使ってみるとガイドで網羅されている情報だと足りなくてうまくいきませんでした。\nまた最近メジャーアップデートが行われたのか、情報も新旧混ざっていたためURLSessionを使う方がすんなり情報も見つかりました。</p>\n<p>サーバー側は単純に<code class=\"language-text\">https://example.com/articles.json</code>で以下のJSONを返すと想定します:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">[</span>\n  <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Quod recusandae sunt molestias.\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"created_at\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2020-09-01T10:39:41+00:00\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"updated_at\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2021-08-09T13:07:23+00:00\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">]</span></code></pre></div>\n<p>今回はモデル定義は割愛しますが、<code class=\"language-text\">Article.swift</code>に上記の定義を書きます。\nここでのポイントはJavaScriptと同様にサーバーは<em>snake_case</em>を返すがクライアントは<em>CamelCase</em>を用いています。\n幸いSwiftではJSONのキーをあらかじめ変換してくれます。</p>\n<div class=\"gatsby-highlight\" data-language=\"swift\"><pre class=\"language-swift\"><code class=\"language-swift\"><span class=\"token keyword\">let</span> decoder <span class=\"token operator\">=</span> <span class=\"token class-name\">JSONDecoder</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\ndecoder<span class=\"token punctuation\">.</span>keyDecodingStrategy <span class=\"token operator\">=</span> <span class=\"token punctuation\">.</span>convertFromSnakeCase</code></pre></div>\n<p>続いてSwiftUI側から先に見てみます:</p>\n<div class=\"gatsby-highlight\" data-language=\"swift\"><pre class=\"language-swift\"><code class=\"language-swift\"><span class=\"token keyword\">import</span> <span class=\"token class-name\">SwiftUI</span>\n\n<span class=\"token keyword\">struct</span> <span class=\"token class-name\">ArticleList</span><span class=\"token punctuation\">:</span> <span class=\"token class-name\">View</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token attribute atrule\">@ObservedObject</span> <span class=\"token keyword\">var</span> modelData<span class=\"token punctuation\">:</span> <span class=\"token class-name\">ModelData</span>\n\n    <span class=\"token keyword\">var</span> body<span class=\"token punctuation\">:</span> <span class=\"token keyword\">some</span> <span class=\"token class-name\">View</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">List</span><span class=\"token punctuation\">(</span>modelData<span class=\"token punctuation\">.</span>articles<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> article <span class=\"token keyword\">in</span>\n            <span class=\"token class-name\">Text</span><span class=\"token punctuation\">(</span>article<span class=\"token punctuation\">.</span>title<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">.</span>onAppear <span class=\"token punctuation\">{</span>\n            modelData<span class=\"token punctuation\">.</span><span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>ここでのポイントは<code class=\"language-text\">@ObservedObject</code>を用いるということです。\n<code class=\"language-text\">@ObservedObject</code>は内容に変更があると自動でViewに反映してくれるはず。\n今回は<code class=\"language-text\">onAppear</code>を使ってみることにします。\n他にも<code class=\"language-text\">ModelData</code>の<code class=\"language-text\">init()</code>に書く方法もありました。</p>\n<div class=\"gatsby-highlight\" data-language=\"swift\"><pre class=\"language-swift\"><code class=\"language-swift\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">ModelData</span><span class=\"token punctuation\">:</span> <span class=\"token class-name\">ObservableObject</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token attribute atrule\">@Published</span> <span class=\"token keyword\">var</span> articles<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token class-name\">Article</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token keyword\">func</span> <span class=\"token function-definition function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">let</span> url <span class=\"token operator\">=</span> <span class=\"token function\">URL</span><span class=\"token punctuation\">(</span>string<span class=\"token punctuation\">:</span> <span class=\"token string-literal\"><span class=\"token string\">\"https://example.com/articles.json\"</span></span><span class=\"token punctuation\">)</span><span class=\"token operator\">!</span>\n        <span class=\"token keyword\">let</span> decoder <span class=\"token operator\">=</span> <span class=\"token class-name\">JSONDecoder</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        decoder<span class=\"token punctuation\">.</span>keyDecodingStrategy <span class=\"token operator\">=</span> <span class=\"token punctuation\">.</span>convertFromSnakeCase\n        <span class=\"token keyword\">let</span> task <span class=\"token operator\">=</span> <span class=\"token class-name\">URLSession</span><span class=\"token punctuation\">.</span>shared<span class=\"token punctuation\">.</span><span class=\"token function\">dataTask</span><span class=\"token punctuation\">(</span>with<span class=\"token punctuation\">:</span> url<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> data<span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">,</span> error <span class=\"token keyword\">in</span>\n            <span class=\"token keyword\">do</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">let</span> json <span class=\"token operator\">=</span> <span class=\"token keyword\">try</span> decoder<span class=\"token punctuation\">.</span><span class=\"token function\">decode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token class-name\">Article</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">,</span> from<span class=\"token punctuation\">:</span> data<span class=\"token operator\">!</span><span class=\"token punctuation\">)</span>\n                <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>articles <span class=\"token operator\">=</span> json\n            <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token function\">fatalError</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"error\"</span></span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n        task<span class=\"token punctuation\">.</span><span class=\"token function\">resume</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>本来であれば<code class=\"language-text\">error</code>や、<code class=\"language-text\">response</code>の処理も必要ですが、今回はわかりやすさ重視で省略しています。\n<code class=\"language-text\">self.articles</code>の行で更新しているのですが、警告が出てしまうもののプレビュー画面では表示されるようになりました。\n今回最もハマった箇所は<code class=\"language-text\">Article</code>を配列で受け取るのに<code class=\"language-text\">[Article].self</code>という記述ができることでした。</p>\n<p>最初の一歩としてはまだまだ不十分かもしれませんが、これから徐々にPOSTやユーザーの認証、他にもiOSならではの制約等も含めて調べていくつもりです。</p>","frontmatter":{"title":"URLSessionの最も単純な使い方","date":"August 11, 2021","description":"iOSのアプリケーションがサーバーからJSONデータを取得するまで"}},"previous":{"fields":{"slug":"/blog/20210724/"},"frontmatter":{"title":"Swift UIの理解を深めよう"}},"next":{"fields":{"slug":"/blog/20210904/"},"frontmatter":{"title":"Fresh Mintについて"}}},"pageContext":{"id":"42b8fd8e-ea23-5992-96d5-7924ab18d674","previousPostId":"7a356756-e263-5628-9ef4-4ef69a89aaa9","nextPostId":"1fd5355f-145d-5e2b-933b-151c432cfa84"}},
    "staticQueryHashes": ["2785349746","2841359383"]}