Deep_Dev
article thumbnail
Published 2024. 4. 22. 20:00
[SwiftUI] SwiftData ๐ŸŽ iOS/SwiftUI

 

 

โœ… SwiftData 

 

 

Why is SwiftData ?

- SwiftData๋Š” ์™œ ๋งŒ๋“ค์–ด์กŒ์„๊นŒ์š” ?

CoreData์™€ Realm์˜ ์žฅ์ ์„ ํ•ฉ์นœ๋“ฏํ•œ ๋Š๋‚Œ

 

 

What is SwiftData ? 

๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ๋ฐ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ํ”„๋ ˆ์ž„์›Œํฌ 

์ฆ‰, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ทธ ์ž์ฒด๋Š” ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ.

 

์™ธ๋ถ€ ํŒŒ์ผ ํ˜•์‹ ์—†์ด ์ „์ ์œผ๋กœ ์ฝ”๋“œ์— ์ง‘์ค‘ํ•˜๊ณ 

Swift์˜ ์ƒˆ๋กœ์šด ๋งคํฌ๋กœ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ• ํ•œ API ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š”

 

  • ๊ตฌ์„ฑ์š”์†Œ
    • @
    • .

โœ… @Model

ํด๋ž˜์Šค๋ฅผ persistent ๋ชจ๋ธ์ด๋ผ๋Š” ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์—ญํ• .

ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์—”ํ‹ฐํ‹ฐ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๊ฒŒ๋˜๊ณ , ๋˜ persistent ๋ชจ๋ธ์ด๋ผ๋Š” ํƒ€์ž…์œผ๋กœ

์•ฑํ•œํ…Œ ์ด์ œ ์ด๊ฑด ์Šคํ‚ค๋งˆ์•ผ ๋ผ๊ณ  ์•Œ๋ ค์ฃผ๊ฒŒ ๋œ๋‹ค.

  • PersistentModel : AnyObject, Obersvable, Hashable, Identifiable

SwiftData๊ฐ€ class๋ฅผ ๋ชจ๋ธ๋กœ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ

 

โ–ถ๏ธ Observable

๊ธฐ์กด์— iOS13๋ถ€ํ„ฐ ์‚ฌ์šฉํ•ด์˜ค๋˜ ObservableObejct์™€ ๋น„๊ตํ•œ๋‹ค๋ฉด,

 

< Model์€ Observable๊นŒ์ง€ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ข…์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด > 

@Model 
class Todo {
	var title: String
    var isDone: Bool
    
    init(title: String, isDone: Bool){
    	self.title = title
        self.isDone = isDone
    }
}

 

 

 

โœ… @Query

  • Fetch / Sync
  • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒ ๋‹ค๋Š” ๊ฒƒ
  • ์ฆ‰, Model ๊ฐ์ฒด๋ฅผ Fetchํ•˜๊ณ  ๋™๊ธฐํ™”์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” PropertyWrapper

 

 

โœ… Bindable

  • SwiftData๋ฅผ ํ†ตํ•ด์„œ ์•ฑ์„ ๋งŒ๋“ค๋•Œ, Updateํ•˜๋Š” ๊ธฐ๋Šฅ์— ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๊ธฐ์กด์— State์™€ Binding์ด๋ผ๋Š” ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‘๊ฐ€์ง€ ๋ทฐ์— ํ”„๋กœํผํ‹ฐ๋ฅผ ์—ฐ๊ฒฐํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, Bindable์€ Model๊ณผ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ Bindable Propperty๋กœ ์„ ์–ธํ•œ ๊ทธ ํ”„๋กœํผํ‹ฐ์˜ ๋ณ€ํ™”๋Š” ๋‹ค ๊ฐ์ง€๊ฐ€ ๋˜๊ณ , ๋ณ€ํ™”๋œ ๋ฐ์ดํ„ฐ๋“ค์€ ๋ชจ๋ธ๊นŒ์ง€๋„ ์ „๋‹ฌ์ด ๋œ๋‹ค.

 

 

<View Modifier>

  • Model Container : Model Context์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ Model Container์— ๋‹ด๊ฒŒ๋œ๋‹ค. 
  • ModelContenxt : Model์„ ๋””์Šคํฌ์— CRUDํ•˜๋Š” ๊ฐ์ฒด..

 

โœ… ModelContainer

 

 

โœ… ModelContext 

๋น„์œ ํ•˜๋ฉด ์ผ์ข…์˜ ํƒ๋ฐฐ์ƒ์ž

 

์„ ์–ธ 

@Environment(\.modelContext) var context

 

์‚ฌ์šฉ

.context.insert(todo)

.context.delete(todo)

try context.save()

 

 

 

 

โœ… 1. ModelDefinition ( ๋ชจ๋ธ ์ •์˜ ) 

  1. Model
    1. Attribute : @Attribute(.) var title: String : ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ, ์œ ๋‹ˆํฌํ•˜๊ฒŒ ๋‹ค๋ฃฐ๊ฑด์ง€, ์•”ํ˜ธํ™”ํ•ด์„œ ์ €์žฅํ• ๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ์ €์žฅํ• ๊ฑด์ง€ ๋“ฑ๋“ฑ ..
    2. Realtionship : ๋‹ค๋ฅธ ๋ชจ๋ธ ๊ฐ์ฒด์™€ ์—ฐ๊ด€์ด ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ์ธ ๊ฑฐ๋ฅผ ๋ช…์‹œํ•˜๋Š” ๋งคํฌ๋กœ. ๊ทธ๋ž˜์„œ ์˜๊ฐ๋œ ๋ชจ๋ธ ๊ฐ์ฒด๊ฐ€ ์‚ฌ๋ผ์งˆ ๋Œ€ ๊ฐ™์ด ์‚ญ์ œํ•  ๊ฑด์ง€ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ . ๊ฐ™์ด ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜ ๋“ฑ๋“ฑ .. 
    3. Transient : ๋ชจ๋ธ ํƒ€์ž…์œผ๋กœ ์ €์žฅ์„ ํ•˜์ง€ ๋ง๋ผ๊ณ  ์•Œ๋ฆฌ๋Š” ๊ฒƒ. ๊ทธ๋ž˜์„œ ์ž์žฅ์ด ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— default value ๋ฐ˜๋“œ์‹œ ํ•„์š” 

 

โœ… 2. ModelStorage ( ๋ชจ๋ธ ์ €์žฅ )

class ModelContainer 

3๊ฐ€์ง€ ์—ญํ•  

  1. ์ปจํ…Œ์ด๋„ˆ ๋งŒ๋“ค๊ธฐ : PersistentModel.Type
  2. ์ปจํ…Œ์ด๋„ˆ ๊ตฌ์„ฑํ•˜๊ธฐ : ModelConfiguration
    1. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ”Œ๋žœ ๋“ฑ๋ก
    2. ๊ฐ Scene ๋˜๋Š” View์— ๋งž๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์žฌ๊ตฌ์„ฑ
  3. ํ™˜๊ฒฝ ์„ค์ •ํ•˜๊ธฐ : ModelContext Environment

โœ… 3. ModelFetch ( ๋ชจ๋ธ ์กฐํšŒ )

Query : Model ๊ฐ์ฒด๋ฅผ Fetchํ•˜๊ณ  ๋™๊ธฐํ™” ์ƒํƒœ๋กœ์œ ์ง€ํ•˜๋Š” Property Wrapper ( Fetch / Sync )

  • Predicate : ๊ฒ€์ƒ‰ ๋˜๋Š” ํ•„ํ„ฐ๋ง์„ ์œ„ํ•œ ๋…ผ๋ฆฌ ์กฐ๊ฑด

  • FetchDescriptor : Fetch ํ•  ๋•Œ ๊ธฐ์ค€, ์ •๋ ฌ ์ˆœ์„œ ๋ฐ ์ถ”๊ฐ€ ๊ตฌ์„ฑ์„ ์„ค๋ช…ํ•˜๋Š” ์œ ํ˜•

 

 

How to Use ? 

 

Step 1 . ๋ชจ๋ธ ์ •์˜ํ•˜๊ธฐ

import Foundation
import SwiftData

@Model
final class Todo {
	var title: String
    var isDone: Bool
    var isImportant: Bool
    let timestamp: Date
    
    init(title: String, isDone: Bool = false, isImportant: Bool = false) {
    	self.title = title
        self.isDone = isDone
        self.isImportant = isImportant
        self.timestamp = .now
    }
}

 

 

Step2. Model Container ๋“ฑ๋กํ•˜๊ธฐ

@main
struct SwiftDataTutorialApp: App {
	var body: some Scene {
    	WindowGroup {
        	TodoListView()
            	.modelContainer(for: Todo.self)
                .modelContainer(for: [Todo.self, Tag.self]) // ๋ฐฐ์—ด ํ˜•ํƒœ๋„ ๊ฐ€๋Šฅ
        }
    }
}

 

 

Step 3. Model Context ์„ค์ • & ์‚ฌ์šฉ

import SwiftUI

struct TodoCreateView: View {
	@Environment (\.modelContext) var context
}

 

Button("Create") {
	context.insert(todo)
}

Button("Delete") {
	context.delete(todo) 
	try context.save()
}

 

 

Step4. ๋ฐ์ดํ„ฐ Queryํ•˜๊ธฐ 

@Query private var todos: [Todo] // ์„ ์–ธ

@Query(
	filter: #Predicate { $0.isDone == false },
    sort: \.title,
    order: .reverse
)
private var todos: [Todo]

 

 

Step5. @Bindable ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉํ•˜๊ธฐ 

Update์— ์ฃผ๋กœ ์‚ฌ์šฉ

- dismiss๋ฐ–์— ์—†์ง€๋งŒ Bindable๋กœ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น Bindable ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๋™์ด ์žˆ์„ ๋•Œ ๋ชจ๋ธ๊นŒ์ง€ ๋‹ค ์ „๋‹ฌ์ด ๋œ๋‹ค.

struct TodoUpdateView: View {
	@Environment (\.dismiss) var dismiss
	@Bindable var todo: Todo
    
    var body: some View {
    	List {
        	TextField("Name", text: $todo.title)
            Toggle("Important?", $todo.isImportant)
            Button("Update){
            	dismiss()
            }
            .navigationTitle("Update To-Do")
        }
    }
}

 

 

 

 

 

 

๐Ÿ“Œ ์ฐธ๊ณ  ) ์˜ค๋ฅ˜๋Š” ์—†๋‚˜์š” ?

 

 

 

 

 

์ฐธ๊ณ )

https://velog.io/@soc06212/SwiftUI-%EB%A7%88%EC%9D%8C%EC%9C%BC%EB%A1%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-SwiftData#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%88%98%EC%A0%95

 

SwiftUI - ๋งˆ์Œ์œผ๋กœ ์ดํ•ดํ•˜๋Š” SwiftData

SwiftData๋ฅผ ๋จธ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๋งˆ์Œ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ

velog.io

 

https://youtu.be/3r_5F9Env7Q?si=IcHDKAer8qbBzaY5

 

'๐ŸŽ iOS > SwiftUI' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[SwiftUI] Custom Alert View  (0) 2024.06.16
[SwiftUI] View -> Flip ๊ธฐ๋Šฅ  (1) 2024.06.16
[SwiftUI] TextEditor BackgroundColor ์ ์šฉ  (0) 2024.04.22
[SwiftUI] NavigationStack  (0) 2024.04.04
[SwiftUI] Property Wrapper โ‘ก  (3) 2024.03.27