Created
July 14, 2016 15:40
-
-
Save ArchieGoodwin/21cf4d49c7fa0c0fdff9a391e77a2fee to your computer and use it in GitHub Desktop.
helper class for Contacts Framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ContactsManager.swift | |
// main | |
// | |
// Created by Nero Wolfe on 14/07/16. | |
// Copyright © 2016 Incoding. All rights reserved. | |
// | |
import UIKit | |
import Contacts | |
public enum Result<T, Error: ErrorType> { | |
case Success(T) | |
case Failure(ContactsError) | |
} | |
public enum ContactsError: ErrorType { | |
case ContactsAccessDenied(message : String) | |
case OtherError(code: Int) | |
case UnexpectedError(message: String) | |
} | |
private let _сontactsManagerSharedInstance = ContactsManager() | |
class ContactsManager: NSObject { | |
var contactStore = CNContactStore() | |
class var sharedInstance: ContactsManager { | |
return _сontactsManagerSharedInstance | |
} | |
func requestForAccess(completionHandler: Result<Bool, NSError> -> Void) { | |
let authorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts) | |
switch authorizationStatus { | |
case .Authorized: | |
completionHandler(Result.Success(true)) | |
case .Denied, .NotDetermined: | |
self.contactStore.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (access, accessError) -> Void in | |
if access { | |
completionHandler(Result.Success(true)) | |
} | |
else { | |
if authorizationStatus == CNAuthorizationStatus.Denied { | |
dispatch_async(dispatch_get_main_queue(), { () -> Void in | |
let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings." | |
completionHandler(Result.Failure(.ContactsAccessDenied(message: message))) | |
}) | |
} | |
} | |
}) | |
default: | |
completionHandler(Result.Success(true)) | |
} | |
} | |
func findContact(firstName : String, lastnName : String) -> CNContact? | |
{ | |
let toFetch = [CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNameSuffixKey] | |
let predicate = CNContact.predicateForContactsMatchingName(firstName + " " + lastnName) | |
var returnContact : CNContact? = nil | |
do{ | |
let contacts = try self.contactStore.unifiedContactsMatchingPredicate(predicate, keysToFetch: toFetch) | |
for contact in contacts | |
{ | |
if contact.nameSuffix == "via Main" | |
{ | |
returnContact = contact | |
break | |
} | |
} | |
} catch let err{ | |
print(err) | |
return nil | |
} | |
return returnContact | |
} | |
func createGroup() -> CNGroup? | |
{ | |
do{ | |
let groups = try self.contactStore.groupsMatchingPredicate(nil) | |
let filteredGroups = groups.filter { $0.name == "Main Contacts" } | |
if filteredGroups.count > 0 | |
{ | |
return filteredGroups[0] | |
} | |
let newGroup = CNMutableGroup(); | |
let saveRequest = CNSaveRequest() | |
newGroup.name = "Main Contacts" | |
saveRequest.addGroup(newGroup, toContainerWithIdentifier: nil) | |
do{ | |
try self.contactStore.executeSaveRequest(saveRequest) | |
print("Successfully added the group") | |
return newGroup | |
} catch let err{ | |
print("Failed to create the group. \(err)") | |
return nil | |
} | |
} | |
catch _ | |
{ | |
return nil | |
} | |
} | |
func loadAllContacts() -> [NSDictionary] | |
{ | |
var contactsArray : [NSDictionary] = [] | |
let keysToFetch = [ | |
CNContactFamilyNameKey, | |
CNContactGivenNameKey, | |
CNContactEmailAddressesKey, | |
CNContactPhoneNumbersKey, | |
CNContactThumbnailImageDataKey, | |
CNContactNameSuffixKey] | |
// Get all the containers | |
var allContainers: [CNContainer] = [] | |
do { | |
allContainers = try contactStore.containersMatchingPredicate(nil) | |
} catch { | |
print("Error fetching containers") | |
} | |
var results: [CNContact] = [] | |
// Iterate all containers and append their contacts to our results array | |
for container in allContainers { | |
let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier) | |
do { | |
let containerResults = try contactStore.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch) | |
results.appendContentsOf(containerResults) | |
} catch { | |
print("Error fetching results for container") | |
} | |
} | |
for contact in results { | |
if contact.familyName.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 && contact.givenName.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 && contact.phoneNumbers.count > 0 | |
{ | |
var phonesArray = Array<Dictionary<String,String>>() | |
for plabel in contact.phoneNumbers { | |
let number = plabel.value as! CNPhoneNumber | |
let label :String = CNLabeledValue.localizedStringForLabel(plabel.label ) | |
let phone = ["label" : label, "phone" : number.stringValue] | |
phonesArray.append(phone) | |
} | |
var emailsArray = Array<Dictionary<String,String>>() | |
for plabel in contact.emailAddresses { | |
print(plabel.label) | |
let eLabel = plabel.label //_$!<Work>!$_ | |
var emailLabel = "Work" | |
if eLabel.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 | |
{ | |
let eLabel2 = eLabel.characters.split("<").map(String.init) //[_$!<, Work>!$_] | |
let eLabel3 = eLabel2[1].characters.split(">").map(String.init) //[Work, >!$_] | |
emailLabel = eLabel3[0] //Work | |
} | |
let email = plabel.value | |
let emailDict = ["label" : emailLabel, "email" : "\(email)" ] | |
emailsArray.append(emailDict) | |
} | |
let person = ["firstname": contact.givenName, "lastname": contact.familyName, "phones" : phonesArray, "emails" : emailsArray, "suffix" : contact.nameSuffix] | |
contactsArray.append(person) | |
} | |
} | |
print("contacts count \(contactsArray.count)") | |
print("contacts \(contactsArray)") | |
return contactsArray | |
} | |
func deleteAllContacts() | |
{ | |
do{ | |
let groups = try self.contactStore.groupsMatchingPredicate(nil) | |
let filteredGroups = groups.filter { $0.name == "Main Contacts" } | |
if filteredGroups.count > 0 | |
{ | |
let predicate = CNContact.predicateForContactsInGroupWithIdentifier(filteredGroups.first!.identifier) | |
let keysToFetch = [CNContactGivenNameKey] | |
let contacts = try self.contactStore.unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch) | |
for contact in contacts | |
{ | |
self.deleteContact(contact) | |
} | |
let saveRequest = CNSaveRequest() | |
saveRequest.deleteGroup(filteredGroups.first!.mutableCopy() as! CNMutableGroup) | |
do { | |
try contactStore.executeSaveRequest(saveRequest) | |
} | |
catch { | |
print("error while deleting group") | |
} | |
} | |
} | |
catch _ | |
{ | |
print("error while deleting group") | |
} | |
} | |
func deleteContact(contact : CNContact) -> Bool | |
{ | |
let req = CNSaveRequest() | |
let mutableContact = contact.mutableCopy() as! CNMutableContact | |
req.deleteContact(mutableContact) | |
do{ | |
try self.contactStore.executeSaveRequest(req) | |
print("Success, You deleted the user") | |
return true | |
} catch let e{ | |
print("Error = \(e)") | |
return false | |
} | |
} | |
func createContact(person : MainContact) | |
{ | |
if !appDelegate.normalExecutionPath() { | |
return | |
} | |
if let c = self.findContact(person.firstname, lastnName: person.lastname) | |
{ | |
self.deleteContact(c) | |
} | |
if let group = self.createGroup() | |
{ | |
let contactData = CNMutableContact() | |
var profType : ProfileType = ProfileType.Basic | |
if let shared = person.profileType | |
{ | |
if shared == "Business" | |
{ | |
profType = ProfileType.Business | |
} | |
if shared == "Social" | |
{ | |
profType = ProfileType.Social | |
} | |
} | |
contactData.givenName = person.firstname | |
contactData.familyName = person.lastname | |
contactData.nameSuffix = "via Main" | |
let phones = helper.phonesForUserAndProfileType(person, profile: profType) | |
if(phones?.count > 0) | |
{ | |
let phonesArray : [Phones] = phones! | |
var phonesToAdd = [CNLabeledValue]() | |
for phone in phonesArray | |
{ | |
if let phoneT = phone.phoneType | |
{ | |
if phoneT.lowercaseString == "mobile" | |
{ | |
let mobilePhone = CNLabeledValue(label: "mobile",value: CNPhoneNumber(stringValue: phone.phone)) | |
phonesToAdd.append(mobilePhone) | |
} | |
if phoneT.lowercaseString == "landline" | |
{ | |
let landlinePhone = CNLabeledValue(label: "landline",value: CNPhoneNumber(stringValue: phone.phone)) | |
phonesToAdd.append(landlinePhone) | |
} | |
} | |
} | |
contactData.phoneNumbers = phonesToAdd | |
} | |
let emails = helper.emailsForUserAndProfileType(person, profile: profType) | |
if(emails?.count > 0) | |
{ | |
let emailsArray : [Emails] = emails! | |
var emailsToAdd = [CNLabeledValue]() | |
for email in emailsArray | |
{ | |
if(email.email != nil) | |
{ | |
let em = CNLabeledValue(label: email.emailType == nil ? CNLabelWork : email.emailType, value: email.email) | |
emailsToAdd.append(em) | |
} | |
} | |
contactData.emailAddresses = emailsToAdd | |
} | |
let request = CNSaveRequest() | |
request.addContact(contactData, toContainerWithIdentifier: nil) | |
request.addMember(contactData, toGroup: group) | |
do{ | |
try self.contactStore.executeSaveRequest(request) | |
print("Successfully added the contact") | |
} catch let err{ | |
print("Failed to save the contact. \(err)") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment