🌇
WebフロントエンドエンジニアがSwiftUIに入門した話
いつもはNuxtやNextを使って開発していますが、Web以外の技術も触ってみたいなってということで、SwiftUIとFirebaseを使って、Todoアプリを作ってみました。
GitHub: https://github.com/AFURO-1130/swift-todo-app
環境
- Swift 5.6.1
- cocoapods 1.12.0
- xcode 13.4.1
xcodeのインストールとプロジェクトの作成
ここは他の人の記事がたくさんあるので、そちらを参照してください。
Hello Worldまでできたら完璧です。
Firebaseとの連携
Firebaseとの連携の流れは、4つ手順があります。
-
Firebaseコンソールから
GoogleService-info.plist
を取得
2.
3.ContentView.swift
と同じ階層にファイルを読み込ませてください
4. もし、ダイアログが出てきたら、下記の画像のようにチェックしてください
5. -
FirebaseのSDKインストール
- 自分はcocoapodsを使っているので、cocoapodsのインストール
-
pod init
をして、Podfile
を作成
Podfilepod 'FirebaseUI' pod 'Firebase' // 上記の二行を追加
-
エントリーファイルに初期化コードを書く
プロジェクト名App.swiftimport SwiftUI //追加 import Firebase //追加 // ここから class AppDelegate: NSObject, UIApplicationDelegate{ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() return true } } // ここまで追加 @main struct tutorials_iOSApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate // 追加 var body: some Scene { WindowGroup { ContentView() } } }
-
使いたいところでモジュールをインポートする
contentView.swiftimport Firebase // Firestoreを呼び出す時 FireStore.firestore()
あとは下記をコピペしたら、とりあえず動くものは完成します!
contentView.swift
//
// ContentView.swift
// Shared
//
// Created by 金城翔太郎 on 2023/04/16.
//
import SwiftUI
import Firebase
// todoの型を作成
struct Todo: Identifiable {
let id: String
let title: String
var isEditing: Bool
}
struct TodoListView: View{
var todo: Todo
var body: some View{
Text(todo.title)
}
}
struct ContentView: View {
@State var todos:[Todo] = [
];
@State private var inputTitle = ""
@State private var newTitle = ""
var body: some View {
VStack{
Spacer().frame(height: 100)
TextField("todoのタイトルを入力してください。", text: $inputTitle).textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
// 入力してもらったものを表示する
Button("タスクを追加する"){
if inputTitle.isEmpty{
return
}
else{
addTodos(title: inputTitle)
getTodoTasks()
}
}
List(todos){
todo in
HStack(){
if todo.isEditing {
TextField("タイトル", text: $newTitle)
} else{
Text(todo.title)
}
Spacer()
if todo.isEditing {
Button(action:{
if newTitle.isEmpty {
print("空ですよ")
} else {
updateTodo(task: todo, newTitle: newTitle)
}
}) {
Text("保存")
}
Spacer()
} else {
Button(action:{
// 編集を押したら走る関数
updateItem(id: todo.id)
}) {
Text("編集")
}
Button(action: {
// Firestoreからデータを削除する関数を呼び出す
deleteTodo(task: todo)
}, label: {
Text("削除").foregroundColor(.red)
}).buttonStyle(PlainButtonStyle())
}
}
}
}
.onAppear(){
getTodoTasks()
}
}
func updateItem(id: String){
if let index = todos.firstIndex(where: { $0.id == id }) {
todos[index].isEditing.toggle()
}
}
func updateTodo(task:Todo, newTitle:String){
let db = Firestore.firestore();
db.collection("todos").document(task.id).updateData([
"title": newTitle,
]) {
err in
if let err = err {
print("更新に失敗しました: \(err)")
} else {
print("更新に成功しました")
getTodoTasks()
}
}
}
func deleteTodo(task: Todo){
let db = Firestore.firestore();
db.collection("todos").document(task.id).delete() {
err in if let err = err{
print("削除に失敗しました \(err)")
}
else{
print("削除に成功しました。")
self.todos = self.todos.filter { $0.id != task.id }
}
}
}
func addTodos(title: String){
let db = Firestore.firestore()
db.collection("todos").addDocument(data: ["title": title, "isDone": false])
{ err in
if let err = err {
print("タスクの追加に失敗しました: \(err)")
} else {
print("タスクの追加に成功しました")
}
}
inputTitle = ""
}
func getTodoTasks(){
let db = Firestore.firestore();
db.collection("todos").getDocuments { snapshot, error in
if let error = error {
print(error.localizedDescription)
return
}
guard let documents = snapshot?.documents else {
return
}
todos = documents.map { document in
let data = document.data()
let id = document.documentID
let title = data["title"] as? String ?? ""
return Todo(id: id, title: title, isEditing: false)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
}
}
}
}
webはこういう時に使い方だが、swiftだったらこう書く
- 非同期処理
2.async/await
やクロージャー
を使って、非同期処理を実装する。 - 画面がマウントされたときのイベント
4..onAppear()
を使って、UIコンポーネントがマウントされた時に、処理ができます。 - TSとかの
type
やinterface
6.struct
を使って、型を書いていきます。
参考資料
- https://www.motokis-brain.com/article/164
- https://zenn.dev/kueharx/articles/ebd14c46f02211
- https://tech.amefure.com/swift-github-upload
- https://qiita.com/miyae/items/6988c1b61b76b4938ae6
- https://tech.amefure.com/swift-firebase
- https://qiita.com/townsoft/items/fa33189a5c6e775eb11d
- https://cocoapods.org/
- https://firebase.google.com/docs/ios/setup?hl=ja
Discussion