Как принудительно включить новый CNContact в локальный CNContainer?

Я пишу приложение, которое сохраняет контактную информацию, полученную через REST и JSON, в контейнер, используя CNContactStore. Я хотел бы, чтобы эти контакты были отделены от любых других учетных записей и хранились только локально на устройстве, но локального хранилища не существует, и я не могу найти способ его создать/активировать?

Я могу получить идентификатор магазина по умолчанию (как настроено на устройстве, например iCloud), используя:

let store = CNContactStore()
let containerID = store.defaultContainerIdentifier()

... и я могу (теоретически) идентифицировать такой локальный контейнер - если он действительно существует:

var allContainers = [CNContainer]()
    do {
        allContainers = try store.containersMatchingPredicate(nil)
        for container in allContainers {
            if container.type == CNContainerType.Local {
                print("Local container is: \(container.identifier)")
                break
            }
        }           
    } catch {
        print("Error fetching containers")
    }

Но локального контейнера не существует. Любые идеи о том, как хранить мои контакты локально или в новом отдельном контейнере?


person pwschulz    schedule 04.01.2016    source источник
comment
После того, как вы отключите синхронизацию контактов из iCloud, описанная выше функция вернет идентификатор локального контейнера. Но я предполагаю, что это не решит ваш вариант использования. (Не могу ожидать, что пользователь будет снова и снова менять настройки iCloud)   -  person Nishant    schedule 01.07.2016
comment
Есть новости по этому поводу? У меня тоже такая же проблема.   -  person Shyam    schedule 19.02.2018
comment
Когда iCloud включен, контакты iCloud используются вместо ваших локальных контактов. Такое поведение является преднамеренным. Apple хочет, чтобы контакты iCloud использовались вместо локальных контактов, чтобы пользователи не получали некоторые контакты, сохраненные на их устройстве, которые не синхронизируются между устройствами.   -  person Peter Johnson    schedule 05.12.2018


Ответы (2)


Это было возможно следующим образом с помощью устаревшего API AB, который все еще может работать как обходной путь:

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions( nil, nil );

ABRecordRef source = ABAddressBookGetSourceWithRecordID( addressBook, kABSourceTypeLocal );

ABRecordRef contact = ABPersonCreateInSource( source );
person Plank    schedule 05.12.2017
comment
Никогда не используйте ABAddressBook, поскольку он уже устарел, когда мы начали этот проект ... но я полагаю, что в противном случае это был бы лучший обходной путь, чем совет пользователю отключить / повторно включить учетные записи контактов (как, например, IBM делает в своем Verse приложение) :) - person pwschulz; 08.12.2017

containersMatchingPredicate(nil) возвращает только контейнер по умолчанию.

У меня аналогичная проблема. Если icloud был настроен, он вернет только контейнер типа CNContainerTypeCardDAV, иначе локальный контейнер.

person Nupur Daddikar    schedule 15.03.2016
comment
Я отправил запрос в Apple по этому поводу. Я заметил, что приложение IBM Verse (почта) помогает пользователям отключать все учетные записи контактов, затем синхронизировать контакты Verse (чтобы сделать их локальными), а затем повторно включать учетные записи контактов... некрасиво. - person pwschulz; 30.03.2016
comment
Это так, как задумано. Когда iCloud включен, концепция локального контейнера больше не существует. Был способ обмануть устройство iOS, заставив его иметь и то, и другое, но это не то, что iOS ожидает от вас, поэтому на него нельзя полагаться. - person Peter Johnson; 31.07.2021