Coredata и NSPersistentDocument: сбой суммы номеров столбцов

У меня проблема с привязкой столбца @sum в моей программе:

Я делаю программу на основе Coredata, NSPersistentDocument. Я делаю в основном все из IB, создание модели данных, NSArrayController и NSTableView...

У меня всего 1 объект с 62 атрибутами (61 NSString и 1 NSNumber). Я импортирую файл CSV с 12722 записями. Импорт работает хорошо, можно сохранять в xml, двоичный файл, sqlite... Я дважды проверил, что в целом процесс работает идеально. Можно сохранить/загрузить. Все есть.

Проблема, которая у меня есть: я создал метку, которую я ПРИВЯЗЫВАЮ к @sum столбца со свойством NSNumber. Вот как я сделал

>     label->Bindings Inspector->Value
>      Bind to: My_Entity_NSArrayController
>       Controller Key: selection
>       Model Key Path: @sum.myNumericAttribute

Когда я запускаю программу, нажимаю «Импорт», выбираю ВСЕ строки, @sum работает хорошо. Однако это быстро, и вот первая проблема: как только я сохраняю файл (перепробовал все... бинарные/xml/sqlite), а затем загружаю его и снова пытаюсь выбрать ВСЕ, программа вылетает без ошибок.

Пробовал через "Профиль"->Распределения. Я заметил:

  • у меня нет утечек памяти
  • При загрузке с диска, а затем выбрать все: Идет крайне медленно. Через 5 минут я еще не закончил (я остановил это), и я увидел +45 МБ CFNumber (Live Bytes) и> 1.500.00#Overall. Значит, здесь что-то не так, так как я говорю о 12722 строках/регистрах типа Interger32.

Вторая проблема такая же, но воспроизведена под другим углом. Вместо «выборки» я попытался использовать «объекты аранжировки». В этом случае проблема появляется даже при импорте из CSV, он идет очень медленно и в конце концов вылетает. Попытка открыть уже созданный файл также вылетает.

Вот как я сделал label->Bindings Inspector->Value

>    label->Bindings Inspector->Value
>      Bind to: My_Entity_NSArrayController
>       Controller Key: arrangedObjects
>       Model Key Path: @sum.myNumericAttribute

Не могли бы вы помочь мне с некоторыми идеями, которые могут помочь мне найти проблему?

Большое спасибо.

Луис


---- НОВОЕ ИЗМЕНЕНИЕ ПОСЛЕ ДОПОЛНИТЕЛЬНЫХ ИССЛЕДОВАНИЙ ----

Я нашел обходной путь, который НЕ ПОНИМАЮ, пожалуйста, комментарии/ответы действительно ценятся.

Моя программа использует Coredata (SQLite), NSPersistentDocument, NSTableView и NSArrayController. Я хочу, чтобы работающий NSTextField был привязан к операции сбора @sum.

Проблема: как только я открываю существующий документ с заполненной базой данных SQLite и пытаюсь выполнить привязку к аранжированным объектам[email protected]_24_Bookings из NSWindowController, происходит сбой программы.

Мое первоначальное предположение, что это связано с Не удается получить доступ к содержимому контроллера объекта после загрузки пера, однако я безуспешно следовал рекомендации выполнить первую выборку следующим образом:

- (void) awakeFromNib
{
    :
    BOOL ok = [[self out_CtEn_Transaction] fetchWithRequest:nil merge:NO error:&error];
    :

Продолжая эту идею, я обнаружил, что если я создам «настоящую» полную Fetch + я выполню доступ @sum из подкласса Document, тогда это сработает.

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

Интерфейс ABDocument (подкласс NSPersistentDocument)

@interface ABDocument : NSPersistentDocument {

    BOOL        ivNewDocument;
    NSArray     *ivFetchedTransactions;
    NSNumber    *ivTotalBookings;
}

@property (nonatomic, getter=isNewDocument) BOOL newDocument;
@property (nonatomic, retain) NSArray   *fetchedTransactions;
@property (nonatomic, retain) NSNumber  *totalBookings;

:

Реализация документа AB

#import "ABDocument.h"
#import "ABWindowController.h"

@implementation ABDocument

@synthesize newDocument                 = ivNewDocument;
@synthesize totalBookings               = ivTotalBookings;
@synthesize fetchedTransactions         = ivFetchedTransactions;

:

/** @brief Create one instance of my custom NSWindowController subclass (ABWindowController)
 *
 * In my NSPersistentDocument I do override makeWindowControllers, where I create 
 * one instance of my custom NSWindowController subclass and use addWindowController: 
 * to add it to the document. 
 *
 */
- (void) makeWindowControllers
{
    // Existing Document?
    if ( ![self isNewDocument]) {
        // NSLog(@"%@:%@ OPENING EXISTING DOCUMENT", [self class], NSStringFromSelector(_cmd));

        // Opening existing document (also has an existing DDBB (SQLite)), so
        // make sure I do perform a first complete "fetch + @sum" to void issues
        // with my NIB bind's.
        [self firstFetchPreventsProblems];
    }

    // Now I can create the Window Controller using my "MainWindow.xib".
    ABWindowController *windowController = [[ABWindowController alloc] init];
    [self addWindowController:windowController];
    [windowController release];    
}


/** @brief First complete "fetch + @sum" to void issues with my NIB bind's.
 *
 *  Before I create the Window Controller with "MainWindow.xib" I have to perform a
 *  first Fetch AND also retrieve a @sum of an NSNumber column.
 *
 *  My NIB has an NSTextField BOUND to @arrangedObjects.@sum.<property> through a NSArrayController
 *  If I don't call this method before the NIB is loaded, then the program will crash.
 *
 */
- (void) firstFetchPreventsProblems {

    // Prepare the Fetch
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Transaction"];

    // 1) Perform the Fetch
    NSError *error = nil;
    [self setFetchedTransactions:[[self managedObjectContext ] executeFetchRequest:request error:&error]];
    if ([self fetchedTransactions] == nil)
    {
        NSLog(@"Error while fetching\n%@",
              ([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error");
        exit(1);
    }

    // 2) Execute Collection Operation @sum
    [self setTotalBookings:[[self fetchedTransactions] valueForKeyPath:@"@sum.t_24_Bookings"]];
}

ABWindowController (контроллер, который загружает мой NIB)

- (void)windowDidLoad
{

:
        // PROGRAM CRASH HERE 
        // IF [self firstFetchToPreventsProblems]; is NOT CALLED
        // ABDocument's "makeWindowControllers:"
       [[self totalSumField] bind: @"value" toObject: [self out_CtEn_Transaction]
                       withKeyPath:@"[email protected]_24_Bookings" options:nil];

}

Пожалуйста, если вы можете прокомментировать, это действительно ценно, у меня есть решение, но я не понимаю, почему.

Танки,
Луис


person Luis Palacios    schedule 04.11.2012    source источник


Ответы (1)


Я сам нашел проблему после нескольких дней исследований. Это было легко (теперь, когда я знаю):

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

Я применил прокомментированные решения в нескольких сообщениях о создании вторичного MOC во вторичном потоке.

Теперь мой код является потокобезопасным в соответствии с действиями, связанными с coredata, поэтому программа не падает.

Еще раз спасибо сообществу.

Луис

person Luis Palacios    schedule 30.11.2012