0

으로 내 이전 질문에서 설명 루프 ...내가 개체를 추가하고와 KVO 방법이기 때문에

이 코드 ...

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

중지 핵심 데이터 '이름'속성이 변경되면 트리거됩니다.

메서드가 syncKVO 메서드에 의해 트리거 된 경우이를 중지해야합니다. 어떻게하면 좋을까요?

답변

0

코드를 살펴보면 객체 키가 변경되는 즉시 엔티티가 저장 될 때 동기화를 수행할지 궁금합니다. 난 당신이 더 완벽하게 관찰하고, NSManagedObjectContextObjectsDidChangeNotification을보고, CoreData documentation에 지정된 userInfo 키의 값을 사용하여 업데이트해야 할 엔티티를 결정하는 것이 더 나을 것이라고 생각합니다.

+0

흠. NSManagedObjectContextObjectsDidChangeNotification 어떻게 사용합니까, 뭔가 변경 될 때 메서드를 트리거하지? 또한 Core Data 속성을 관찰하고 있는데 NSManagedObjectContextObjectsDidChangeNotification을 사용하여 동일한 작업을 수행 할 수 있습니까? – Joshua

+0

또한이 방법으로 내 무한 루프를 막을 수 있습니까? – Joshua

+0

옵서버를 추가할까요? http://snapplr.com/qffn? – Joshua

1

당신이 할 수있는 가장 간단한 방법은 당신이 동기화하고 있는지 여부를 추적하고 설정시 관찰자 변경 사항을 무시하는 인스턴스 변수를 사용하는 것입니다. 시작과 끝 부분 인 syncKVO:에서 중지하고 관찰하는 것이 더 좋을 수 있지만 실제로 관찰하는 내용에 따라 달라집니다. 큰 컬렉션을보고있는 경우 대량 구독을 취소하고 다시 구독하고 싶지는 않습니다.

+0

나는 그 일을 시도했지만 디버거에서 오류가 발생했습니다. 이 코드를 핵심 데이터 이름 속성을 관찰하고있는 Managed Object 하위 클래스에 추가했습니다. http://cld.ly/616yf하지만 문제가 있었는지 http://cld.ly/1c6ye. – Joshua

+0

이것이 어떤 이유입니까? – Joshua

+0

클래스 메소드 내부에서'self'는 개별 인스턴스가 아닌'Class' 객체 (JGManagedObject 메타 클래스의 인스턴스)를 참조하기 때문에 옵저버 관리 호출은 개별 인스턴스가 아닌 클래스 인스턴스의 키를보고 있습니다. 이것들을 인스턴스 메소드 (바람직하게는'-syncKVO :'를 포함하는 컨트롤러에서 관리 객체에 추가/제거 옵저버 인터페이스가 이미 제공되기 때문에)로 옮겨야합니다. –

관련 문제