-
-
Save arytbk/9c7560720e43c786c801 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// | |
// Contact.swift | |
// FriendLender | |
// | |
// Created by Logan Wright on 9/22/14. | |
// Copyright (c) 2014 lowriDevs. All rights reserved. | |
// | |
import UIKit | |
import AddressBookr | |
// MARK: Debugging | |
private let ContactDebug = false | |
// MARK: NSCoding Constants | |
private let ContactFirstNameKey = "firstNameKey" | |
private let ContactFirstNamePhoneticKey = "firstNamePhoneticKey" | |
private let ContactMiddleNameKey = "middleNameKey" | |
private let ContactMiddleNamePhoneticKey = "middleNamePhoneticKey" | |
private let ContactLastNameKey = "lastNameKey" | |
private let ContactLastNamePhoneticKey = "lastNamePhoneticKey" | |
private let ContactPrefixKey = "prefixKey" | |
private let ContactSuffixKey = "suffixKey" | |
private let ContactNicknameKey = "nicknameKey" | |
private let ContactBirthDateKey = "birthDateKey" | |
private let ContactCreationDateKey = "creationDateKey" | |
private let ContactModificationDateKey = "modificationDateKey" | |
private let ContactOrganizationKey = "organizationKey" | |
private let ContactJobTitleKey = "jobTitleKey" | |
private let ContactDepartmentKey = "departmentKey" | |
private let ContactPhoneNumbersKey = "phoneNumbersKey" | |
private let ContactEmailsKey = "emailsKey" | |
private let ContactNoteKey = "noteKey" | |
// MARK: Contact Class | |
class Contact: NSObject, NSCoding { | |
// MARK: Names | |
var firstName: String? | |
var firstNamePhonetic: String? | |
var middleName: String? | |
var middleNamePhonetic: String? | |
var lastName: String? | |
var lastNamePhonetic: String? | |
var prefix: String? // Prefix ("Sir" "Duke" "General") - kABStringPropertyType | |
var suffix: String? // Suffix ("Jr." "Sr." "III") - kABStringPropertyType | |
var nickname: String? | |
var fullName: String? { | |
get { | |
var fullName: String = "" | |
if let firstName = self.firstName { | |
fullName += firstName | |
} | |
if let lastName = self.lastName { | |
if countElements(fullName) > 0 { | |
fullName += " " | |
} | |
fullName += lastName | |
} | |
return countElements(fullName) > 0 ? fullName : nil | |
} | |
} | |
// MARK: Dates | |
var birthDate: NSDate? | |
var creationDate: NSDate? | |
var modificationDate: NSDate? | |
// MARK: Work | |
var organization: String? | |
var jobTitle: String? | |
var department: String? | |
// MARK: Contact Information | |
var phoneNumbers: PhoneNumbers? | |
var emails: Emails? | |
// MARK: Additional Info | |
var note: String? | |
// MARK: Initialization | |
init(recordRef: ABRecordRef) { | |
super.init() | |
self.initializeNamesWithABRecordRef(recordRef) | |
self.initializeWorkInfoWithABRecordRef(recordRef) | |
self.initializeCreationInfoWithABRecordRef(recordRef) | |
self.birthDate = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonBirthdayProperty) as? NSDate | |
self.note = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonNoteProperty) as? String | |
if let phonesRef: Unmanaged<AnyObject> = ABRecordCopyValue(recordRef, kABPersonPhoneProperty){ | |
self.phoneNumbers = PhoneNumbers(phoneNumbersRef: phonesRef.takeRetainedValue() as ABMultiValueRef) | |
} | |
if let emailRef: Unmanaged<AnyObject> = ABRecordCopyValue(recordRef, kABPersonEmailProperty){ | |
self.emails = Emails(emailsRef: emailRef.takeRetainedValue() as ABMultiValueRef) | |
} | |
} | |
func initializeNamesWithABRecordRef(recordRef: ABRecordRef) { | |
self.firstName = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonFirstNameProperty) as? String | |
self.firstNamePhonetic = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonFirstNamePhoneticProperty) as? String | |
self.lastName = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonLastNameProperty) as? String | |
self.lastNamePhonetic = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonLastNamePhoneticProperty) as? String | |
self.middleName = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonMiddleNameProperty) as? String | |
self.middleNamePhonetic = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonMiddleNamePhoneticProperty) as? String | |
self.prefix = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonPrefixProperty) as? String | |
self.suffix = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonSuffixProperty) as? String | |
self.nickname = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonNicknameProperty) as? String | |
} | |
func initializeWorkInfoWithABRecordRef(recordRef: ABRecordRef) { | |
self.organization = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonOrganizationProperty) as? String | |
self.jobTitle = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonJobTitleProperty) as? String | |
self.department = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonDepartmentProperty) as? String | |
} | |
func initializeCreationInfoWithABRecordRef(recordRef: ABRecordRef) { | |
self.creationDate = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonCreationDateProperty) as? NSDate | |
self.modificationDate = self.rawValueFromABRecordRef(recordRef, forProperty: kABPersonModificationDateProperty) as? NSDate | |
} | |
// MARK: Getting Properties From RecordRef | |
// @arytbk fixed crash when value is nil with Xcode 6.3 Beta 3 | |
func rawValueFromABRecordRef(recordRef: ABRecordRef, forProperty property: ABPropertyID) -> AnyObject? { | |
if let val = ABRecordCopyValue(recordRef, property) { | |
return val.takeRetainedValue() | |
} else { | |
return nil | |
} | |
} | |
// MARK: NSCoding | |
func encodeWithCoder(aCoder: NSCoder) { | |
if firstName != nil {aCoder.encodeObject(firstName!, forKey: ContactFirstNameKey)} | |
if firstNamePhonetic != nil {aCoder.encodeObject(firstNamePhonetic!, forKey: ContactFirstNamePhoneticKey)} | |
if middleName != nil {aCoder.encodeObject(middleName!, forKey: ContactMiddleNameKey)} | |
if middleNamePhonetic != nil {aCoder.encodeObject(middleNamePhonetic!, forKey: ContactMiddleNamePhoneticKey)} | |
if lastName != nil {aCoder.encodeObject(lastName!, forKey: ContactLastNameKey)} | |
if lastNamePhonetic != nil {aCoder.encodeObject(lastNamePhonetic!, forKey: ContactLastNamePhoneticKey)} | |
if prefix != nil {aCoder.encodeObject(prefix!, forKey: ContactPrefixKey)} | |
if suffix != nil {aCoder.encodeObject(suffix!, forKey: ContactSuffixKey)} | |
if nickname != nil {aCoder.encodeObject(nickname!, forKey: ContactNicknameKey)} | |
if birthDate != nil {aCoder.encodeObject(birthDate!, forKey: ContactBirthDateKey)} | |
if creationDate != nil {aCoder.encodeObject(creationDate!, forKey: ContactCreationDateKey)} | |
if modificationDate != nil {aCoder.encodeObject(modificationDate!, forKey: ContactModificationDateKey)} | |
if organization != nil {aCoder.encodeObject(organization!, forKey: ContactOrganizationKey)} | |
if jobTitle != nil {aCoder.encodeObject(jobTitle!, forKey: ContactJobTitleKey)} | |
if department != nil {aCoder.encodeObject(department!, forKey: ContactDepartmentKey)} | |
if phoneNumbers != nil {aCoder.encodeObject(phoneNumbers!, forKey: ContactPhoneNumbersKey)} | |
if emails != nil {aCoder.encodeObject(emails!, forKey: ContactEmailsKey)} | |
if note != nil {aCoder.encodeObject(note!, forKey: ContactNoteKey)} | |
} | |
required init(coder aDecoder: NSCoder) { | |
self.firstName = aDecoder.decodeObjectForKey(ContactFirstNameKey) as? String | |
self.firstNamePhonetic = aDecoder.decodeObjectForKey(ContactFirstNamePhoneticKey) as? String | |
self.middleName = aDecoder.decodeObjectForKey(ContactMiddleNameKey) as? String | |
self.middleNamePhonetic = aDecoder.decodeObjectForKey(ContactMiddleNamePhoneticKey) as? String | |
self.lastName = aDecoder.decodeObjectForKey(ContactLastNameKey) as? String | |
self.lastNamePhonetic = aDecoder.decodeObjectForKey(ContactLastNamePhoneticKey) as? String | |
self.prefix = aDecoder.decodeObjectForKey(ContactPrefixKey) as? String | |
self.suffix = aDecoder.decodeObjectForKey(ContactSuffixKey) as? String | |
self.nickname = aDecoder.decodeObjectForKey(ContactNicknameKey) as? String | |
self.birthDate = aDecoder.decodeObjectForKey(ContactBirthDateKey) as? NSDate | |
self.creationDate = aDecoder.decodeObjectForKey(ContactCreationDateKey) as? NSDate | |
self.modificationDate = aDecoder.decodeObjectForKey(ContactModificationDateKey) as? NSDate | |
self.organization = aDecoder.decodeObjectForKey(ContactOrganizationKey) as? String | |
self.jobTitle = aDecoder.decodeObjectForKey(ContactJobTitleKey) as? String | |
self.department = aDecoder.decodeObjectForKey(ContactDepartmentKey) as? String | |
self.phoneNumbers = aDecoder.decodeObjectForKey(ContactPhoneNumbersKey) as? PhoneNumbers | |
self.emails = aDecoder.decodeObjectForKey(ContactEmailsKey) as? Emails | |
self.note = aDecoder.decodeObjectForKey(ContactNoteKey) as? String | |
} | |
} | |
// MARK: Emails Class NSCoding Constants | |
private let EmailsHomeKey = "EmailsHomeKey" | |
private let EmailsWorkKey = "EmailsWorkKey" | |
private let EmailsOtherKey = "EmailsOtherKey" | |
private let EmailsUnknownEmailsKey = "EmailsUnknownEmailsKey" | |
// MARK: Emails | |
class Emails: NSObject, NSCoding { | |
// MARK: Public Properties | |
var home: String? | |
var work: String? | |
var other: String? | |
var unknownEmails: [String : String] = [:] | |
var bestEmail: String? { | |
get { | |
var bestEmail: String? | |
if let home = home { | |
bestEmail = home | |
} else if let work = work { | |
bestEmail = work | |
} else if let other = other { | |
bestEmail = other | |
} else if unknownEmails.count > 0 { | |
bestEmail = unknownEmails.values.first | |
} | |
return bestEmail | |
} | |
} | |
// MARK: Initialization | |
init(emailsRef: ABMultiValueRef) { | |
super.init() | |
for i in 0..<ABMultiValueGetCount(emailsRef) { | |
let emailKey = (ABMultiValueCopyLabelAtIndex(emailsRef, i).takeRetainedValue() as CFStringRef) | |
let emailValue = ABMultiValueCopyValueAtIndex(emailsRef, i).takeRetainedValue() as String | |
if emailKey == kABHomeLabel { | |
home = emailValue | |
} | |
else if emailKey == kABWorkLabel { | |
work = emailValue | |
} | |
else if emailKey == kABOtherLabel { | |
other = emailValue | |
} | |
else { | |
if ContactDebug {println("UnknownEmailKey: \(emailKey) Val: \(emailValue)")} | |
/* | |
I implemented all of the available keys as well as Home, not sure if other keys exist. Just in case, I store unexpected values here. | |
*/ | |
unknownEmails[emailKey] = emailValue | |
} | |
if ContactDebug { | |
println("EmailKey: \(emailKey)") | |
println("EmailVal: \(emailValue)") | |
} | |
} | |
} | |
// MARK: NSCoding | |
func encodeWithCoder(aCoder: NSCoder) { | |
if home != nil {aCoder.encodeObject(home!, forKey: EmailsHomeKey)} | |
if work != nil {aCoder.encodeObject(work!, forKey: EmailsWorkKey)} | |
if other != nil {aCoder.encodeObject(other!, forKey: EmailsOtherKey)} | |
if unknownEmails.count > 0 {aCoder.encodeObject(unknownEmails, forKey: EmailsUnknownEmailsKey)} | |
} | |
required init(coder aDecoder: NSCoder) { | |
home = aDecoder.decodeObjectForKey(EmailsHomeKey) as? String | |
work = aDecoder.decodeObjectForKey(EmailsWorkKey) as? String | |
other = aDecoder.decodeObjectForKey(EmailsOtherKey) as? String | |
if let decodedUnknownEmails = aDecoder.decodeObjectForKey(EmailsUnknownEmailsKey) as? [String : String] { | |
unknownEmails = decodedUnknownEmails | |
} | |
} | |
} | |
// MARK: Phone Numbers Class NSCoding Constants | |
private let PhoneNumbersMobileKey = "PhoneNumbersMobileKey" | |
private let PhoneNumbersIPhoneKey = "PhoneNumbersIPhoneKey" | |
private let PhoneNumbersMainKey = "PhoneNumbersMainKey" | |
private let PhoneNumbersFaxHomeKey = "PhoneNumbersFaxHomeKey" | |
private let PhoneNumbersFaxWorkKey = "PhoneNumbersFaxWorkKey" | |
private let PhoneNumbersFaxOtherKey = "PhoneNumbersFaxOtherKey" | |
private let PhoneNumbersPagerKey = "PhoneNumbersPagerKey" | |
private let PhoneNumbersHomeKey = "PhoneNumbersHomeKey" | |
private let PhoneNumbersUnknownNumbersKey = "PhoneNumbersUnknownNumbersKey" | |
// MARK: PhoneNumbers | |
class PhoneNumbers: NSObject, NSCoding { | |
// MARK: Public Properties | |
var mobile: String? | |
var iPhone: String? | |
var main: String? | |
var home: String? | |
var faxHome: String? | |
var faxWork: String? | |
var faxOther: String? | |
var pager: String? | |
var unknownNumbers: [String : String] = [:] | |
var bestTextNumber: String? { | |
get { | |
var textNumber: String? | |
if let iPhone = iPhone { | |
textNumber = iPhone | |
} else if let mobile = mobile { | |
textNumber = mobile | |
} else if let main = main { | |
textNumber = main | |
} | |
return textNumber | |
} | |
} | |
var bestPhoneNumber: String? { | |
get { | |
var phoneNumber: String? | |
if let iPhone = iPhone { | |
phoneNumber = iPhone | |
} else if let mobile = mobile { | |
phoneNumber = mobile | |
} else if let main = main { | |
phoneNumber = main | |
} else if let home = home { | |
phoneNumber = home | |
} | |
return phoneNumber | |
} | |
} | |
// MARK: Initialization | |
init(phoneNumbersRef: ABMultiValueRef) { | |
super.init() | |
for i in 0..<ABMultiValueGetCount(phoneNumbersRef) { | |
let phoneNumberKey = (ABMultiValueCopyLabelAtIndex(phoneNumbersRef, i).takeRetainedValue() as CFStringRef) | |
let phoneNumberValue = ABMultiValueCopyValueAtIndex(phoneNumbersRef, i).takeRetainedValue() as String | |
if phoneNumberKey == kABPersonPhoneMobileLabel { | |
self.mobile = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhoneIPhoneLabel { | |
self.iPhone = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhoneMainLabel { | |
self.main = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhoneHomeFAXLabel { | |
self.faxHome = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhoneWorkFAXLabel { | |
self.faxWork = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhoneOtherFAXLabel { | |
self.faxOther = phoneNumberValue; | |
} | |
else if phoneNumberKey == kABPersonPhonePagerLabel { | |
self.pager = phoneNumberValue | |
} | |
else if phoneNumberKey == "_$!<Home>!$_" { | |
self.home = phoneNumberValue | |
} | |
else { | |
if ContactDebug {println("UnknownPhoneNumberKey: \(phoneNumberKey) Val: \(phoneNumberValue)")} | |
/* | |
I implemented all of the available keys as well as Home, not sure if other keys exist. Just in case, I store unexpected values here. | |
*/ | |
unknownNumbers[phoneNumberKey] = phoneNumberValue | |
} | |
if ContactDebug { | |
println("PhoneNumberKey: \(phoneNumberKey)") | |
println("PhoneNumberVal: \(phoneNumberValue)") | |
} | |
} | |
} | |
// MARK: NSCoding | |
func encodeWithCoder(aCoder: NSCoder) { | |
if mobile != nil {aCoder.encodeObject(mobile!, forKey: PhoneNumbersMobileKey)} | |
if iPhone != nil {aCoder.encodeObject(iPhone!, forKey: PhoneNumbersIPhoneKey)} | |
if main != nil {aCoder.encodeObject(main!, forKey: PhoneNumbersMainKey)} | |
if faxHome != nil {aCoder.encodeObject(faxHome!, forKey: PhoneNumbersFaxHomeKey)} | |
if faxWork != nil {aCoder.encodeObject(faxWork!, forKey: PhoneNumbersFaxWorkKey)} | |
if faxOther != nil {aCoder.encodeObject(faxOther!, forKey: PhoneNumbersFaxOtherKey)} | |
if pager != nil {aCoder.encodeObject(pager!, forKey: PhoneNumbersPagerKey)} | |
if home != nil {aCoder.encodeObject(home!, forKey: PhoneNumbersHomeKey)} | |
if unknownNumbers.count > 0 {aCoder.encodeObject(unknownNumbers, forKey: PhoneNumbersUnknownNumbersKey)} | |
} | |
required init(coder aDecoder: NSCoder) { | |
mobile = aDecoder.decodeObjectForKey(PhoneNumbersMobileKey) as? String | |
iPhone = aDecoder.decodeObjectForKey(PhoneNumbersIPhoneKey) as? String | |
main = aDecoder.decodeObjectForKey(PhoneNumbersMainKey) as? String | |
faxHome = aDecoder.decodeObjectForKey(PhoneNumbersFaxHomeKey) as? String | |
faxWork = aDecoder.decodeObjectForKey(PhoneNumbersFaxWorkKey) as? String | |
faxOther = aDecoder.decodeObjectForKey(PhoneNumbersFaxOtherKey) as? String | |
pager = aDecoder.decodeObjectForKey(PhoneNumbersPagerKey) as? String | |
home = aDecoder.decodeObjectForKey(PhoneNumbersHomeKey) as? String | |
if let decodedUnknownNumbersDict = aDecoder.decodeObjectForKey(PhoneNumbersUnknownNumbersKey) as? [String : String] { | |
unknownNumbers = decodedUnknownNumbersDict | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I just fixed the crash when finding a nil value with Xcode 6.3 beta 3.