Помогите с CoreData сделать NSPredicate - Рекурсивный поиск - PullRequest
2 голосов
/ 03 августа 2010

Я использую CoreData для проекта iPhone, и я застреваю, пытаясь создать предикат.

Моя основная сущность данных -

Folder 
   parent  - Point to the folder class parent, can be null and is one to one.
   secure  - An enum that holds the security type.

Проблема, с которой я столкнулся, заключается в том, что я пытаюсь сделать так, чтобы не показывать папки, находящиеся в защищенной папке.

Прямо сейчас мой предикат выглядит примерно так:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"secure = $@ AND (parent = %@ OR parent.secure = %@)",[NSNumber numberWithInteger:kNoSecurity], [NSNull null], [NSNumber numberWithInteger:kNoSecurity]];

Это работает, когда у меня есть только цепочка типа folder1 -> folder2 и folder1 безопасна.Но если у меня есть папка 1 -> папка 2 -> папка 3 (папка 2 и папка 3 не защищены).Folder3 возвращается, потому что я проверяю только один уровень.Есть ли способ получить предикат для проверки всей цепочки?

Спасибо.

Ответы [ 3 ]

3 голосов
/ 04 августа 2010

Проблема в том, что это только идет вверх один уровень. Так что если у меня есть folder1 -> папка2 -> папка3 -> папка4 и Папка1 безопасна. Тогда folder2 не покажи но folder3 и folder4.

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

В этом случае у вас есть объект Folder, который имеет отношение к себе, называемое parent, и атрибут secure. Поэтому ключевой путь может описывать не более двух этих свойств с путем parent.secure. Вы не можете создать ключевой путь parent.parent.secure, потому что в графе сущностей таких отношений фактически не существует. Такой путь существует только иногда в графе живых объектов. Было бы логически невозможно жестко закодировать путь, который может существовать или не существовать в зависимости от особенностей данных в любой момент времени.

Этот тип ситуации очень полезен для возможности создания настраиваемых подклассов NSManagedObject. Ваши Folder объекты не обязательно должны быть просто тупыми данными, вы можете добавить к ним поведение, чтобы каждый объект мог обращаться к своему собственному состоянию и возвращать различные данные по мере необходимости.

В этом случае я бы рекомендовал добавить временное логическое свойство с именем что-то вроде hasSecureAncestor. Затем создайте собственный метод получения, например:

- (BOOL) hasSecureAncestor{
    BOOL hasSecureAncestor=NO;
    if (self.parent.secure==kNoSecurity) {
        hasSecureAncestor=YES;
    }else {
        if (self.parent.parent!=nil) {
            hasSecureAncestor=self.parent.hasSecureAncestor;
        }else {
            hasSecureAncestor=NO;
        }
    }
    return hasSecureAncestor;
}

Затем просто создайте предикат для проверки на hasSecureAncestor == YES. Пользовательский метод доступа будет проходить произвольно глубокие рекурсивные отношения в поисках безопасного предка.

1 голос
/ 03 августа 2010

Почему бы просто не захватить все объекты Папки с kNoSecurity?

NSPredicate *pred = [NSPredicate predicateWithFormat:@"secure = %@ ", [NSNumber numberWithInteger:kNoSecurity]];
0 голосов
/ 03 августа 2010

Как насчет возвращения через отношения:

NSPredicate *pred = [NSPredicate predicateWithFormat:"parent.secure = %@", [NSNumber numberWithInteger:kNoSecurity]];
...