Nsundomanager التراجع عن عدم العمل مع البيانات الأساسية
-
21-09-2019 - |
سؤال
أحاول إنشاء تطبيق iPhone حيث يمكن للمستخدم إضافة إدخالات. عندما يضغط على إدخال جديد ، سوف يطالب صندوق يطلب منه ببعض المعلومات. ثم يمكنه إما الضغط على "إلغاء" أو "حفظ" لتجاهل البيانات أو حفظها على القرص.
من أجل الادخار ، أنا أستخدم إطار البيانات الأساسية ، والذي يعمل بشكل جيد. ومع ذلك ، لا يمكنني الحصول على زر "إلغاء" للعمل. عندما تنبثق النافذة ، وأطلب معلومات ، أقوم بإنشاء كائن جديد في سياق الكائن المدار (MOC). ثم عندما يضغط المستخدم على الإلغاء ، أحاول استخدام Nsundomanager الذي ينتمي إلى MOC.
أود أيضًا أن أفعل ذلك باستخدام مجموعات التراجع المتداخلة ، لأنه قد تكون هناك مجموعات متداخلة.
لاختبار هذا ، كتبت تطبيقًا بسيطًا. التطبيق هو مجرد قالب "التطبيق القائم على النوافذ" مع تمكين البيانات الأساسية. بالنسبة لنموذج البيانات الأساسية ، أقوم بإنشاء كيان واحد يسمى "الكيان" مع سمة عدد صحيح "X". ثم داخل ApplicationDidFinishLaunching ، أضيف هذا الرمز:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
unsigned int x=arc4random()%1000;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager beginUndoGrouping];
NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
NSLog(@"Insert Value %d",x);
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager endUndoGrouping];
[self.managedObjectContext.undoManager undoNestedGroup];
NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityEntity];
NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
for(entity in result) {
NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
}
[window makeKeyAndVisible];
}
الفكرة بسيطة. حاول إدراج كائن كيان جديد ، والتراجع عنه ، وجلب جميع كائنات الكيان في MOC وطباعتها. إذا نجح كل شيء بشكل صحيح ، فلن يكون هناك أي كائنات في النهاية.
ومع ذلك ، أحصل على هذا الإخراج:
[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136
كما ترون ، الكائن موجود في MOC بعد أن أحاول التراجع عن إنشائها. أي اقتراحات حول ما أفعله خطأ؟
المحلول
تحدث مشكلتك عن حقيقة أنه ، على عكس OS X ، لا يحتوي سياق الكائن المدير على iPhone على مدير تراجع افتراضيًا. تحتاج إلى إضافة واحدة بشكل صريح.
قم بتغيير الكود الذي تم إنشاؤه في مندوب التطبيق لخاصية ManagedObjectContext لتبدو مثل هذا:
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
//add the following 3 lines of code
NSUndoManager *undoManager = [[NSUndoManager alloc] init];
[managedObjectContext setUndoManager:undoManager];
[undoManager release];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
بعد إجراء هذا التغيير ، لم تعد رسالة السجل الثاني مطبوعة.
امل ان يساعد...
ديف
نصائح أخرى
حاولت نهج ديف ، لكنني لم أعمل من أجلي. لقد وجدت أخيرًا الحل في مثال Apple coredatabooks
تتمثل الحيلة في إنشاء سياق جديد يشاركه سياق تطبيقك. لتجاهل التغييرات التي لا تحتاجها للقيام بأي شيء ، ما عليك سوى تجاهل كائن السياق الجديد. نظرًا لأنك تشارك المنسق ، فإن حفظ التحديثات الخاصة بك.
فيما يلي نسختي المكيفة ، حيث أستخدم كائنًا ثابتًا لسياق Temp لإنشاء كائن ChannelMo جديد.
//Gets a new ChannelMO that is part of the addingManagedContext
+(ChannelMO*) getNewChannelMO{
// Create a new managed object context for the new channel -- set its persistent store coordinator to the same as that from the fetched results controller's context.
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
addingManagedObjectContext = addingContext;
[addingManagedObjectContext setPersistentStoreCoordinator:[[self getContext] persistentStoreCoordinator]];
ChannelMO* aux = (ChannelMO *)[NSEntityDescription insertNewObjectForEntityForName:@"ChannelMO" inManagedObjectContext:addingManagedObjectContext];
return aux;
}
+(void) saveAddingContext{
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserver:self selector:@selector(addControllerContextDidSave:)
name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];
NSError *error;
if (![addingManagedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];
// Release the adding managed object context.
addingManagedObjectContext = nil;
}
اتمني ان يكون مفيدا
جونسو