itisjustK
코딩과 사람 사는 이야기
itisjustK
전체 방문자
오늘
어제
  • 분류 전체보기 (207)
    • 일이삼사오육칠팔구십일이삼사오육칠팔구십일이삼사오육칠.. (0)
    • Web (43)
      • html & css (9)
      • django & python (15)
      • java script (9)
    • iOS (51)
      • Swift (42)
      • SwiftUI (5)
    • CS (25)
      • 자료구조 (6)
      • 운영체제 (3)
      • 데이터베이스 (9)
      • 네트워크 (7)
    • PS (34)
      • 알고리즘 & 자료구조 (0)
    • Life (36)
    • Retrospective (15)
    • Book (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 어플
  • binding
  • AppleDevloperAcademy
  • 점주
  • 개발자
  • 세그멘테이션
  • nosql
  • ios
  • CoreData
  • crud
  • SwiftUI
  • CS
  • 생활코딩
  • 연결리스트
  • 킨디
  • 생활코딩 #이고잉 #HTML #코딩 #개발자
  • mongodb
  • 독립서점
  • POSTECH
  • SWIFT

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
itisjustK

코딩과 사람 사는 이야기

[SwiftUI] iOS App Dev Tutorial에서 Data Update  파트 간단 정리
iOS/SwiftUI

[SwiftUI] iOS App Dev Tutorial에서 Data Update 파트 간단 정리

2022. 5. 11. 22:22

그동안 내가 궁금해했던 CRUD중 data를 Update하는 파트를 정리해보자! 

 

우선 흐름을 먼저 잡아보자

  1. DetailEditView 생성
  2. 기존 data 불러와서 DetailEditView에도 띄우기
  3. 데이터 수정
  4. 수정된 데이터 저장
  5. 기존 View에 갱신된 데이터로 띄우기 (사실 4까지 잘 되면 5는 자동으로 됨. 그냥 저장된 데이터를 불러오는 코드이므로)

 

각 흐름에 대한 key를 정리해보자

  1. 쓰이는 코드들 : [ TextField, 이미 만들어놓은 PickerView, Slider의 value값, 새로운 멤버 append ]
  2. DetailView에서 @State로 선언된 data -> DetailEditView에서 @Binding wrapper로 받는다 (& 데이터 타입 선언)
  3. $(바인딩)으로 각각 value 지칭해준다 (불러온 값이 곧 수정 값이고, 수정하는 값이 곧 불러온 값)
  4. 변경된 거 저장하자! -> data 파일에서 mutating func update() 이용

 

자자 이제 이를 코드로 구체적으로 적용해보자고 


1. DetailEditView & 2. 기존 data 불러와서 DetailEditView에도 띄우기 & 3. 데이터 수정

코드를 보자 

주석으로 설명 달아놨데이

//DetailEditView.swift

import SwiftUI

//변경된 값은 Data property에 저장
//이때 @State wrapper 사용. 왜냐하면, 변경된 값 인식해서 View를 바로 그릴 것.
struct DetailEditView: View {
    
    @Binding var data : DailyScrum.Data
    //@Binding wrapper를 사용했다 = DetailView에서 던져준 data를 받았다
    //여기서는 data: DailyScrum.Data 이렇게 데이터 타입만 선언
    
    @State private var newAttendeeName: String = ""
    
    var body: some View {
        Form {
            Section(header:Text("meeting info")){
                TextField("Title", text: $data.title)
                //여기에 있는 값(text)이 data의 title임($data.title)
                //그리고 TextField이므로 사용자가 직접 입력하여 변경함
                
                HStack{
                    Slider(value: $data.lengthInMinutes, in: 5...30, step: 1) {
                    //여기에 있는 값(value)이 data의 lengthInMinutes임($data.lengthInMinutes)
                    //그리고 Slider이므로 사용자가 직접 움직이며 변경함
                        
                        Text("Length")
                    }
                    Spacer()
                    Text("\(Int(data.lengthInMinutes)) Minutes")
                }
                ThemePicker(selection: $data.theme)
            }
            Section(header: Text("Attendees")){
                ForEach(data.attendees) { attendee in
                    Text(attendee.name)
                }
                
                //Delete하는 코드
                .onDelete{ indicies in
                    data.attendees.remove(atOffsets: indicies)
                }
                
                HStack{
                    TextField("New Attendee", text:$newAttendeeName)    //여기 있는 값(text)을 newattendeeName이라고 할거고
                    Button(action: {
                        withAnimation { //Button을 클릭하면 animation과 함께 밑에 있는 코드를 수행할 거다
                                        //밑에 있는 코드가 뭐냐면 data의 attendees에 newAttendeeName을 추가하는 거
                            
                            let newAttendee = DailyScrum.Attendee(name: newAttendeeName)
                            data.attendees.append(newAttendee)
                            newAttendeeName = ""    //넣어주고 나면 값을 초기화시켜줘서 나중에도 쓸 수 있게 한다(컵 또 쓰게 씻는 느낌. 설거지!)
                        }
                    }) {
                        Image(systemName: "plus.circle.fill")
                    }
                    .disabled(newAttendeeName.isEmpty)  //빈값이면 버튼 비활성화
                }
            }
        }
        
    }
}

 

4. 수정된 데이터 저장

코드를 바로 보자. 그 전에 여기서 기억해야할 것이 있다. 

toolbar !

DetailView에서 DetailEditView로 넘어가는 것은 Sheet으로 구현했다. 그렇기 때문에 Edit View 상단 양쪽에 위치한 Cancel, Done 버튼은 toolbar로 적용하는 건데, 이 toolbar의 위치가 DetailView에서 설정한다. (Sheet에 관한 설정을 DetailView에서 하는 것처럼)

 

//DetailView.swift

import SwiftUI

struct DetailView: View {
    @Binding var scrum: DailyScrum
    
    @State private var data = DailyScrum.Data()
    @State private var isPresentingEditView = false
    
    var body: some View {

        List {
            Section(header: Text("Meeting Info")){
                NavigationLink(destination: MeetingView()) {
                    Label("Starting Meeting", systemImage: "timer")
                        .font(.headline)
                        .foregroundColor(.accentColor)
                }
                
                HStack {
                    Label("Length", systemImage: "clock")
                    Spacer()
                    Text("\(scrum.lengthInMinutes) Minutes")
                }
                .accessibilityElement(children: .combine)
                
                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")
                }
            }
        }
        .navigationTitle(scrum.title)
        .toolbar {
            Button("Edit") {
                isPresentingEditView = true
                data = scrum.data //Edit 버튼 누르면 scrum.data를 data에 담아준다
            }
        }
        .sheet(isPresented: $isPresentingEditView){
            NavigationView{
                DetailEditView(data: $data)
                    //navigationTitle 위치!
                    .navigationTitle(scrum.title)
                    .toolbar{    //이게 DetailEditView 상단에 위치할 toolbar
                        
                        //placement가 .cancellationAction! 아주 직관적인 위치 명시
                        ToolbarItem(placement:.cancellationAction){
                            Button("Cancel"){
                                isPresentingEditView = false
                            }
                        }
                        
                        //placement가 .confirmationAction! 아주 직관적인 위치 명시
                        ToolbarItem(placement: .confirmationAction){
                            Button("Done"){
                                isPresentingEditView = false
                                
                                //이게 바로 update하라는 명령. 이는 함수를 의미하는 것이고
                                //DailyScrum.swift 파일에 담겨있다
                                scrum.update(from: data)
                            }
                        }
                    }
            }
        }
    }
}

 

func update 잡으러 가자

//DailyScrum.swift

import Foundation

struct DailyScrum: Identifiable {
    let id: UUID //인스턴스 하나씩 다루기 위해
    var title: String
    var attendees: [Attendee] //String으로 이루어진 List라는 의미를 '[String]'으로 표기
    var lengthInMinutes: Int
    var theme: Theme //Theme.swift에서 선언해준 enum 타입
    
    //이거 custom initializer임
    //매개변수 이니셜라이저
    init(id: UUID = UUID(), title: String, attendees: [String], lengthInMinutes: Int, theme: Theme){
        self.id = id
        self.title = title
        self.attendees = attendees.map{Attendee(name:$0)}
        self.lengthInMinutes = lengthInMinutes
        self.theme = theme
    }
    
}

extension DailyScrum {
    
    struct Attendee: Identifiable {
        let id: UUID
        var name: String
        
        init(id: UUID = UUID(), name: String) {
            self.id = id
            self.name = name
        }
    }
    
    //이런 식으로 default값 지정해주면, 나중에 Data()라고 선언하면서 바로 쓸 수 있음
    struct Data {
        var title: String = ""
        var attendees: [Attendee] = []
        var lengthInMinutes: Double = 5
        var theme: Theme = .seafoam
    }
    
    var data: Data {
        //밑에 코드 무슨 말이지 ..
        Data(title: title, attendees: attendees, lengthInMinutes: Double(lengthInMinutes), theme: theme)
    }
    
    //이게 바로 update하는 함수다
    mutating func update(from data: Data) { //from : 매개변수, data : 전달인자, Data : 전달인자 타입
        title = data.title  //전달인자의 title 프로퍼티를 DailyScrum의 title에 할당
        attendees = data.attendees  //전달인자의 attendees 프로퍼티를 DailyScrum의 attendees에 할당
        lengthInMinutes = Int(data.lengthInMinutes) //전달인자의 lengthInMinutes 프로퍼티를 DailyScrum의 lengthInMinutes에 할당
        theme = data.theme  //전달인자의 theme 프로퍼티를 DailyScrum의 theme에 할당
        
        //새로운 값들을 본체에 할당!
    }
}


//provide sample data
extension DailyScrum {
    static let sampleData: [DailyScrum] =
    [
        DailyScrum(title: "Design", attendees: ["Cathy", "Daisy", "Simon", "Jonathan"], lengthInMinutes: 10, theme: .yellow),
        DailyScrum(title: "App Dev", attendees: ["Katie", "Gray", "Euna", "Luis", "Darla"], lengthInMinutes: 5, theme: .orange),
        DailyScrum(title: "Web Dev", attendees: ["Chella", "Chris", "Christina", "Eden", "Karla", "Lindsey", "Aga", "Chad", "Jenn", "Sarah"], lengthInMinutes: 5, theme: .poppy)
    ]
}

 

 

오케이 특별히 이거 중요한 거니까 func update 부분만 따로 빼주겠음

    //이게 바로 update하는 함수다
    mutating func update(from data: Data) { //from : 매개변수, data : 전달인자, Data : 전달인자 타입
        title = data.title  //전달인자의 title 프로퍼티를 DailyScrum의 title에 할당
        attendees = data.attendees  //전달인자의 attendees 프로퍼티를 DailyScrum의 attendees에 할당
        lengthInMinutes = Int(data.lengthInMinutes) //전달인자의 lengthInMinutes 프로퍼티를 DailyScrum의 lengthInMinutes에 할당
        theme = data.theme  //전달인자의 theme 프로퍼티를 DailyScrum의 theme에 할당
        
        //새로운 값들을 본체에 할당!
    }

 

그리고 이거를 toolbar의 Done을 눌렀을 때 action으로 이 함수를 실행시키면 update된다! 

//DetailView.swift

                ToolbarItem(placement: .confirmationAction){
                Button("Done"){
                isPresentingEditView = false
                scrum.update(from: data)
              		}
            	}

 

끝

저작자표시 (새창열림)

'iOS > SwiftUI' 카테고리의 다른 글

[SwiftUI] Core Data를 이용한 데이터 CRUD (iCalories)  (0) 2022.05.17
[SwiftUI] Making Classes Observable  (0) 2022.05.11
[SwiftUI] Managing Data Flow Between Views  (0) 2022.05.10
[SwiftUI] Design Pattern : MVVM  (0) 2022.04.27
    'iOS/SwiftUI' 카테고리의 다른 글
    • [SwiftUI] Core Data를 이용한 데이터 CRUD (iCalories)
    • [SwiftUI] Making Classes Observable
    • [SwiftUI] Managing Data Flow Between Views
    • [SwiftUI] Design Pattern : MVVM
    itisjustK
    itisjustK

    티스토리툴바