[SwiftUI] 튜토리얼 3단계

chosh·2023년 2월 6일
0
post-custom-banner

필터링 구현하기

  1. State 추가
    state는 하위에 있는 View의 값을 보유하기 위해서 만들어주기 때문에 private로 선언하면 됨

    struct LandmarkList: View {
        // 즐겨찾기 한 목록에 대한 값을 가지기 위해서 State 지정
        // State는 하위에 있는 View의 값을 보유하기 위해서 선언하기 때문에
        // 항상 private로 선언함
        @State private var showFavoritesOnly = false 
    
        var body: some View {
            NavigationView {
                List(landmarks) { landmark in
                    NavigationLink {
                        LandmarkDetail(landmark: landmark)
                    } label: {
                        LandmarkRow(landmark: landmark)
                    }
                }
                .navigationTitle("Landmarks")
            }
        }
    }
  2. Canvas 새로고침
    뷰의 속성을 추가하거나 수정하면 수동으로 새로고침 해줘야 한다고 함

  3. 필터링한 데이터를 변수에 담아줌

    var filteredLandmarks: [Landmark] { // Landmark가 있는 배열타입
        landmarks.filter { landmark in // landmarks 를 filter로 돌림
            (!showFavoritesOnly || landmark.isFavorite) // showFavoritesOnly 가 false면 모두 보여줌(필터 기능을 사용할때만 필터링하기 위한 값)
        }
    }
  4. filter 기능 켜면 필터링 됨

    struct LandmarkList: View {
        @State private var showFavoritesOnly = true // 이 값이 필터를 사용할건지 말건지 선택하는 값
    
        var filteredLandmarks: [Landmark] {
            landmarks.filter { landmark in
                (!showFavoritesOnly || landmark.isFavorite)
            }
        }
    // --생략--

컨트롤 토글 추가

상태 업데이트와 관련 있는 내용 같음(리랜더링)

A binding acts as a reference to a mutable state. When a user taps the toggle from off to on, and off again, the control uses the binding to update the view’s state accordingly.

list안에 정적or동적인 데이터를 합치거나 다른 동적 그룹을 합치려면 ForEach를 사용해야 된다고함

To combine static and dynamic views in a list, or to combine two or more different groups of dynamic views, use the ForEach type instead of passing your collection of data to List.

이전코드

List(filteredLandmarks) { landmark in
	NavigationLink {
    	LandmarkDetail(landmark: landmark)
    } label: {
    	LandmarkRow(landmark: landmark)
    }
}

변경코드

List {
	ForEach(filteredLandmarks) { landmark in
		NavigationLink {
			LandmarkDetail(landmark: landmark)
		} label: {
			LandmarkRow(landmark: landmark)
		}
	}
}

합친코드

List {
	Toggle(isOn: $showFavoritesOnly) { // $사인을 이용해서 바인딩 (바인딩을 해야 변할때 ui를 업데이트함)
		Text("Favorites only")
	}

	ForEach(filteredLandmarks) { landmark in
		NavigationLink {
			LandmarkDetail(landmark: landmark)
		} label: {
			LandmarkRow(landmark: landmark)
		}
	}
}

$ 마크로 상단에 있는 값을 바인딩 시켜줌
바인딩을 해야 그 값이 변할때 UI를 업데이트

관찰 가능한 데이터 선언

  • 사용자가 값을 바꿔서 제어를 하려면 일단 관찰 가능한 객체에 값을 담아줘야 됨
  • Observable Object는 SwiftUI 환경의 저장소에서 뷰에 바인딩될 수 있는 데이터에 대한 사용자 정의 객체

Combine 프레임워크에서 ObservableObject protocol에 적합한 새로운 모델 타입을 선언

import Foundation
import Combine // Combine 을 먼저 import 

final class ModelData: ObservableObject {
}

SwiftUI는 ObservableObject 를 구독하여 데이터가 생신될 때 마다 UI를 업데이트 시켜줍니다.

ObservableObject는 변경사항을 선택 할 수 있도록 Publish(게시) 해야됨

import Foundation
import Combine

final class ModelData: ObservableObject {
	@Published var landmarks: [Landmark] = load("landmarkData.json") // @Published 를 붙여줘서 게시함
}

모델 데이터를 뷰에서 채택하기

@EnvironmentObject를 이용해서 모델 데이터를 가져옴

import SwiftUI

struct LandmarkList: View {
	@EnvironmentObject var modelData: ModelData // 이렇게 선언해서 가져옴
    @State private var showFavoritesOnly = false
profile
제가 참고하기 위해 만든 블로그라 글을 편하게 작성했습니다. 틀린거 있다면 댓글 부탁드립니다.
post-custom-banner

0개의 댓글