gpt4 book ai didi

objective-c - 方法/IBAction 陷入无限循环。仍然没有成功

转载 作者:行者123 更新时间:2023-12-03 17:37:14 25 4
gpt4 key购买 nike

现在这可能听起来像我之前的问题,但我已经改变并尝试了一些在我的其他问题中回答的事情,试图使其工作,但我仍然遇到同样的问题。

我正在观察 NSManagedObject 子类中的核心数据属性,并且当属性更改时调用另一个方法,但在该方法中它添加了核心数据对象,该对象触发 KVO 方法,该方法再次触发该方法,等等。或者看起来是这样,我对此不太确定,因为似乎发生了一些不同的事情,这是一系列事件......

  1. 我单击一个与 iCal 同步的按钮(这在 IBAction 中,其代码与方法syncKVO 中的代码完全相同)。此同步工作正常。
  2. 我将一个对象添加到我的大纲 View 中。一切都很好。
  3. 我更改了它的名称,这会触发与 iCal 同步的 KVO 声明(因为我更改了“名称”属性)。工作正常。
  4. 我删除了刚刚添加的对象,它以某种方式触发了 KVO 声明(从而触发了该方法),并使我陷入了无限循环

现在来看一些代码。

NSManagedObject 子类(称为 JGManagedObject)内的代码...

- (void) awakeFromFetch {
[self addObserver:[NSApp delegate] forKeyPath:@"name" options:0 context:nil];
}

- (void) awakeFromInsert {
[self addObserver:[NSApp delegate] forKeyPath:@"name" options:0 context:nil];
}

+ (void) addObserver{
[self addObserver:[NSApp delegate] forKeyPath:@"name" options:0 context:nil];
}

+ (void) removeObserver{
[self removeObserver:[NSApp delegate] forKeyPath:@"name"];
}

KVO 声明(在应用程序委托(delegate)内)...

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

方法(也在应用程序委托(delegate)内部)...

- (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");
}

我尝试过...

过滤调用 KVO 声明的键路径

if ([keyPath isEqualToString:@"name"]) {

}

使用

分离和重新附加观察者
[JGManagedObject removeObserver];
//and
[JGManagedObject addObserver];

但是它第一次工作,但第二次停止该方法,说它无法删除观察者,因为它没有观察,这是没有意义的,因为我第一次再次添加了观察者。这就是为什么我将此代码保留在实际方法之外,否则它将在第二次同步时停止。

我不确定这是怎么回事,我想我已经尝试了一切。出了什么问题?

任何帮助将不胜感激。

最佳答案

问题可能出在这里:

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

}

每当“name”发生某些事情时,无论“name”实际发生了什么,您都会调用syncKVO:我建议您开始使用对象、更改和上下文参数来确定刚刚发生了什么以及应该采取什么操作(如果有)。

顺便说一句,向应用程序委托(delegate)添加大量内容并不被认为是好的做法。您可能希望将所有这些同步内容放入适当的 Controller 类中,并在需要时调用 [NSApp delegate]。

关于objective-c - 方法/IBAction 陷入无限循环。仍然没有成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1617752/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com