سؤال

أحاول إنشاء تطبيق 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;
}

اتمني ان يكون مفيدا

جونسو

يجب أن تعمل. هل قمت بتعيين مدير Undo بشكل صحيح إلى ManagedObjectContext؟ إذا كنت قد فعلت ذلك بحق ، فقد تم تمكين التسجيل بشكل افتراضي ، ويجب أن تكون على ما يرام. هناك مقالة جيدة عن البيانات الأساسية هنا. يوجد برنامج تعليمي جيد عن البيانات الأساسية و NSundomanager هنا. امل ان يساعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top