停止循环

发布于 2024-08-08 19:10:22 字数 5386 浏览 9 评论 0原文

正如我之前的问题中所解释的...

此代码...

- (void)syncKVO:(id)sender {
    NSManagedObjectContext *moc = [self managedObjectContext];
    [syncButton setTitle:@"Syncing..."];
    NSString *dateText = (@"Last Sync : %d", [NSDate date]);
    [syncDate setStringValue:dateText];
    NSEntityDescription *entityDescription = [NSEntityDescription
                                                                                  entityForName:@"projects" inManagedObjectContext:moc];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:entityDescription];

    NSError *error = nil;
    NSArray *array = [moc executeFetchRequest:request error:&error];
    if (array == nil)
    {
        NSAlert *anAlert = [NSAlert alertWithError:error];
        [anAlert runModal];
    }
    NSArray *namesArray = [array valueForKey:@"name"];
    NSPredicate *predicate = [CalCalendarStore taskPredicateWithCalendars:[[CalCalendarStore defaultCalendarStore] calendars]];
    NSArray *tasksNo = [[CalCalendarStore defaultCalendarStore] tasksWithPredicate:predicate];
    NSArray *tasks = [tasksNo valueForKey:@"title"];
    NSMutableArray *namesNewArray = [NSMutableArray arrayWithArray:namesArray];
    [namesNewArray removeObjectsInArray:tasks];
    NSLog(@"%d", [namesNewArray count]);        
    NSInteger *popIndex = [calenderPopup indexOfSelectedItem];

    //Load the array
    CalCalendarStore *store = [CalCalendarStore defaultCalendarStore];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *supportDirectory = [paths objectAtIndex:0];
    NSString *fileName = [supportDirectory stringByAppendingPathComponent:@"oldtasks.plist"];

    NSMutableArray *oldTasks = [[NSMutableArray alloc] initWithContentsOfFile:fileName];
    [oldTasks removeObjectsInArray:namesArray];
    NSLog(@"%d",[oldTasks count]);
    //Use the content
    NSPredicate* taskPredicate = [CalCalendarStore taskPredicateWithCalendars:[[CalCalendarStore defaultCalendarStore] calendars]];
    NSArray* allTasks = [[CalCalendarStore defaultCalendarStore] tasksWithPredicate:taskPredicate];

    // Get the calendar
    CalCalendar *calendar = [[store calendars] objectAtIndex:popIndex];
    // Note: you can change which calendar you're adding to by changing the index or by
    // using CalCalendarStore's -calendarWithUID: method        

    // Loop, adding tasks
    for(NSString *title in namesNewArray) {
        // Create task
        CalTask *task = [CalTask task];
        task.title = title;
        task.calendar = calendar;

        // Save task
        if(![[CalCalendarStore defaultCalendarStore] saveTask:task error:&error]) {
                NSLog(@"Error");
                // Diagnostic error handling
                NSAlert *anAlert = [NSAlert alertWithError:error];
                [anAlert runModal];
        }
    } 

    NSMutableArray *tasksNewArray = [NSMutableArray arrayWithArray:tasks];
    [tasksNewArray removeObjectsInArray:namesArray];
    NSLog(@"%d", [tasksNewArray count]);        
    for(NSString *title in tasksNewArray) {
        NSManagedObjectContext *moc = [self managedObjectContext];
        JGManagedObject *theParent = 
        [NSEntityDescription insertNewObjectForEntityForName:@"projects"
                                      inManagedObjectContext:moc];
        [theParent setValue:nil forKey:@"parent"];
        // This is where you add the title from the string array
        [theParent setValue:title forKey:@"name"]; 
        [theParent setValue:[NSNumber numberWithInt:0] forKey:@"position"];

    }

    for(CalTask* task in allTasks)
        if([oldTasks containsObject:task.title]) {
                [store removeTask:task error:nil];
        }

    // Create a predicate for an array of names.
    NSPredicate *mocPredicate = [NSPredicate predicateWithFormat:@"name IN %@", oldTasks];
    [request setPredicate:mocPredicate];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    // Execute the fetch request put the results into array
    NSArray *resultArray = [moc executeFetchRequest:request error:&error];
    if (resultArray == nil)
    {
        // Diagnostic error handling
        NSAlert *anAlert = [NSAlert alertWithError:error];
        [anAlert runModal];
    }

    // Enumerate through the array deleting each object.
    // WARNING, this will delete everything in the array, so you may want to put more checks in before doing this.
    for (JGManagedObject *objectToDelete in resultArray ) {
        // Delete the object.
        [moc deleteObject:objectToDelete];
    }
    //Save the array
    [namesArray writeToFile:fileName atomically:YES];
    [syncButton setTitle:@"Sync Now"];
    NSLog(@"Sync Completed");
}

触发此代码...

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"name"]) {
        [self performSelector:@selector(syncKVO:)];
    }
}

因为我正在添加对象,并且当核心数据“名称”属性更改时会触发 KVO 方法。

如果 observeValueForKeyPath:ofObject:change:context: 方法是由 syncKVO 方法触发的,我需要停止该方法。我该怎么做?

As explained in my earlier question …

This code …

- (void)syncKVO:(id)sender {
    NSManagedObjectContext *moc = [self managedObjectContext];
    [syncButton setTitle:@"Syncing..."];
    NSString *dateText = (@"Last Sync : %d", [NSDate date]);
    [syncDate setStringValue:dateText];
    NSEntityDescription *entityDescription = [NSEntityDescription
                                                                                  entityForName:@"projects" inManagedObjectContext:moc];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:entityDescription];

    NSError *error = nil;
    NSArray *array = [moc executeFetchRequest:request error:&error];
    if (array == nil)
    {
        NSAlert *anAlert = [NSAlert alertWithError:error];
        [anAlert runModal];
    }
    NSArray *namesArray = [array valueForKey:@"name"];
    NSPredicate *predicate = [CalCalendarStore taskPredicateWithCalendars:[[CalCalendarStore defaultCalendarStore] calendars]];
    NSArray *tasksNo = [[CalCalendarStore defaultCalendarStore] tasksWithPredicate:predicate];
    NSArray *tasks = [tasksNo valueForKey:@"title"];
    NSMutableArray *namesNewArray = [NSMutableArray arrayWithArray:namesArray];
    [namesNewArray removeObjectsInArray:tasks];
    NSLog(@"%d", [namesNewArray count]);        
    NSInteger *popIndex = [calenderPopup indexOfSelectedItem];

    //Load the array
    CalCalendarStore *store = [CalCalendarStore defaultCalendarStore];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *supportDirectory = [paths objectAtIndex:0];
    NSString *fileName = [supportDirectory stringByAppendingPathComponent:@"oldtasks.plist"];

    NSMutableArray *oldTasks = [[NSMutableArray alloc] initWithContentsOfFile:fileName];
    [oldTasks removeObjectsInArray:namesArray];
    NSLog(@"%d",[oldTasks count]);
    //Use the content
    NSPredicate* taskPredicate = [CalCalendarStore taskPredicateWithCalendars:[[CalCalendarStore defaultCalendarStore] calendars]];
    NSArray* allTasks = [[CalCalendarStore defaultCalendarStore] tasksWithPredicate:taskPredicate];

    // Get the calendar
    CalCalendar *calendar = [[store calendars] objectAtIndex:popIndex];
    // Note: you can change which calendar you're adding to by changing the index or by
    // using CalCalendarStore's -calendarWithUID: method        

    // Loop, adding tasks
    for(NSString *title in namesNewArray) {
        // Create task
        CalTask *task = [CalTask task];
        task.title = title;
        task.calendar = calendar;

        // Save task
        if(![[CalCalendarStore defaultCalendarStore] saveTask:task error:&error]) {
                NSLog(@"Error");
                // Diagnostic error handling
                NSAlert *anAlert = [NSAlert alertWithError:error];
                [anAlert runModal];
        }
    } 

    NSMutableArray *tasksNewArray = [NSMutableArray arrayWithArray:tasks];
    [tasksNewArray removeObjectsInArray:namesArray];
    NSLog(@"%d", [tasksNewArray count]);        
    for(NSString *title in tasksNewArray) {
        NSManagedObjectContext *moc = [self managedObjectContext];
        JGManagedObject *theParent = 
        [NSEntityDescription insertNewObjectForEntityForName:@"projects"
                                      inManagedObjectContext:moc];
        [theParent setValue:nil forKey:@"parent"];
        // This is where you add the title from the string array
        [theParent setValue:title forKey:@"name"]; 
        [theParent setValue:[NSNumber numberWithInt:0] forKey:@"position"];

    }

    for(CalTask* task in allTasks)
        if([oldTasks containsObject:task.title]) {
                [store removeTask:task error:nil];
        }

    // Create a predicate for an array of names.
    NSPredicate *mocPredicate = [NSPredicate predicateWithFormat:@"name IN %@", oldTasks];
    [request setPredicate:mocPredicate];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    // Execute the fetch request put the results into array
    NSArray *resultArray = [moc executeFetchRequest:request error:&error];
    if (resultArray == nil)
    {
        // Diagnostic error handling
        NSAlert *anAlert = [NSAlert alertWithError:error];
        [anAlert runModal];
    }

    // Enumerate through the array deleting each object.
    // WARNING, this will delete everything in the array, so you may want to put more checks in before doing this.
    for (JGManagedObject *objectToDelete in resultArray ) {
        // Delete the object.
        [moc deleteObject:objectToDelete];
    }
    //Save the array
    [namesArray writeToFile:fileName atomically:YES];
    [syncButton setTitle:@"Sync Now"];
    NSLog(@"Sync Completed");
}

triggers this code …

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"name"]) {
        [self performSelector:@selector(syncKVO:)];
    }
}

because I am adding objects and the KVO method is triggered when the Core Data 'name' property is changed.

I need to stop the observeValueForKeyPath:ofObject:change:context: method if it was triggered by the syncKVO method. How would I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鲸落 2024-08-15 19:10:22

您可以做的最简单的事情是使用一个实例变量,该变量跟踪您是否正在同步并在设置时忽略观察者的更改。最好在 syncKVO: 的开头和结尾处停止并开始观察,但这取决于您实际观察的内容:如果您观看大量收藏。

The simplest thing you could do is use an instance variable which keeps track of whether you’re syncing and ignore observer changes when it’s set. It may be better to stop and start observing at the beginning and end of syncKVO:, but it depends on what you’re actually observing: you don’t want to mass unsubscribe and resubscribe if you’re watching a large collection.

于我来说 2024-08-15 19:10:22

看看您的代码,我想知道您是否真的想在保存实体时进行同步,而不是在对象键更改后立即进行同步。我认为您最好完全放弃观察并使用 CoreData 文档 来确定需要更新哪些实体。

Looking at your code I wonder if you really want to do this syncing when entities are saved, and not as soon as the object keys changed. I think you’d be better off ditching observing completely and watching for the NSManagedObjectContextObjectsDidChangeNotification, using the values of the userInfo keys specified in the CoreData documentation to determine which entities need to be updated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文