NSDiptributedNotifications를 사용하여 프로세스간에 핵심 데이터 저장소를 어떻게 공유합니까?

StackOverflow https://stackoverflow.com/questions/1815518

  •  07-07-2019
  •  | 
  •  

문제

배경

나는 이미 기본 사항에 대한 질문을 게시했습니다 프로세스간에 핵심 데이터 저장소 공유.

주어진 권장 사항을 구현하려고 노력하고 있으며 문제가 발생합니다.

내 목표

Helper App과 UI의 두 가지 프로세스가 있습니다. 둘 다 단일 데이터 저장소를 공유합니다. Helper 앱이 새로운 데이터를 매장에 저장했을 때 UI가 NSmanagedObjectContext를 업데이트하기를 원합니다.

현재 프로그램 흐름

  1. 도우미 앱 프로세스는 데이터를 매장에 씁니다.

  2. 헬퍼 앱에서는 nsmanagedObjectContextDidSavenotification 알림을 듣습니다.

  3. 컨텍스트가 저장되면 URI 표현 및 NSARCHIVER를 사용하여 삽입, 삭제 및 업데이트 된 객체를 인코딩합니다.

  4. 이 인코딩 된 사전을 userInfo로 NSDiptributedNotificationCenter에 NSNotification을 보냅니다.

  5. UI 프로세스는 저장 알림을 듣고 있습니다. 알림을 받으면 nsunarchiver를 사용하여 userinfo를 구제하지 않습니다.

  6. 주어진 URI에서 업데이트 된/삽입/삭제 된 객체를 모두 찾아 NsmanagedObjects로 대체합니다.

  7. 업데이트 된/삽입/삭제 된 객체와 함께 NSNotification을 구성합니다.

  8. 나는 mergechangesfromcontextDidsavenotification을 호출합니다. UI 프로세스의 관리 된 객체 컨텍스트에서 이전 단계에서 구성된 nsnotification을 통과합니다.

문제

삽입 된 객체는 UI 관리 객체 컨텍스트에 대해 결함이 있으며 UI에 나타납니다. 문제는 업데이트 된 객체와 함께 제공됩니다. 그들은 단지 업데이트하지 않습니다.

내가 시도한 것

  1. 가장 분명한 것은 헬퍼 앱 프로세스에서 UI 프로세스로 저장 알림을 전달하는 것입니다. 쉽지? 음 ... 아니. userinfo 사전이 올바른 형식이 아니기 때문에 분산 알림은이를 수행 할 수 없습니다. 그것이 내가 모든 nsarchiving 일을하고있는 이유입니다.

  2. 나는 nsmanagedObjects에서 업데이트 될 nmanagedObjects에서 refreshObject : mergechanges를 호출하려고 시도했지만 이것은 효과가없는 것 같습니다.

  3. 메인 스레드와 현재 스레드에서 MergechangesfromcontextDidsavenotification : 선택기를 수행하려고 시도했습니다. 결과에 영향을 미치지 않는 것 같습니다.

  4. 나는 mergechangesfromcontextDidsavenotification을 사용해 보았습니다. 스레드 사이에, 물론 훨씬 더 단순하고 완벽하게 작동했습니다. 그러나 프로세스간에 동일한 기능이 필요합니다.

대안?

내가 여기서 뭔가를 놓치고 있습니까? 나는 필요한 것보다 훨씬 더 복잡해지는 느낌을 지속적으로 이해하고 있지만 문서를 여러 번 읽고 며칠을 며칠을 보낸 후에는 MOC를 새로 고치는 다른 방법을 볼 수 없습니다. UI.

더 우아한 방법이 있습니까? 아니면 내 코드 어딘가에 어리석은 실수를하고 있습니까?

코드

나는 그것을 가능한 한 읽을 수있게 만들려고 노력했지만 여전히 엉망입니다. 죄송합니다.

도우미 앱 코드

   -(void)workerThreadObjectContextDidSave:(NSNotification *)saveNotification {
        NSMutableDictionary *savedObjectsEncodedURIs = [NSMutableDictionary dictionary];
        NSArray *savedObjectKeys = [[saveNotification userInfo] allKeys];

        for(NSString *thisSavedObjectKey in savedObjectKeys) {
            // This is the set of updated/inserted/deleted NSManagedObjects.
            NSSet *thisSavedObjectSet = [[saveNotification userInfo] objectForKey:thisSavedObjectKey];
            NSMutableSet *thisSavedObjectSetEncoded = [NSMutableSet set];

            for(id thisSavedObject in [thisSavedObjectSet allObjects]) {
                // Construct a set of URIs that will be encoded as NSData
                NSURL *thisSavedObjectURI = [[(NSManagedObject *)thisSavedObject objectID] URIRepresentation];
                [thisSavedObjectSetEncoded addObject:thisSavedObjectURI];
            }
            // Archive the set of URIs.
            [savedObjectsEncodedURIs setObject:[NSArchiver archivedDataWithRootObject:thisSavedObjectSetEncoded] forKey:thisSavedObjectKey];
        }

        if ([[savedObjectsEncodedURIs allValues] count] > 0) {
            // Tell UI process there are new objects that need merging into it's MOC
            [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"com.synapticmishap.lapsus.save" object:@"HelperApp" userInfo:(NSDictionary *)savedObjectsEncodedURIs];
        }
    }

UI 코드

-(void)mergeSavesIntoMOC:(NSNotification *)notification {
    NSDictionary        *objectsToRefresh        = [notification userInfo];
    NSMutableDictionary *notificationUserInfo    = [NSMutableDictionary dictionary];
    NSArray *savedObjectKeys = [[notification userInfo] allKeys];

    for(NSString *thisSavedObjectKey in savedObjectKeys) {
        // Iterate through all the URIs in the decoded set. For each URI, get the NSManagedObject and add it to a set.
        NSSet *thisSavedObjectSetDecoded = [NSUnarchiver unarchiveObjectWithData:[[notification userInfo] objectForKey:thisSavedObjectKey]];
        NSMutableSet *savedManagedObjectSet = [NSMutableSet set];

        for(NSURL *thisSavedObjectURI in thisSavedObjectSetDecoded) {
            NSManagedObject *thisSavedManagedObject = [managedObjectContext objectWithID:[persistentStoreCoordinator managedObjectIDForURIRepresentation:thisSavedObjectURI]];
            [savedManagedObjectSet addObject:thisSavedManagedObject];
            // If the object is to be updated, refresh the object and merge in changes.
            // This doesn't work!
            if ([thisSavedObjectKey isEqualToString:NSUpdatedObjectsKey]) {
                [managedObjectContext refreshObject:thisSavedManagedObject mergeChanges:YES];
                [managedObjectContext save:nil];
            }
        }
        [notificationUserInfo setObject:savedManagedObjectSet forKey:thisSavedObjectKey];
    }
    // Build a notification suitable for merging changes into MOC.
    NSNotification *saveNotification = [NSNotification notificationWithName:@"" object:nil userInfo:(NSDictionary *)notificationUserInfo];
    [managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                    withObject:saveNotification
                                 waitUntilDone:YES];
}
도움이 되었습니까?

해결책

당신은 - (void) refreshObject를 찾고 있습니다 : (nsmanagedObject *) 객체 합병 : (bool) 플래그 나는 믿습니다.

이렇게하면 영구 저장소의 정보가 포함 된 객체를 새로 고치고 원하는 경우 변경 사항을 병합합니다.

다른 팁

나는 방법을 사용했다

http://www.mlsite.net/blog/?p=518

그러면 모든 객체가 올바르게 결함이 있지만 결함이 캐시에 가져 오므로 여전히 업데이트되지 않습니다.

나는 [moc stalenessinterval = 0]를해야했다.

그리고 그것은 마침내 관계와 함께 일했습니다.

나는 Mike의 제안과 함께 가서 변경 사항을 위해 상점 파일을 보았습니다.

가장 효율적이지는 않지만 성공을 거두었습니다. - [NSManagedObjectContext reset] 상점이 변경 될 때 두 번째 프로세스에서. 내 경우, 코드는 상당히 선형입니다. 재설정 후 일부 데이터에 대한 페치 요청을 실행하는 것입니다. 이것이 바인딩과 복잡한 UI로 어떻게 작동하는지 모르겠지만 자동으로 처리되지 않으면 물건을 수동으로 업데이트하기 위해 알림을 게시 할 수 있습니다.

나는 내가 작업 한 iPhone 앱과 똑같은 문제를 가졌다. 필자의 경우 솔루션은 컨텍스트의 Stalenessinterval을 적절한 무한대 (예 : 0.5 초)로 설정하는 것이 포함되었습니다.

이것은 샌드 박스 앱을 제외하고는 작동합니다. 사용자 정보 표시로 알림을 보낼 수 없습니다. 대신 XPC와 같은 다른 IPC를 고려하거나 DO를 고려하십시오.

참고로, NSDURTURIBEDNOTIFICECENTER를 사용하는 것이 시스템이 바쁘다면 항상 100%는 아닙니다.

관리되는 객체 컨텍스트의 Stalenessinterval 설정이 작동합니다. 내 사례에는 프로세스 대신 여러 스레드가 포함됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top