5

Podano wiele pytań dotyczących SO związanych ze słuchaniem wywołania zwrotnego zmiany książki adresowej na iOS. Znane pytanie Address book sync.Uzyskaj usunięty kontakt za pomocą ABAddressBookRegisterExternalChangeCallback lub innego powiadomienia

Ale moje pytanie jest wąskie, tzn. Jak możemy uzyskać, które kontakty zostały usunięte podczas wywołania zwrotnego synchronizacji książki adresowej.

void MyAddressBookExternalChangeCallback (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context) 
{ 
NSLog(@"Changed Detected......"); 
/* 
    NSDate *lastSyncTime = [self gettingLastSyncTime]; 
    // By above time, I could get which contacts are modified(kABPersonModificationDateProperty) 
    // and which contacts are created newly(ABRecordGetRecordID() 
    // But how can I get this contact was DELETED? 
*/ 
} 

Ale ktoś wyczyścił ten problem w Detect what was changed..... W tym celu: (a) Przechowywanie wszystkich identyfikatorów rekordów za pierwszym razem (b) Podczas synchronizacji, sprawdź wszystkie zapisane identyfikatory rekordów z bieżącymi identyfikatorami książki adresowej, aby sprawdzić, czy są one dostępne. Jeśli nie, to załóż, że ma zostać usunięty kontakt (kosztowna operacja).

Moje pytanie: Czy istnieje inny sposób wykrycia skasowanego kontaktu?

Odpowiedz

1

O ile mi wiadomo, jedynym sposobem, aby to zrobić, jest przechowywanie identyfikatorów kontaktu w pewien sposób i sprawdzenie zmodyfikowanych, ponieważ MyAddressBookExternalChangeCallback jest wywoływane tylko wtedy, gdy aplikacja jest aktywna lub znajduje się w tle, więc po jej zakończeniu użytkownik będzie nie można śledzić tych zmian. Oto moja implementacja kontrolera synchronizacji książki adresowej, który po prostu aktualizuje lokalne kontakty z urządzeniami:

// Header.h 
@interface AddressBookSyncController : NSObject 

+ (instancetype)sharedInstance; 
+ (NSString *)archiveFilePath; 

- (void)syncAddressBook; 
- (void)beginObserving; 
- (void)invalidateObserving; 

@end 

// Implementation.m 
NSString *const AddressBookSyncAllKey = @"AddressBookSyncAllKey"; 

@interface AddressBookSyncController() 

@property (nonatomic) ABAddressBookRef addressBook; 
@property (nonatomic) BOOL isObserving; 

@end 

@implementation AddressBookSyncController 

+ (instancetype)sharedInstance 
{ 
    static AddressBookSyncController *instance; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     instance = [AddressBookSyncController new]; 
    }); 

    return instance; 
} 

+ (NSString *)archiveFilePath 
{ 
    // Your archive file path... 
} 

- (void)syncAddressBook 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) return; 

     NSString *archiveFilePath = [AddressBookSyncController archiveFilePath]; 
     BOOL needSyncAllContacts = [[[NSUserDefaults standardUserDefaults] objectForKey:AddressBookSyncAllKey] boolValue]; 
     BOOL archiveExists = [[NSFileManager defaultManager] fileExistsAtPath:archiveFilePath]; 

     if (!needSyncAllContacts && !archiveExists) return; 

     ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil); 
     CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); 
     NSInteger nPeople = ABAddressBookGetPersonCount(addressBook); 
     NSMutableArray *syncContacts = [NSMutableArray arrayWithCapacity:nPeople]; 
     NSMutableArray *archivedContacts = archiveExists ? [[NSKeyedUnarchiver unarchiveObjectWithFile:archiveFilePath] mutableCopy] : [NSMutableArray array]; 

     if (needSyncAllContacts) 
     { 
      NSMutableArray *newContacts = [NSMutableArray array]; 

      for (NSInteger i = 0; i < nPeople; ++i) 
      { 
       ABRecordRef record = CFArrayGetValueAtIndex(allPeople, i); 
       NSInteger recordId = ABRecordGetRecordID(record); 
       NSDate *modificationDate = (__bridge_transfer NSDate *)ABRecordCopyValue(record, kABPersonModificationDateProperty); 
       AddressContact *contact = [[archivedContacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"recordId == %i", recordId]] firstObject]; 

       if (contact && [contact.modificationDate isEqualToDate:modificationDate]) continue; 

       AddressContact *newContact = [AddressContact addressContactWithRecord:record]; 

       [syncContacts addObject:newContact]; 

       if (contact) 
       { 
        NSUInteger idx = [archivedContacts indexOfObject:contact]; 
        if (idx != NSNotFound) 
        { 
         [archivedContacts replaceObjectAtIndex:idx withObject:newContact]; 
        } 
        else 
        { 
         NSLog(nil, @"idx == NSNotFound for syncAddressBook"); 
        } 
       } 
       else 
       { 
        [newContacts addObject:newContact]; 
       } 
      } 

      [archivedContacts addObjectsFromArray:newContacts]; 
     } 
     else 
     { 
      for (NSInteger i = 0, l = archivedContacts.count; i < l; ++i) 
      { 
       AddressContact *contact = [archivedContacts objectAtIndex:i]; 
       ABRecordRef record = ABAddressBookGetPersonWithRecordID(addressBook, (int)contact.recordId); 

       if (!record) continue; 

       NSDate *modificationDate = (__bridge_transfer NSDate *)ABRecordCopyValue(record, kABPersonModificationDateProperty); 

       if ([modificationDate isEqualToDate:contact.modificationDate]) continue; 

       AddressContact *newContact = [AddressContact addressContactWithRecord:record]; 

       [syncContacts addObject:newContact]; 
       [archivedContacts replaceObjectAtIndex:i withObject:newContact]; 
      } 
     } 

     CFRelease(allPeople); 
     CFRelease(addressBook); 

     BOOL result = NO; 

     if ([syncContacts count] != 0) 
     { 
      // Do your logic with contacts 
      result = [NSKeyedArchiver archiveRootObject:archivedContacts toFile:archiveFilePath]; 
     } 

     NSLog(@"Archiving %@", result ? @"Succeed" : @"Failed"); 

     [[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:AddressBookSyncAllKey]; 
     [[NSUserDefaults standardUserDefaults] synchronize]; 
    }); 
} 

- (void)beginObserving 
{ 
    if (self.isObserving || ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) return; 

    self.addressBook = ABAddressBookCreateWithOptions(NULL, nil); 
    ABAddressBookRegisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *)self); 

    self.isObserving = YES; 
} 

- (void)invalidateObserving 
{ 
    if (!self.isObserving) return; 

    ABAddressBookUnregisterExternalChangeCallback(self.addressBook, addressBookChanged, (__bridge void *)self); 
    CFRelease(self.addressBook); 

    self.isObserving = NO; 
} 

void addressBookChanged(ABAddressBookRef reference, CFDictionaryRef dictionary, void *context) 
{ 
    NSLog(@"%@ changed %@", reference, dictionary); 

    ABAddressBookRevert(reference); 

    [(__bridge AddressBookSyncController *)context syncAddressBook]; 
} 

@end 
+0

+1 za Twoje rzeczy. Ale już wspomniałem o linku, który jest taki sam jak twoja odpowiedź. Ale szukam lepszej odpowiedzi. – Mani

Powiązane problemy