import SwiftUI
import SwiftData
struct DetailView: View {
let scrum: DailyScrum // swiftData
@State private var isPresentingEditView = false //add a Boolean @State property named isPresentingEditView.
@State private var errorWrapper: ErrorWrapper? // error
var body: some View {
List {
Section(header: Text("Meeting Info")) {
// 3depth
NavigationLink(destination: MeetingView(scrum: scrum, errorWrapper: $errorWrapper)) { //errorWrapper 추가
Label("Start Meeting", systemImage: "timer")
.font(.headline)
.foregroundColor(.accentColor)
}
HStack {
Label("Length", systemImage: "clock")
Spacer()
Text("\(scrum.lengthInMinutes) minutes")
}
.accessibilityElement(children: .combine)
/**
VoiceOver 사용 시 설정
.accessibilityElement
.accessibilityLabel("내 맘대로 정의") // 사용자가 정의한 라벨 적용
SwiftUI에서 접근성(VoiceOver 등)이 특정 UI 요소를 어떻게 인식할지 정의
.ignore : 접근성 요소로 인식하지 않음
.combine : 하나의 요소로 읽음
.contain : 개별로 읽음
*/
HStack {
Label("Theme", systemImage: "paintpalette")
Spacer()
Text(scrum.theme.name)
.padding(4)
.foregroundColor(scrum.theme.accentColor)
.background(scrum.theme.mainColor)
.cornerRadius(4)
}
.accessibilityElement(children: .combine)
}
// 참석자
Section(header: Text("Attendees")) {
ForEach(scrum.attendees) { attendee in
Label(attendee.name, systemImage: "person")
}
}
// history
Section(header: Text("회의내역")) {
if scrum.history.isEmpty {
Label("회의 내역이 없습니다.", systemImage: "calendar.badge.exclamationmark")
.foregroundColor(.gray)
}
ForEach(scrum.history) { history in
NavigationLink(destination: HistoryView(history: history)) {
HStack {
Image(systemName: "calendar")
Text(history.date, style: .date)
}
}
}
}
}
.navigationTitle(scrum.title)
.toolbar {
Button("수정") {
isPresentingEditView = true
}
}
.sheet(isPresented: $isPresentingEditView) {
NavigationStack{
DetailEditView(scrum: scrum)
.navigationTitle(scrum.title)
}
}
.sheet(item: $errorWrapper, onDismiss: nil) { wrapper in //error
ErrorView(errorWrapper: wrapper)
}
}
}
#Preview {
NavigationStack {
DetailView(scrum: DailyScrum.sampleData[0])
}
}
let scrum: DailyScrum // 읽기전용
List 는 스크롤이 가능한 목록을 자동으로 만들어주는 컴포넌트로, 테이블 뷰의 형태를 하고 있다.
List 에는 선택할 수 있는게 자동 기능이 있다. 와우
@State private var multiSelection = Set<UUID>()
var body: some View {
NavigationView {
List(oceans, selection: $multiSelection) {
Text($0.name)
}
.navigationTitle("Oceans")
.toolbar { EditButton() }
}
Text("\(multiSelection.count) selections")
}
리스트 땡겼다가 놨을 때 새로고침하는 인스턴스 메소드도 추가 가능하다.
https://developer.apple.com/documentation/swiftui/view/refreshable(action:)
refreshable(action:) | Apple Developer Documentation
Marks this view as refreshable.
developer.apple.com
refreshable(action:)
https://developer.apple.com/documentation/swiftui/displaying-data-in-lists
Displaying data in lists | Apple Developer Documentation
Visualize collections of data with platform-appropriate appearance.
developer.apple.com
Supporting multidimensional lists
List | Apple Developer Documentation
A container that presents rows of data arranged in a single column, optionally providing the ability to select one or more members.
developer.apple.com
여기서 또 하나 찾게 된 키워드는 ScrollViewReader
https://developer.apple.com/documentation/swiftui/scrollviewreader
ScrollViewReader | Apple Developer Documentation
A view that provides programmatic scrolling, by working with a proxy to scroll to known child views.
developer.apple.com
ScrollViewProxy를 사용해서 특정 ID를 가진 뷰로 이동할 수 있다.
[사용자 액션]
↓
[View의 이벤트 발생 (버튼 클릭 등)]
↓
[dismiss 호출] [context 사용: insert/save 등]
↓ ↓
[현재 View를 스택/시트에서 제거] [메모리에 추가/변경 기록]
↓
[context.save() 호출]
↓
[SwiftData 저장소에 반영 (디스크 기록)]
dismiss 호출 시
- 메모리 안에서 뷰 인스턴스 자체가 사라짐.
- View 관련 State들도 해제됨 (@State, @Binding, @Environment 모두 메모리에서 정리)
- 저장할 데이터가 있다면, View 닫기 전에 따로 저장
사용자가 TextField 입력 or Slider 조정
↓
@State 변수들(title, attendees, theme 등)이 변함
↓
사용자가 "Done" 버튼 클릭
↓
saveEdits() 호출
↓
scrum.title 등 모델 프로퍼티 업데이트
↓
context.insert(scrum) or 기존 데이터 수정
↓
(아직 메모리 안에서만 반영된 상태)
↓
try context.save() 호출
↓
SwiftData 엔진이:
- 메모리 안 context 변경사항을
- 디스크에 영구 저장 (sqlite 기반 데이터베이스 등)
↓
저장이 성공하면 완료
(에러 나면 ErrorWrapper로 잡음)
'iOS > App' 카테고리의 다른 글
Scrumdinger 분석하기 02-2. /scrum/ScrumsView.swift (0) | 2025.04.17 |
---|---|
Scrumdinger 분석하기 02-1. /scrum/ScrumsView.swift (0) | 2025.04.15 |
Scrumdinger 분석하기 01. /scrum/CardView.swift (0) | 2025.04.14 |
Scrumdinger 개발 10 : Recording audio (0) | 2025.04.10 |
Scrumdinger 개발 09 : Drawing the timer view (0) | 2025.04.09 |