😫 이번 삽질을 통해.. 대충 넘겨짚고 넘어가는 건 언젠가 큰 화를 불러온다는 것을 알았다..
다음에는 삽질을 덜 하기 위해 개념을 좀 정리해본다.
FetchRequest는 프로퍼티 래퍼로 내부는 @ObservedObject
로 되어 있다.
지금 개발하고 있는 투두앱은 Core Data를 활용한다. FetchRequest는 SwiftUI에서 Core Data Persistence의 데이터를 받아오기 위해 사용한다.
투두앱에서 임의의 날짜를 선택하면 그 날짜의 투두 리스트 데이터를 받아와 화면을 새로 그려야 한다.
나는 @FetchRequest가 @ObservedObject로 구현되어 있는지 모르고 새로운 데이터를 받기 위해 FetchRequest를 한번 더 쓰려고 한 것이다.....
부족한 공부가 부른 삽질이었다.
이미 Swift는 @FetchRequest 프로퍼티의 스토리지를 감시하고 있으므로 새로운 검색 결과를 명시적으로 받아올 필요는 없었다.
@ObservedObject란 무엇인가?
@ObservedObject 프로퍼티 래퍼를 사용하기 위해서는, ObservableObject 프로토콜을 따르는 객체가 필요하다.
@ObservedObject 프로퍼티 래퍼를 사용한 프로퍼티가 변경되면, 그 프로퍼티가 포함된 뷰는 자동으로 업데이트(새로그리기)가 된다.
아......어쩐지 @FetchRequest 프로퍼티 래퍼가 쓰인데다가 또 @State를 쓰려고 했는데 안되더라니 참 바보같은 시도였다 ㅠㅠ
@FetchRequest(
sortDescriptors: [
SortDescriptor(\.name, order: .reverse)
]
) var users: FetchedResults<User>
//길게 선언되어 있는 프로퍼티를 보고
//@State var users...라고 수정해보려고 했었다
생각해보니 프로퍼티 래퍼가 무엇인지에 대한 개념이 바로 안 잡혀 있는 것 같다.
프로퍼티 래퍼란 @ 기호가 따라 붙는 코드 재사용을 위한 키워드이다.
FetchRequest 정의 부분을 보면 다음과 같다.
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper @MainActor public struct FetchRequest<Result> where Result : NSFetchRequestResult {
/// The fetched results of the fetch request.
///
/// SwiftUI returns the value associated with this property
/// when you use ``FetchRequest`` as a property wrapper, and then access
/// the wrapped property by name. For example, consider the following
/// `quakes` property declaration that fetches a `Quake` type that the
/// <doc://com.apple.documentation/documentation/CoreData/loading_and_displaying_a_large_data_feed>
/// sample code project defines:
///
/// @FetchRequest(fetchRequest: request)
/// private var quakes: FetchedResults<Quake>
///
/// You access the request's `wrappedValue`, which contains a
/// ``FetchedResults`` instance, by referring to the `quakes` property
/// by name:
///
/// Text("Found \(quakes.count) earthquakes")
💬 @FetchRequest 정의에 대해 궁금하신 분은 Xcode에서 SwiftUI를 import하고 @FetchRequest 프로퍼티를 작성한 다음에 커맨드 선택하여 정의 부분을 참고하시길 바란다.
✅ 프로퍼티래퍼의 속 알맹이는 struct였다.
이 struct 안에 프로퍼티니 메소드니 구현되어 있는 것이다.
그래서 프로퍼티 래퍼로 감싼 프로퍼티는 그 프로퍼티 래퍼에 정의된 프로퍼티나 메소드를 쓸 수 있는 것이다.
실제로 FetchRequest 프로퍼티 래퍼를 쓸 때 사용되는 init 메소드는 다음과 같이 정의되어 있었다. 익숙한 모양새다.
@MainActor public init(entity: NSEntityDescription,
sortDescriptors: [NSSortDescriptor],
predicate: NSPredicate? = nil, animation: Animation? = nil)
커스텀으로 프로퍼티 래퍼 또한 정의할 수 있다고 한다. struct 정의 부분에 @PropertyWrapper라고 정의하고, wrappedValue라는 이름의 계산 프로퍼티를 정의해 이것의 getter와 setter를 정의한다.
그래서 언뜻 보면 class와 기능이 비슷한 것 같기도?
FetchRequest는 ObservedObject로 구현되었다 했다. 그럼 또 여기서 궁금한 것, ObservedObject와 State는 어떻게 다른 것인가?
정말 좋은 글 감사합니다!