22
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GAOGAOAdvent Calendar 2019

Day 9

SwiftWebUIでWebアプリをつくろう!

Posted at

はじめに

WWDC2019で発表され、大いに注目を集めるSwiftUIですが、そのSwiftUIでWebアプリを作れることをご存知でしょうか?

SwiftWebUIを使えばできます!
SwiftWebUIは、そのままですが、SwiftUIをWebでも使えるようにしようというプロジェクトです。

Screen Shot 2019-12-09 at 6.45.00.png

今回は簡単にTODOアプリを作っていきます。

Task App Demo.gif

参考リンク

Hello World

Xcodeを開き、New Project, macOS, Command Line Toolを選択します。
Screen Shot 2019-12-09 at 5.46.11.png

適当に名前を入力し、作成できたらSwift Package ManagerでSwiftWebUIを入れていきます。

[iOSアプリ開発にSwift Package Managerを使おう - Qiita]のリンクがわかりやすいです。

きちんと導入できれば、main.swift で下記をコピペしてBuild&Runして、http://localhost:1337にアクセスすれば、テキストの内容(Hello World)が表示されているでしょう

main.swift
import SwiftWebUI

SwiftWebUI.serve(Text("Hello World"))

続いて簡単なTODOアプリを作っていきましょう

TODOアプリ

モデルを定義します。

Task.swift

struct Task: Identifiable {
  var text: String
  var createdAt: Date
  var isFinished: Bool

  var id: String { text }
  var createdAtString: String {
    let f = DateFormatter()
    f.timeStyle = .short
    f.dateStyle = .short
    f.locale = Locale(identifier: "ja_JP")
    return f.string(from: createdAt)
  }
}

タスク一つ一つのUIを作成します。
Viewが一つのtaskを持っていて、Doneボタンを押せばisFinishedtrueになってタスクが完了し、文字色やViewのEnabledが制御されています。

TaskRow.swift

struct TaskRow: View {

  @State var task: Task

  var body: some View {
    HStack {
      Button("Done") {
        self.task.isFinished = true
      }

      VStack(alignment: .leading) {
        Text(task.name)
          .font(.headline)
          .color(task.isFinished ? .secondary : .primary)
        Text(task.createdAtString)
          .color(.secondary)
          .font(.subheadline)
      }
    }
    .padding()
    .disabled(task.isFinished)
  }
}

上記のUIは↓のようになります。

Screen Shot 2019-12-09 at 6.10.03.png

モデルとUIができればモックが作れるので、main.swiftを書き換えていきましょう。


import Foundation
import SwiftWebUI

struct MainView: View {

  @State private var tasks: [Task] = [
    Task(name: "Sample Task", createdAt: Date(), isFinished: false),
    Task(name: "Sample Task", createdAt: Date(), isFinished: false),
    Task(name: "Sample Task", createdAt: Date(), isFinished: false)
  ]

  var body: some View {
    Form {
      Section(header: Text("Task App").font(.title)) {
        List(tasks.identified(by: \.id)) { TaskRow(task: $0) }
      }
    }
  }
}

SwiftWebUI.serve(MainView())

この状態でBuild&Runすればタスクが画面の真ん中に表示されているかと思います。

Screen Shot 2019-12-09 at 6.13.09.png

あとはタスクを追加できるようにすれば完了です。

TaskInputViewを作成し、textをTextFieldで変更していき、追加ボタンを押したらactionを呼ぶようにします。

TaskInputView.swift
import SwiftWebUI

struct TaskInputView: View {

  @State private var text: String = ""

  let action: (String) -> Void

  var body: some View {
    HStack {
      TextField($text)
      Spacer()
      Button("追加", action: {
        self.action(self.text)
        self.text = ""
      })
        .disabled(text.isEmpty)
    }
  }
}

一方で、main.swiftではTaskInputViewのactionでString型受け取るので、tasksの配列に追加していくようにしておきます。

main.swift
  var body: some View {
    Form {
      Section(header: Text("Task App").font(.title)) {
        TaskInputView(action: { text in
          let task = Task(text: text, createdAt: Date(), isFinished: false)
          self.tasks.append(task)
        })
        Spacer(minLength: 12)
        Text("Task List")
          .font(.title)
          .bold()
        List(tasks.identified(by: \.id)) { TaskRow(task: $0) }
      }
    }
  }

下記のようなアプリが出来上がります。

Task App Demo.gif

既知のバグとして

  • TextField内のtextの変更を受け取れていない
  • Task Listを空配列で定義するとタスクを追加できない

が残っておりいろいろ雑ですが、現状のSwiftWebUIの仕様など、詳しくみれていないので時間があれば調査したいと思います。

完成形のプロジェクトをGitHubに上げておきます。
GitHub - mtfum/SwiftWebUISample

懸念点

  • NavigationViewが利用できない
  • Buttonの色が変更されない
  • タスクの空配列に追加してもListに反映されない
    • TypeError: Cannot read property 'parentNode' of Nullのエラーが表示される

など、実際に触ってみるとバグも多く、利用していくにはまだまだ先になりそうです。
また、ブラウザ上でSwiftを動かすためにはSwift Wasmの対応も待たなければなりません。

最後に

SwiftWebUIはプロダクション用ではなくSwiftUIを学ぶのに適していると注意書きされています。

Disclaimer: This is a toy project! Do not use for production. Use it to learn more about SwiftUI and its inner workings.

しかし、SwiftでWebアプリがつくれる日が近づいている証でもあり、まだまだ先は長そうですが今からとても楽しみです。

SwiftUIを触ってみるには良い環境かもしれないので、興味のある人は触ってみてください。
ということでSwiftWebUIの紹介を示させてもらえればと思います。
最後までお読みいただきありがとうございました。

22
17
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
22
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?