Share Extension

Dear all,

How can i build extension for ios 8 contacts ios app?

Thank you.

Rana

Accepted Answer

Hi Viva


The iOS contacts app shares a vCard representation of the selected contact. Your share extension will appear in the list of available activities for a shared contact if your share extension contains an activation rule that matches on attachments conforming to the public.vcard Uniform Type Identifier. Here is an example activation rule that matches on one or more vCards:


<key>NSExtension</key>

<dict>

<key>NSExtensionAttributes</key>

<dict>

<key>NSExtensionActivationRule</key>

<string>

SUBQUERY (

extensionItems, $extensionItem,

SUBQUERY (

$extensionItem.attachments, $attachment,

ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.vcard"

).@count >= 1

).@count > 0

</string>

</dict>


When the your share extension has loaded, its extension context's inputItems will contain an NSItemProvider that can be used to retrieve the serialized vCard data. Once you have retrieved the vCard data as an instance of NSData from the NSItemProvider, you can use the -contactsWithData:error: method of CNContactVCardSerialization to decode the data into an array of CNContact objects.


for (NSExtensionItem *item in self.extensionContext.inputItems) {

for (NSItemProvider *provider in item.attachments) {

if ([provider hasItemConformingToTypeIdentifier:kUTTypeVCard]) {

[provider loadItemForTypeIdentifier:kUTTypeVCard options:nil completionHandler:^(NSData *vCardData, NSError *error) {

NSArray *contacts = [CNContactVCardSerialization contactsWithData:vCardData error:nil];

for (CNContact *contact in contacts) {

/ Do something with contact */

}

}];

}

}

}


More information about declaring the types supported by a Share extension and writing custom activation rules can be found in the "Declaring Supported Data Types for a Share or Action Extension" section of the App Extension Programming Guide <https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html> and the Predicate Programming Guide <https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html>


More information about Uniform Type Identifier can be found in the Uniform Type Identifiers Overview <https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_intro/understand_utis_intro.html> and the System-Declared Uniform Type Identifiers <https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html>

Thank you so much, it's working now.

Hello, how is this implemented in Swift/iOS 10? I'm trying to write an action extenion in 10.6 for when the user shares the contact from phone app's recent call history.


If I implement this for example:


for item in self.extensionContext!.inputItems as! [NSExtensionItem]
        {
            for provider in item.attachments! as! [NSItemProvider]
            {
                if provider.hasItemConformingToTypeIdentifier(kUTTypeVCard as String)
                {
                    provider.loadItem(forTypeIdentifier:  kUTTypeVCard as String, options: nil, completionHandler: { (contactData, error) in
                        OperationQueue.main.addOperation
                        {



Then the type of contactData is not NSData as in your obejctive C example but NSSecureCoding. I can't see any vCard related method of CNContact using NSSecureCoding. However there is CNContact.init(NSCoding), so I tried to change the above code to this:


for item in self.extensionContext!.inputItems as! [NSExtensionItem]
        {
            for provider in item.attachments! as! [NSItemProvider]
            {
                if provider.hasItemConformingToTypeIdentifier(kUTTypeContact as String)
                {
                    provider.loadItem(forTypeIdentifier: kUTTypeContact as String, options: nil, completionHandler: { (contactCoder, error) in
                        OperationQueue.main.addOperation
                        {
                            if error == nil
                            {
                                if let contactCoder = contactCoder
                                {
                                    if let theContact = CNContact(coder: contactCoder)
                                    {
                                        let givenName = theContact.givenName


But this does not compile as there is an error about not being able to convert NSSecureCoding to NSCoder. But if the CNContact instantiation is changed to this

let theContact = CNContact(coder: contactCoder as! NSCoder)

t

hen there is a dynamic cast runtime exception when that line is executed.


So what is the correct way to obtain the contact from the call history in an action extension in iOS 10.6 with Swift?


Thanks

I solved it, I used this:



let theContacts = try CNContactVCardSerialization.contacts(with: contactCoder as! Data)

Share Extension
 
 
Q