2

I create/update contacts, using CNMutableContact. I can set new image via imageData property, but I need to set custom crop information for creating thumbnail. Property thumbnailImageData is read-only.

Code:

let cnContact = CNMutableContact()
cnContact.imageData = imageData //created before

How to add custom thumbnailImage crop?

Igor
  • 12,165
  • 4
  • 57
  • 73

1 Answers1

2

It seems that setting a thumbnail is not possible in iOS. However, by definition, a thumbnail of an image is the same image cropped to a smaller dimension. Hence iOS will auto generate the thumbnail from the image data set on the contact while saving the contact.

If you want to setup a different images for thumbnail and actual contact image, iOS will not allow you to do this.

Problem I have:

Before adding a new contact (CNMutableContact reference) in the user's contacts, I want to display the contact to the user. I can use the imageData to setup the new contact's image. However, when using CNContactViewController to display this new contact, the image is not cropped as per thumbnail. The thumbnail image showed looks super weird and scaled. How to resolve this?

Solution:

This occurs because the thumbnailImageData property on the CNMutableContact object is nil. This property cannot be set by the developers. This property can only be set by iOS internals and is auto generated by iOS while saving the contact.

So, before displaying the CNMutableContact object, you should save it to the users contacts, to kick in the auto-thumbnail-generation, and then immediately delete the contact.

The following extension on CNMutableContact depicts what you can do to achieve this.

extension CNMutableContact {
    func generateThumbnailImage() {
        if self.thumbnailImageData != nil {
            return
        }

        // contact.thumbnailImageData is nil
        // First save the contact for the thumbnail to be generated

        let saveRequest = CNSaveRequest()
        saveRequest.add(self, toContainerWithIdentifier: nil)
        do {
            try CNContactStore().execute(saveRequest)
        } catch let error {
            print("Error occurred while saving the request \(error)")
        }

        // self.thumbnailImageData is not nil. Contact Store will generate the thumbnail for this contact with the imageData provided.
        // Now delete the contact
        let deleteRequest = CNSaveRequest()
        deleteRequest.delete(self)
        do {
            try CNContactStore().execute(deleteRequest)
        } catch let error  {
            print("Error occurred while deleting the request \(error)")
        }

        // The contact is removed from the Contact Store
        // However, the contact.thumbnailImageData is not nil anymore. Contacts Store has generated the thumbnail automatically with the imageData provided.
    }
}
Dunes Buggy
  • 1,779
  • 1
  • 21
  • 41
  • Thanks, @iRavi, but I don't understand, how to get a goal. Could you share code? It's still actual for me. – Igor Apr 30 '17 at 23:21
  • @Igor added the code. Please note, this solution is only for generating the thumbnail information with iOS, but not to set the thumbnail information. Hopefully this helps you. – Dunes Buggy Apr 30 '17 at 23:45
  • But, I think, if I change imageData, will be generated new thumbnailImageData. I need to store image for contact and create thumbnailImageData from another area, than this do autogenerator. Do you found a way to do that? I'm sorry, if I still misunderstand you. – Igor Apr 30 '17 at 23:55
  • @Igor I think we need may have a different use case, hence the confusion. Just to clarify, its currently not possible to set the thumbnailImageData for a contact in iOS. Edited my answer to explain my use case and solution. – Dunes Buggy May 01 '17 at 01:01
  • I have another case. I need only to change crop position of thumbnail image programmatically (how user can change it via embed Contacts app). But, I think it's impossible. – Igor May 01 '17 at 13:18
  • @Igor Umm, I don't think thats possible directly. However, you can use your custom view to allow the user to setup the crop position, similar to that on the contacts app. You can generate (programmatically) a new image with this crop information, with the remaining pixels (outside the crop) transparent. Then set this new image on the contact instead. Let me know if that helps. – Dunes Buggy May 01 '17 at 14:52
  • @iRaviiVooda Will you please let me know what this `Manager` is? – The iOSDev Jan 23 '19 at 06:50
  • @TheiOSDev. Sorry Manager was just my internal constants. But to clarify: `Manager.contactsStore` returns `CNContactStore()`. I will update my code in the answer as well – Dunes Buggy Jan 23 '19 at 20:45
  • @iRaviiVooda thansk for your reply I just don't understands why this method gives me error like `Error occurred while saving the request Error Domain=CNErrorDomain Code=1 "Communication Error" UserInfo={NSLocalizedDescription=Communication Error, NSLocalizedFailureReason=An error occurred while trying to communicate with the Contacts service.}` – The iOSDev Jan 24 '19 at 06:38