Пользовательский метод доступа к данным Core даже не вызывается - PullRequest
4 голосов
/ 18 февраля 2012

У меня есть свойство Core Data, которое я пытаюсь установить во время выполнения, со значением, полученным из другого свойства.Однако любопытно, что созданный мной пользовательский метод доступа никогда даже не вызывается.

Свойство seasonNameVisible вызывается только из предиката с терминами из поля поиска, как показано здесь:

// Add our search predicates
for (NSString *term in searchTerms) {
    NSPredicate *searchTermPredicate = [NSPredicate predicateWithFormat:@"(episodeName contains[cd] %@) OR (fromSeason.seasonNameVisible contains[cd] %@) OR (fromSeason.fromSeries.seriesName contains[cd] %@)", term, term, term];
    [subPredicates addObject:searchTermPredicate];
}

Если я изменю это свойство на seasonName, эта часть предиката вернет результат просто отлично, поэтому я не подозреваю предикат или любой другой код поиска.

Мой планэто получить seasonNameVisible NSString из seasonName во время выполнения.Итак, я изменил подкласс Season NSManagedObject, чтобы переопределить метод доступа и установщик, используя примитивные методы доступа.Но, насколько я могу судить, мой метод доступа никогда не вызывается.

Вот заголовок / интерфейс:

//
//  Season.h
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Episode, Series;

@interface Season : NSManagedObject

@property (nonatomic, retain) NSNumber * seasonIndex;
@property (nonatomic, retain) NSString * seasonName;
@property (nonatomic, retain) NSString * seasonNameVisible;
@property (nonatomic, retain) NSSet *episodes;
@property (nonatomic, retain) Series *fromSeries;

@property (nonatomic, retain) NSString * primitiveSeasonName;
@property (nonatomic, retain) NSString * primitiveSeasonNameVisible;
@end

@interface Season (CoreDataGeneratedAccessors)

- (void)addEpisodesObject:(Episode *)value;
- (void)removeEpisodesObject:(Episode *)value;
- (void)addEpisodes:(NSSet *)values;
- (void)removeEpisodes:(NSSet *)values;

@end

// my additions
@interface Season (PrimitiveAccessors)
- (NSString *)primitiveSeasonName;
- (NSString *)primitiveSeasonNameVisible;
@end

... и реализация:

//
//  Season.m
//

#import "Season.h"
#import "Episode.h"
#import "Series.h"


@implementation Season

@dynamic seasonIndex;
@dynamic seasonName;
@dynamic seasonNameVisible;
@dynamic episodes;
@dynamic fromSeries;

// my additions
@dynamic primitiveSeasonName;
@dynamic primitiveSeasonNameVisible;

- (NSString *)seasonNameVisible
{
    NSString *visible;
    [self willAccessValueForKey:@"seasonNameVisible"];
    visible = [self primitiveValueForKey:@"seasonNameVisible"];
    [self didAccessValueForKey:@"seasonNameVisible"];

    if (visible != nil) {
        return visible;
    } else {
        [self willAccessValueForKey:@"seasonName"];
        visible = [[self primitiveValueForKey:@"seasonName"] substringFromIndex:2];
        [self didAccessValueForKey:@"seasonName"];
        [self setSeasonNameVisible:visible];
        return visible;
    }
}

- (void)setSeasonNameVisible:(NSString *)seasonNameVisible 
{
    [self willChangeValueForKey:@"seasonNameVisible"];
    [self setPrimitiveValue:seasonNameVisible forKey:@"seasonNameVisible"];
    [self didChangeValueForKey:@"seasonNameVisible"];
}

@end

Я прочитал документы Apple и искал справку о пользовательских методах доступа в StackOverflow, и я думаю У меня правильный код (это первый раз, когда я пытался использовать примитивные средства доступаили переопределить метод NSManagedObject, так что я немного оторвался от своей обычной глубины), но даже когда я ставлю на него точку останова, она никогда не вызывается.

1 Ответ

1 голос
/ 18 февраля 2012

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

После дополнительной информации в комментариях я бы посоветовал следующее:

  • разделите ваш сезон на два атрибута: номер сезона (int) и название сезона
  • Сортируйте запрос на получение по номеру сезона
  • путь ключа имени раздела - это новое свойство только для чтения вашего объекта, которое возвращает строку, состоящую из числа и имени

Ошибка, которую вы видите в своем комментарии, является нормальной при изменении запроса на выборку, используемого с FRC. Удалите приложение из симулятора и пересоберите, и оно исчезнет, ​​или используйте нулевой кеш при разработке. FRC хранит свой кэш постоянно (например, между запусками), поэтому любые изменения нарушают его.

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

sectionNameKeyPath

Ключевой путь к объектам результата, который возвращает имя раздела. Передайте nil, чтобы указать, что контроллер должен генерировать один раздел. Имя раздела используется для предварительного вычисления информации о разделе. Если этот путь ключа не совпадает с указанным первым дескриптором сортировки в fetchRequest, они должны генерировать те же относительные упорядочения. Например, первый дескриптор сортировки в fetchRequest может указывать ключ для постоянного свойства; sectionNameKeyPath может указывать ключ для переходного свойства, полученного из постоянного свойства .

Таким образом, у вас будет объект Season с двумя постоянными атрибутами: seasonNumber и seasonName. Вы бы отсортировали запрос на получение по номеру сезона. Ваш путь ключа имени раздела (для выборки, предположительно, в эпизодах, имеющих отношение season) будет @"season.seasonSectionName", реализованным следующим образом - никаких изменений в модели управляемого объекта, просто изменения в объекте Season:

Season.h:

@property(nonatomic,readonly) NSString *seasonSectionName;

Season.m:

-(NSString*)seasonSectionName
{
    return [NSString stringWithFormat:@"%d - %@",self.seasonNumber,self.seasonName];
}

Все, что вы действительно делаете, это украшаете номер сезона другим свойством.

...