iOS/App

Scrumdinger 분석하기 02-1. /scrum/ScrumsView.swift

태애니 2025. 4. 15. 23:07
728x90

Big Idea (큰 주제)

- 코드분석

Essential Question (핵심 질문)

- Scrumdinger 에서 해당 코드를 쓴 이유에 대해 나는 잘 이해하고 있을까?

Challenge (도전 과제)

- 하나의 뷰에서 내가 모르는 코드에 대해 분석해보자

 

 



Activities (학습 활동)

 

이번에 할 파일은 ScrumsView 이다.

 

import SwiftUI
import SwiftData

struct ScrumsView: View {
    @Query(sort: \DailyScrum.title) private var scrums: [DailyScrum]
    @State private var isPresentingNewScrumView = false
    
    var body: some View {
        NavigationStack {
            List(scrums) { scrum in
                NavigationLink(destination: DetailView(scrum: scrum)) {
                    CardView(scrum: scrum)
                }
                .listRowBackground(scrum.theme.mainColor)
            }
            .navigationTitle("Daily Scrums")
            .toolbar {
                Button(action: {
                    isPresentingNewScrumView = true
                }) {
                    Image(systemName: "plus")
                }
                .accessibilityLabel("New Scrum")
            }
            .sheet(isPresented: $isPresentingNewScrumView) {
                NewScrumSheet()
            }
        }
    }
}

#Preview {
    ScrumsView()
}

 

 

 

@Query(sort: \DailyScrum.title) private var scrums: [DailyScrum] 

 

https://developer.apple.com/kr/xcode/swiftdata/

 

SwiftData - Xcode - Apple Developer

SwiftData를 사용하면 선언적 코드를 사용하여 데이터를 쉽게 유지할 수 있습니다. 일반 Swift 코드를 사용하여 데이터를 쿼리 및 필터링할 수 있으며, SwiftUI와 매끄럽게 통합할 수 있습니다.

developer.apple.com

 

 

@Query 는 SwiftData를 가져올 수 있다. 

설명을 보면, SwiftData와 SwiftUI가 연동되어 기본 데이터 변경 시 뷰에 라이브 업데이트를 제공하므로 결과를 수동으로 새로고침할 필요가 없다. 라고 나와있다.

 

 

 

SwiftData

Core Data 의 Persistent 기술과 Swift의 concurrency 기능을 결합하고, 외부 종속성이 없어 최소한의 코드 구현이 가능하다.

기본 모델 데이터를 저장, 여러 기기 간 데이터 동기화 처리도 가능하다. 또한, 캐싱 매커니즘이나 제한적인 오프라인 기능을 제공할 수 있다.

 

이때 사용하는 매크로들이 바로

 

@Model, @Attribute, @Relationship 이다.

이들을 모델 속성으로 사용하여 커스터마이징 할 수 있다.

 

 

그리고 ModelContext 클래스를 사용하여 model instance 를 C,U,D 한다.

 

이 뷰 모델을 표시할 때 사용하는 매크로가 바로 @Query 이며, 이를 이용해 조건 또는 Fetch Descriptor 를 지정하면 된다.

 

ModelContext SwiftUI 에서 접근하고, modelContainer ModelContext modifiers 이용해 특정 컨텍스트나 컨테이너를 지정할 수도 있다.

 

 

더보기

여기서 질문1, Scrumdinger 앱에서 DailyScrum 모델에는 왜 Attribute 를 붙이지 않고 사용한거지??

 

답변을 하자면, 

 

SwiftData에서는 기본적으로 id는 자동으로 인식됨. (이야.. 좋은 세상이다 역시)

  • SwiftData는 UUID 타입의 id를 자동으로 고유 식별자(primary key)로 인식합니다.
  • 이때 @Attribute를 생략해도 내부적으로는 속성으로 처리되기 때문에 문제가 발생하지 않습니다.

 

단, Core Data 키워드와 이름이 겹치는 속성 의 이름은 에러가 나니 주의 해야한다.

나도 한번 먹어봤던 경고.. ⚠️

 

Fatal error: Unable to have an Attribute named description

 

 @Attribute(originalName:)

뭐 이런식으로 회피가 가능하다고는 하는데

 

그냥 쓰지 말자 (ex: description, hash)

 

 

 

.listRowBackground(scrum.theme.mainColor)

List 의 Row 에서만 쓰는 특수한 listRow.... modifier 들

  1. listRowBackground(_:)
    각 row의 배경을 설정. Color나 View(예: RoundedRectangle)도 지정 가능.
    예: .listRowBackground(Color.yellow)
  2. listRowSeparator(_:)
    해당 row의 separator(구분선)를 보이거나 숨길 수 있음.
    값으로 .visible 또는 .hidden 사용 가능.
    예: .listRowSeparator(.hidden)
  3. listRowSeparatorTint(_:)
    row separator의 색상을 설정할 수 있음.
    예: .listRowSeparatorTint(.red)
  4. listRowInsets(_:)
    row의 내부 여백(padding)을 직접 지정할 수 있음.
    EdgeInsets를 사용해서 top, leading, bottom, trailing 여백을 조정할 수 있음.
    예: .listRowInsets(EdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20))
  5. listRowPlatter(_:)
    visionOS에서 사용하는 modifier. 일반 iOS에서는 거의 쓰지 않음.

 

이거 말고도 NavigationLink 에 적용되는 것들 중에 아래와 같은 modifier도 있다.

이건 이정도 있구나로 알아두면 될 듯.

isDetailLink(_:) : iPad에서 Split View로 push할지 여부를 결정

tint(_:) : NavigationLink 내부의 라벨 색상을 커스터마이즈 (iOS 15+)

 

 

 

https://developer.apple.com/documentation/swiftui/navigationstack

 

NavigationStack | Apple Developer Documentation

A view that displays a root view and enables you to present additional views over the root view.

developer.apple.com

 

 

 

 

 

.sheet

func sheet<Content>(
    isPresented: Binding<Bool>,
    onDismiss: (() -> Void)? = nil,
    @ViewBuilder content: @escaping () -> Content
) -> some View where Content : View

 

https://developer.apple.com/documentation/swiftui/view/sheet(item:ondismiss:content:)

 

sheet(item:onDismiss:content:) | Apple Developer Documentation

Presents a sheet using the given item as a data source for the sheet’s content.

developer.apple.com

 

 

 

 

Solution (해결 결과)

- 안그래도 오늘 작업하면서 NavigationStack 을 쓰는데, 이것저것 한번 넣어봐야겠다. 라는 생각이 들었다.

- SwiftData 에 대해 더 자세히 알고 싶어졌다.

- 특히 List 에 CardView 라는 View 를 만들었는데 이상하게 중간쯤부터 이상하게 밑줄이 그어지는 문제가 있었다. 이부분 한번 파봐야겠다.🤔

 

 

Reflection (회고)

오늘 배운 것:

SwiftData, NavigationStack 맛보기

 

 

 

오늘은 너무 피곤해서 여기까지ㅠㅠ 뒤에 코드 분석 내용들은 좀 더 빌드업해서 추가로 정리하겠음!!

 

 

다음에 공부해보고 싶은 :

 

 

1. 남은 코드 분석

2. 같은 러너인 미니가 알려준 public, private 외에 추가적인 접근제어 open, internal, fileprivate, private(set)과 관련된 키워드

3. SwiftData 더 알아보기

4. NavigationStack 더 알아보기

 

 

728x90