2016-04-01 6 views
0

У меня есть пользовательский объект (Data), наследующий от NSObject, который должен быть сохранен в основных данных. Поэтому я создал NSManagedObject (Transaction), который содержит Data, что-то вроде этого:Основные данные не возвращают корректные данные иногда

@interface Transaction (CoreDataProperties) 

@property (nonatomic) BOOL m_isUploaded; 
@property (nullable, nonatomic, retain) id m_transactionData; // this is the Data class, stored under Transformable 
@property (nonatomic) int64_t m_submitDateTimeEpochMilliseconds; 
@property (nullable, nonatomic, retain) NSString *m_uuid; 

@end 

я создал один контекст и сделал все, что связано с контекстом в основном потоке.

Я сделал Data соответствует протоколам NSCoding и NSCopying. Кроме того, некоторые пользовательские классы, используемые в Data, также соответствуют NSCoding.

Это короткая выдержка из Data.h:

@interface Data : NSObject <NSCoding, NSCopying> 

@property (strong, nonatomic, nullable) HeldItem *m_heldItem; 
@property (strong, nonatomic, nullable) NSDecimalNumber *m_discountAmount; 
@property (strong, nonatomic, nonnull) NSMutableArray<Record *> *m_records; 
@property (strong, nonatomic, nonnull) NSString *m_transactionId; 
@property (nonatomic) CLLocationCoordinate2D m_location; 
@property (strong, nonatomic, nullable) NSString *m_status; 

- (void)encodeWithCoder:(nonnull NSCoder *)aCoder; 
- (nonnull id)initWithCoder:(nonnull NSCoder *)aDecoder; 

...lots of variables/methods here... 

@end 

Если я чисто просто вставить, нет никаких проблем (я подтвердил это, глядя на переменные во encodeWithCoder:). Или, если я делаю чистое чтение, проблем нет.

Однако, если бы я, чтобы вставить новую TransactionData) запись и поиск/прочитать существующую запись и изменить его (Data), существующая запись не спасутся, и новый рекорд в основном пустой (как будто новый). Эта проблема возникает при случайных. Я могу запустить его 8 раз, прежде чем столкнуться с этой ситуацией.

Любая идея, где я, возможно, пошла не так? Я застрял довольно долго.

Это та часть, где он, кажется, дает мне проблему:

// Store the existing/new data into Core Data 
    Transaction *t = [MANAGER createTransaction]; 
    Data *data = [Data new]; 
    t.m_kmsTransactionData = data; 

    // ...some assigning stuffs to other variables... 

    // ========== if this whole section is omitted the newly created record saves fine ========= 
    Transaction *old = [MANAGER getTransactionFromCoreDataWithId:someOldDataIdString]; 
    // oldData sometimes is returning a blank object (i.e. booleans are no, objects are nil etc) 
    Data *oldData = [old.m_kmsTransactionData mutableCopy]; 

    oldData.m_status = @"old"; // testing to see if the old record gets updated 

    old.m_isUploaded = NO; 
    old.m_kmsTransactionData = [oldData copy]; 

    // This doesn't work because oldData.m_transactionId is nil 
    data.m_transactionId = [MANAGER generateNewTransactionIDBasedOn:oldData.m_transactionId]; 
    //=============================================== 

    // ... more assigning code here .... 

    // Save context 
    [MANAGER saveDatabase]; 

-

// Some helper function in some manager 
- (Transaction * _Nonnull)getTransactionFromCoreDataWithId:(NSString * _Nonnull)dataId 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:[Transaction entityName]]; 
    request.returnsObjectsAsFaults = NO; 

    NSError *error; 
    NSArray<Transaction *> *fetchedObjects = [self.m_coreDataStore.managedObjectContext executeFetchRequest:request error:&error]; 
    NSAssert(fetchedObjects != nil, @"Failed to execute %@: %@", request, error); 

    if(fetchedObjects == nil || fetchedObjects.count == 0) 
    { 
     // error 
     return nil; 
    } 

    for(Transaction *t in fetchedObjects) 
    { 
     Data *td = t.m_kmsTransactionData; 
     if([td.m_salesRecordId isEqualToString:salesRecordId]) 
     { 
      return t; 
     } 
    } 
return nil; 
} 
+0

где вы экономить?почему ваш класс не является подклассом «NSManagedObject»? Вы сериализуете 'Data' в экземпляры' Transaction'? – Wain

+0

Мои «данные» уже были созданы как «NSObject», и поскольку мне нужно хранить «данные», чтобы он сохранялся, а также отслеживал, что я сделал с «данными», я создал «транзакцию» для их хранения , Я спасаю в конце всего. Позвольте мне исправить код. – CyberMew

+0

Можете ли вы включить отладку компакт-диска «-com.apple.CoreData.SQLDebug 1» в разделе «Аргументы, переданные при запуске». Интересно, будет ли CD автоматически использовать NSKeyedArchiver для упаковки/распаковки вашего объекта. – Andy

ответ

0

Я думал, что это был бзик основных данных с трансформируемых свойствами, но это не было.

часть, где я был

// ...some assigning stuffs to other variables... 

Я назначил m_salesRecordId к существующему идентификатору, который уже находится в базе данных. Поэтому при поиске по методу getTransactionFromCoreDataWithId: он возвратил вновь созданный объект на основе m_salesRecordId, который я только что сделал ранее.

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

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

ТЛ; др: Проверьте вашу программу логики снова первый

Смежные вопросы