SwiftUIを使ったハンズオン用に記事を作成しました
使用するAPI
今回はQiitaAPiを題材とします。(ドキュメント)
登録不要で使えて、例えば、 https://qiita.com//api/v2/items で、投稿を取得できます。
[{
rendered_body: "...",
coediting: false,
comments_count: 0,
created_at: "2017-11-09T22:50:51+09:00",
group: null,
id: "fe412a67b64e793d138b",
likes_count: 0,
private: false,
reactions_count: 0,
tags: [{
name: "processing",
versions: []
},
{
name: "openFrameworks",
versions: []
}
],
title: "【openFrameworks 初心者冒険記5】逃げまくってた...三角関数の扉を再ノック。sin() cos() サインコサイン....。メディアアートで避けては通れない?最初の壁",
updated_at: "2017-11-09T22:50:51+09:00",
url: "http://qiita.com/39_isao/items/fe412a67b64e793d138b",
user: {
description: "鮭とメロンパンが好物な奥田民生になりたいボーイです。 最近はてなブログ始めました http://sudara-bluse.hatenablog.com/",
facebook_id: "",
followees_count: 52,
followers_count: 44,
github_login_name: null,
id: "39_isao",
items_count: 103,
linkedin_id: "",
location: "",
name: "",
organization: "",
permanent_id: 76843,
profile_image_url: "https://qiita-image-store.s3.amazonaws.com/0/76843/profile-images/1508030106",
twitter_screen_name: "sudara_bluse",
website_url: "http://sudara-bluse.hatenablog.com/"
}
},
{,,,}
]
今回は、以下のデータを使ってiOSアプリを作ってみます。
- 投稿タイトル
- ユーザアイコン
- URL
完成したアプリ
プロジェクトを作成する
使うライブラリをインストールする
file -> swift package から使用するライブラリを追加します
https://github.com/dmytro-anokhin/url-image.git
通信周りのクラスを作成する
JSONを変換するための構造体を作成
import Foundation
struct Item: Decodable, Identifiable {
let id: String
let title: String
let body: String?
let url: String
let user: User
}
struct User: Decodable {
let profileImageUrl: String
}
APIからデータを取得するクラスを実装
SwiftUIの画面から参照するためObservableObject
を継承し、画面に表示する値を @Published
にする
import Foundation
class ApiFetcher: ObservableObject {
@Published var items = [Item]()
private let baseURL = "https://qiita.com/api/v2"
func fetchItems(query: String) {
let url = URL(string: "\(baseURL)/items?query=\(query)&page=1&per_page=50")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let data = data {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let items = try decoder.decode([Item].self, from: data)
DispatchQueue.main.async {
self.items = items
}
}
} catch {
// ignore
}
}.resume()
}
}
一覧画面を作る
一覧のセルを作成する
新しく ItemRow.swift というファイルを作成します
import SwiftUI
import URLImage
struct ItemRow: View {
let item: Item
var body: some View {
HStack {
URLImage(URL(string: item.user.profileImageUrl)!) { proxy in
proxy.image
.resizable()
.aspectRatio(contentMode: .fill)
.clipped()
}.frame(width: 60.0, height: 60.0)
Text(item.title)
}
}
}
struct ItemRow_Previews: PreviewProvider {
static var previews: some View {
ItemRow(item: Item(
id: "d040cf8b2d15bd7e507d",
title: "[Angular] Angular アプリの構成をみる",
body: "Angular に関する自身の勉強の復習がてらの備忘録記事。",
url: "https://qiita.com/ksh-fthr/items/d040cf8b2d15bd7e507d",
user: User(
profileImageUrl: "https://qiita-user-profile-images.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F193342%2Fprofile-images%2F1500888159?ixlib=rb-1.2.2&auto=compress%2Cformat&lossless=0&w=300&s=9a22e880d804d67db66a33ac2e7671b5"
)
))
}
}
一覧画面を作成する
新しく ItemRow.swift というファイルを作成します
import SwiftUI
struct ItemList: View {
@ObservedObject var fetcher = ApiFetcher()
@State var keyword: String = ""
var body: some View {
NavigationView {
VStack {
TextField("Search", text: $keyword) {
self.fetcher.fetchItems(query: self.keyword)
}.padding(16)
List(fetcher.items) { item in
ItemRow(item: item)
}
}
.navigationBarTitle(Text("投稿一覧"))
}
}
}
struct ItemList_Previews: PreviewProvider {
static var previews: some View {
ItemList()
}
}
ここまで作成するとプレビューが以下のように表示されます
起動画面を一覧画面にする
もともと作成されている ContentView を修正して一覧画面を表示するようにします
struct ContentView: View {
var body: some View {
ItemList()
}
}
起動する
ここまで作ったら一度起動して入力した文字で検索できることを確認してみましょう
詳細画面を作る
詳細画面は一覧でタップした投稿をWebViewで表示します
新しくItemDetail.swiftを作成します
import SwiftUI
import WebKit
struct ItemDetail: View {
let title: String
let url: String
var body: some View {
WebView(url: URL(string: url)!)
.navigationBarTitle(Text(title), displayMode: .inline)
}
}
struct WebView : UIViewRepresentable {
var url: URL
func makeUIView(context: Context) -> WKWebView {
return WKWebView(frame: .zero)
}
func updateUIView(_ uiView: WKWebView, context: Context) {
let req = URLRequest(url: url)
uiView.load(req)
}
}
struct ItemDetail_Previews: PreviewProvider {
static var previews: some View {
ItemDetail(title: "テスト", url: "https://www.apple.com")
}
}
一覧から詳細画面に遷移できるようにする
ItemList.swift の List を以下のように修正して画面遷移できるようにします
List(fetcher.items) { item in
ItemRow(item: item)
}
List(fetcher.items) { item in
NavigationLink(
destination: ItemDetail(
title: item.title,
url: item.url
)
) {
ItemRow(item: item)
}
}
実行してみましょう
最後に
完成はこちらにあります。
https://github.com/decoch/swiftui_example_qiita_client
おつかれさまでした。