Предикат SwiftUI FetchRequest с данными из ObservedObject вызывает запуск инициализаторов свойств до того, как self станет доступным

Я использую модель CoreData, в которой групповой объект имеет GroupMembers (firstName: String), связанный с членами сущности. GroupMembers имеют соответствующую группу свойств, которая обратно подключается к объекту группы. В моем Detailview я передаю групповой объект. В FetchRequest я хочу отфильтровать всех членов группы, которые имеют ту же группу, что и моя переданная группа.

Я использую следующий код:

struct GroupDetailView: View {
    @ObservedObject var group: Group
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \GroupMember.firstName_, ascending: true)],
        predicate: NSPredicate(format: "group == %@", group),
        animation: .default)
    private var members: FetchedResults<GroupMember>
    
    var body: some View {

    }
}

Но я получаю следующую ошибку:

Cannot use instance member 'group' within property initializer; property initializers run before 'self' is available

это происходит потому, что вы используете group перед его инициализацией, поэтому вы используете пустой Group объект в своем FetchRequest

grandsirr 26.10.2022 17:43

У вас есть идеи, как я могу это исправить?

hfs23 26.10.2022 18:03

Вам действительно нужна группа как ObservedObject в этом представлении? Возможно, это может быть решено простым редизайном, например, написанием пользовательской инициализации, которая принимает группу в качестве аргумента и использует эту группу для создания предиката и назначения его запросу на выборку.

Joakim Danielson 27.10.2022 14:19

Или наоборот, вам вообще нужен запрос на выборку? Разве вы не можете получить все объекты GroupMember, используя атрибут отношения для Group -> GroupMember?

Joakim Danielson 27.10.2022 14:22

Я вижу, что на этот вопрос теперь есть принятый ответ, но теперь я убежден, что правильным решением является то, что я упомянул в своем предыдущем комментарии, пропустить запрос на выборку и вместо этого получить объекты из объекта Group.

Joakim Danielson 27.10.2022 21:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот один из способов:

struct GroupDetailView: View {

    private var fetchRequest: FetchRequest<GroupMember>
    private var members: FetchedResults<GroupMember> {
        fetchRequest.wrappedValue
    }
    
    init(group: Group) {
        fetchRequest = FetchRequest(sortDescriptors: [SortDescriptor(\.firstName)], predicate: group.membersPredicate)
    }

    var body: some View {

    }
}

Возможно, вы не видели, что запрос и результаты разделены таким образом, источником этой идеи является комментарий в заголовочном файле для @SectionedFetchRequest.

Вам также необходимо добавить lazy var в расширение класса Group, чтобы привязать к объекту NSPredicate, чтобы его можно было повторно использовать, если это представление снова инициализируется. В редакторе моделей для Group выберите только расширение класса. Затем в меню «Редактор» выберите «Создать подкласс NSManagedObject», выберите папку, в которой находятся быстрые файлы, и выберите цель приложения. Это делает оба файла, поэтому удалите расширение класса и сохраните класс. Возможно, вам придется очистить сборку несколько раз, чтобы она перестала использовать автоматически сгенерированный файл класса. Затем отредактируйте его следующим образом:

import Foundation
import CoreData

@objc(Group)
public class Group: NSManagedObject {

    lazy var membersPredicate = {
        NSPredicate(format: "group = %@", self)
    }()
}

Другие вопросы по теме