Core Data を使用して iOS アプリを開発しています。、エンティティ、およびエンティティとの関係Log
との一対多の関係を持つエンティティがあります。ログには、、、プロパティもあります。ログを作成し、そのプロパティを変更し、エンティティを追加すると、アプリケーションを終了するまで、これらの変更が正しく表示されます。すべての変更が消え、sqlite データベースを見ていましたが、これらの変更はすべてデータベースに保持されませんでした。データベースでは、オブジェクトが作成されるだけで、オブジェクトにリンクされません。Audio
Photo
one-to-one
Status
text
longitude
latitude
status
status
log
しかし、audio
orphoto
オブジェクトをorに追加すると、 log.audioSet
orへlog.photoSet
の変更をlog
含め、 に対して行った変更が突然データベースに保存されます。text
status
NSManagedObjectContext
そのため、関連する one_to_many エンティティが追加され、[[LTLogStore sharedStore] saveChanges]
が突然機能し始めるまで、変更は でのみ維持されるようです。
を管理するためにシングルトンを使用していNSManagedObjectContext
ます。何か案は?
関連する場合は、いくつかのコードを投稿します。ありがとう。
更新: これらのコードで十分かどうかはわかりません。しかし、基本的にすべてが機能し、表示されますが、データベースに保存されません。を使用してandmogenerator
を設定していますが、すべてがコンテキスト内にあるためです。これが必要なコードかどうかはわかりません。text
latitude
コード:
@interface LTLogStore : NSObject{
}
+ (LTLogStore *)sharedStore;
- (void)removeItem:(Log *)p;
- (Log *)createItem;
- (BOOL)saveChanges;
@property(nonatomic, strong) NSFetchedResultsController *resultsController;
@property(nonatomic, strong) NSManagedObjectModel *model;
@property(nonatomic, strong) NSManagedObjectContext *context;
@end
@implementation LTLogStore
@synthesize resultsController;
@synthesize context, model;
+ (LTLogStore *)sharedStore
{
static LTLogStore *sharedStore = nil;
if(!sharedStore){
sharedStore = [[super allocWithZone:nil] init];
}
return sharedStore;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedStore];
}
- (id)init
{
self = [super init];
if(self) {
model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *psc =
[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// Where does the SQLite file go?
NSString *path = [self itemArchivePath];
NSURL *storeURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&error]) {
[NSException raise:@"Open failed"
format:@"Reason: %@", [error localizedDescription]];
}
// Create the managed object context
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:psc];
// The managed object context can manage undo, but we don't need it
[context setUndoManager:nil];
}
return self;
}
- (NSFetchedResultsController *)resultsController {
if (resultsController !=nil) {
return resultsController;
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *e = [[model entitiesByName] objectForKey:@"Log"];
[request setEntity:e];
NSSortDescriptor *sd = [NSSortDescriptor
sortDescriptorWithKey:@"created_at"
ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sd]];
[request setReturnsObjectsAsFaults:NO];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:nil cacheName:@"Root"];
NSError *error;
BOOL success = [fetchedResultsController performFetch:&error];
if (!success) {
//handle the error
}
return fetchedResultsController;
}
- (NSString *)itemArchivePath
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
// Get one and only document directory from that list
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *storePath = [documentDirectory stringByAppendingPathComponent:@"store.data"];
return storePath;
}
- (BOOL)saveChanges
{
NSError *err = nil;
BOOL successful = [context save:&err];
NSLog(@"Saving changes to the database");
if (!successful) {
NSLog(@"Error saving: %@", [err localizedDescription]);
}
return successful;
}
- (void)removeItem:(Log *)l
{
[context deleteObject:l];
[self saveChanges];
}
- (Log *)createItem
{
Log *p = [NSEntityDescription insertNewObjectForEntityForName:@"Log"
inManagedObjectContext:context];
[self saveChanges];
return p;
}
@end
@interface Log : _Log {
}
//these two are some custom convenience methods for location attributes, but it does the work of setting the longitude and latitude value in the log object, but calling the [[LTLogStore sharedStore] saveChanges] still won't save it into the database.
-(CLLocation*)location;
-(void)setLocation:(CLLocation*)location;
//this all works
-(Audio*)newAudio;
-(Audio*)newAudioWithPath:(NSString*)audioPath;
//after calling this method, even the log.text changes will be saved to the database.
-(void)addAudioWithPath:(NSString*)audioPath;
-(void)removeAudio:(Audio*)audio;
@end
#import "Log.h"
#import "Audio.h"
#import "LTLogStore.h"
@implementation Log
-(CLLocation*)location{
if (!self.longitude || !self.latitude) {
return nil;
}
CLLocation *l = [[CLLocation alloc] initWithLatitude:[self.latitude doubleValue] longitude:[self.longitude doubleValue]];
return l;
}
-(void)setLocation:(CLLocation*)location{
if (location==nil) {
self.latitude = nil;
self.longitude = nil;
}
self.latitude = [NSNumber numberWithDouble: location.coordinate.latitude];
self.longitude = [NSNumber numberWithDouble:location.coordinate.longitude];
[[LTLogStore sharedStore] saveChanges];
}
-(Audio*)newAudio{
Audio *a = [Audio new];
a.log = self;
return a;
}
-(Audio*)newAudioWithPath:(NSString*)audioPath{
Audio *new = [self newAudio];
[new setKey:audioPath];
return new;
}
-(void)addAudioWithPath:(NSString*)audioPath{
Audio *new = [self newAudio];
[new setKey:audioPath];
[[LTLogStore sharedStore] saveChanges];
}
-(void)removeAudio:(Audio*)audio{
[self.audiosSet removeObject:audio];
[[[LTLogStore sharedStore] context] deleteObject:audio];
[[LTLogStore sharedStore] saveChanges];
}
@end
アップデート:
問題は解決しました。回答を参照してください。
更新の質問: オーバーライドが問題を引き起こしているのはなぜですか? Core Data や KVO の背後にある魔法の背後にある原因を誰か説明できますか?