I am trying to create a custom table view cell and use it in my project.Unfortunately I get an error in the delegate method cellForRowAtIndexPath and I really don't understand why
The person class
import Foundation
class Person {
var name = "name"
var imageName = "blank"
init(name:String , image :String){
self.name = name
self.imageName = image
}
}
the custom cell class looks like this :
import UIKit
class personTableViewCell: UITableViewCell {
#IBOutlet var label: UILabel!
#IBOutlet var iamge: UIImageView!
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
And I am using it here:
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecordRef!) {
var arrayItems = ["firstName","lastName","mobileNumber","homeNumber","homeEmail","workEmail","address","city","zip","image"]
var valuesArray = ["","","","","","","","","",""]
var dictionary :NSMutableDictionary = NSMutableDictionary(objects: valuesArray, forKeys: arrayItems )
var firstName: NSString! = Unmanaged<CFString>.fromOpaque(ABRecordCopyValue(person, kABPersonFirstNameProperty).toOpaque()).takeUnretainedValue().__conversion()
var lastName = Unmanaged<CFString>.fromOpaque(ABRecordCopyValue(person, kABPersonLastNameProperty).toOpaque()).takeRetainedValue().__conversion()
dictionary.setObject(firstName, forKey: "firstName")
if lastName == "" {
}
else{
dictionary.setObject(lastName, forKey: "lastName")
}
// println("\(firstName) \(lastName)")
// Unmanaged<CFString>.fromOpaque(ABRecordCopyValue(person, kABPersonPhoneProperty).toOpaque()).takeRetainedValue().__conversion()
let unmanagedPhones = ABRecordCopyValue(person, kABPersonPhoneProperty)
let phones: ABMultiValueRef =
Unmanaged.fromOpaque(unmanagedPhones.toOpaque()).takeUnretainedValue()
as NSObject as ABMultiValueRef
let countOfPhones = ABMultiValueGetCount(phones)
var ct2 = 1
for index in 0..<countOfPhones{
let unmanagedPhone = ABMultiValueCopyValueAtIndex(phones, index)
let phone: String = Unmanaged.fromOpaque(
unmanagedPhone.toOpaque()).takeUnretainedValue() as NSObject as String
if ct2 == 1 {
dictionary.setObject(phone, forKey: "mobileNumber")
ct2 = ct2 + 1
}
else{
dictionary.setObject(phone, forKey: "homeNumber")
}
// println(phone)
}
let unmanangedEmail = ABRecordCopyValue(person, kABPersonEmailProperty)
let emails :ABMultiValueRef = Unmanaged.fromOpaque(unmanangedEmail.toOpaque()).takeUnretainedValue() as NSObject as ABMultiValueRef
//var oneEmail = ABMultiValueCopyValueAtIndex(emails, 0)
//var secEmail = ABMultiValueCopyValueAtIndex(emails, 1)
//var email :String = Unmanaged.fromOpaque(oneEmail.toOpaque()).takeUnretainedValue() as NSObject as String
var workEmail :String = String()
let countOfEmail = ABMultiValueGetCount(emails)
var ct = 1
for index2 in 0..<countOfEmail {
var oneEmail = ABMultiValueCopyValueAtIndex(emails, index2)
var email :String = Unmanaged.fromOpaque(oneEmail.toOpaque()).takeUnretainedValue() as NSObject as String
if ct==1 {
dictionary.setObject(email ,forKey: "homeEmail")
ct++
}
else {
dictionary.setObject(email,forKey:"workEmail")
}
// print("\(email) is the email")
}
if ABPersonHasImageData(person) {
// var imageData : CFDataRef = Unmanaged.fromOpaque(ABPersonCopyImageData(person).toOpaque()).takeUnretainedValue() as CFDataRef
// self.image = UIImage(data: imageData)
// var contactImage :CFData = ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail).takeRetainedValue()
// dictionary.setObject(imageData, forKey: "image")
}
// dictionary.setObject(workEmail,forKey:"workEmail")
var unamangedAddressDictionary = ABRecordCopyValue(person, kABPersonAddressProperty)
let addresses : ABMultiValueRef = Unmanaged.fromOpaque(unamangedAddressDictionary.toOpaque()).takeUnretainedValue() as NSObject as ABMultiValueRef
// var addressDictionary : NSDictionary = Unmanaged.fromOpaque(ABMultiValueCopyValueAtIndex(unamangedAddressDictionary, 0).toOpaque())
var addressDictionary = ABMultiValueCopyValueAtIndex(addresses, 0).takeUnretainedValue() as NSDictionary
if addressDictionary.objectForKey(kABPersonAddressCityKey) == nil {
}
else{
var smth: AnyObject? = addressDictionary.objectForKey(kABPersonAddressCityKey)
// dictionary.setObject(addressDictionary.objectForKey(kABPersonAddressCityKey) , forKey: "city")
// dictionary.setObject(smth, forKey: "city")
dictionary.setValue(addressDictionary.objectForKey(kABPersonAddressCityKey), forKey: "city")
}
if addressDictionary.objectForKey(kABPersonAddressZIPKey) == nil {
}
else {
// dictionary.setObject(addressDictionary.objectForKey(kABPersonAddressZIPKey), forKey: "zip")
dictionary.setValue(addressDictionary.objectForKey(kABPersonAddressZIPKey), forKey: "zip")
}
if addressDictionary.objectForKey(kABPersonAddressStreetKey) == nil {
}
else{
// dictionary.setObject(addressDictionary.objectForKey(kABPersonAddressStreetKey), forKey: "address")
dictionary.setValue(addressDictionary.objectForKey(kABPersonAddressStreetKey), forKey: "address")
}
contactsArray.addObject(dictionary)
// println(contactsArray)
var fullName = firstName + " " + lastName
self.empty = true
var pers : Person = Person(name: fullName, image: "")
self.arrayOfPerson.append(pers)
self.objects.addObject(fullName)
self.tableView?.reloadData()
self.addressBookController.dismissViewControllerAnimated(true, completion: nil)
//println("\(dictionary)")
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell : personTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as personTableViewCell
self.ceva = "mere"
// Configure the cell...
//cell.textLabel.text = self.objects[indexPath.row] as NSString
let person :Person = self.arrayOfPerson[indexPath.row] as Person
cell.label.text = person.name
if self.image != nil {
cell.iamge.image = self.image
}
else {
cell.iamge.image = UIImage(named: "nopicture.png")
}
return cell
}
I get the error when dequeueing it with identifier :
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[UILabel isEqualToString:]:
unrecognized selector sent to instance 0x79e51190'
I set up the identifier correctly and the array from which i get the person is containing items in it
Can you guys help me and tell me where I did wrong?
Any type of advice will be greatly appreciated
Related
This is My Class in which Methods for UITableViewDatasource are overrided to have data as 'Email' in Tableview in a single Cell using UITableViewCell as in code. but these methods don't get executed. Will anybody please help me to fix this isseu ?
import UIKit
var operationViewFlag: Int!
class HomeCellView: UITableViewCell
{
#IBOutlet weak var btn_tablecell_Delete: UIButton!
#IBOutlet weak var btn_tablecell_Edit: UIButton!
#IBOutlet weak var lbl_tablecell_Email: UILabel!
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
#IBOutlet weak var TableView_Mainscreen: UITableView!
#IBOutlet weak var lbl_MainScreen_Title: UILabel!
#IBOutlet weak var btn_Mainscreen_Insert: UIButton!
var databasepath:String!
var arrayStudInfo:NSMutableArray!
// viewDidLoad
override func viewDidLoad()
{
operationViewFlag=1
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
lbl_MainScreen_Title.font = UIFont(name: "HelveticaNeue-Bold", size: 20)
btn_Mainscreen_Insert.layer.cornerRadius = 15
btn_Mainscreen_Insert.layer.borderWidth = 1
btn_Mainscreen_Insert.layer.borderColor = UIColor.brownColor().CGColor
// Variable Intialization
arrayStudInfo = NSMutableArray()
// Process for Creating Opening Database
let filemgr = NSFileManager.defaultManager()
let dirpath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docdir = dirpath[0] as String
databasepath = docdir.stringByAppendingString("StudentDataManipulation.sqlite");
if filemgr.fileExistsAtPath(databasepath as String)
{
let contactDB = FMDatabase(path: databasepath as String)
if contactDB == nil
{
print("Error: \(contactDB.lastErrorMessage())")
}
if contactDB.open()
{
let sql_stmt = "CREATE TABLE IF NOT EXISTS StudentData (Name TEXT, Phone TEXT, Email TEXT PRIMARY KEY NOT NULL, Comment TEXT)"
if !contactDB.executeStatements(sql_stmt)
{
print("Error: \(contactDB.lastErrorMessage())")
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
}
//viewWillAppear
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(true)
listAllData()
}
//didReceiveMemoryWarning
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Edit Method
#IBAction func btn_Edit_Clicked(sender: UIButton)
{
operationViewFlag=2
let updateView = self.storyboard?.instantiateViewControllerWithIdentifier("PerformOperation") as! PerformOperation
updateView.strEmail = arrayStudInfo[sender.tag]["Email"] as? String
print("Email to pass = \(updateView.strEmail)")
updateView.dictRecord = (arrayStudInfo[sender.tag] as! NSDictionary)
self.navigationController?.pushViewController(updateView, animated: true)
}
// Delete Method
#IBAction func btn_Delete_Clicked(sender: UIButton)
{
let contactDB = FMDatabase(path: databasepath as String)
let strDelete = arrayStudInfo[sender.tag]["Email"] as? String
if contactDB.open()
{
let deleteSQL = "DELETE FROM StudentData WHERE Email='\(strDelete!)'"
let result = contactDB.executeUpdate(deleteSQL, withArgumentsInArray: nil)
if !result
{
print("Error: \(contactDB.lastErrorMessage())")
}
else
{
print("Deleted Record.")
listAllData()
}
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
contactDB.close()
}
// List All Data
func listAllData()
{
arrayStudInfo.removeAllObjects();
let contactDB = FMDatabase(path: databasepath as String)
if contactDB.open()
{
let filemgr = NSFileManager.defaultManager()
let dirpath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docdir = dirpath[0] as String
databasepath = docdir.stringByAppendingString("StudentDataManipulation.sqlite");
if filemgr.fileExistsAtPath(databasepath as String)
{
let contactDB = FMDatabase(path: databasepath as String)
if contactDB == nil
{
print("Error: \(contactDB.lastErrorMessage())")
}
if contactDB.open()
{
let sql_stmt = "CREATE TABLE IF NOT EXISTS StudentData (Name TEXT, Phone TEXT, Email TEXT PRIMARY KEY NOT NULL, Comment TEXT)"
if !contactDB.executeStatements(sql_stmt)
{
print("Error: \(contactDB.lastErrorMessage())")
}
let SelectQuery = "SELECT * FROM StudentData"
if let results:FMResultSet? = contactDB.executeQuery(SelectQuery, withArgumentsInArray: nil)
{
while results?.next() == true
{
let dictRecord = results?.resultDictionary()
arrayStudInfo.insertObject(dictRecord!, atIndex: arrayStudInfo.count)
print("\nRESULT : \(results?.resultDictionary())")
}
TableView_Mainscreen.reloadData()
}
else
{
print("Recored not found");
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
// TableView Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrayStudInfo.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let Cell = tableView.dequeueReusableCellWithIdentifier("CellHome") as! HomeCellView
Cell.lbl_tablecell_Email.text! = arrayStudInfo[(indexPath.row)]["Email"] as! String
print("Your Email : \(Cell.lbl_tablecell_Email.text!)")
Cell.btn_tablecell_Edit.tag=indexPath.row
Cell.btn_tablecell_Delete.tag=indexPath.row
Cell.btn_tablecell_Edit.layer.cornerRadius = 10
Cell.btn_tablecell_Delete.layer.cornerRadius = 10
// btn_Delete_Clicked
Cell.btn_tablecell_Edit.addTarget(self, action: #selector(ViewController.btn_Edit_Clicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
Cell.btn_tablecell_Delete.addTarget(self, action: #selector(ViewController.btn_Delete_Clicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
return Cell
}
}
Did you set delegate and data source to ViewController.
If you are using storyboard, you can control click your tableView to ViewController and set both delegate and data source.
If you want to do it in code, you can do this
TableView_Mainscreen.delegate = self
TableView_Mainscreen.datasource = self
Also you should be using lower camel case to name your variable.
I have created a program where it calculates the borders of certain countries based on a Custom Object being inputed into a function. This function returns an array of custom objects. I keep getting this error when trying to add this array to a NSMutableArray. The error is called "Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0)".
Here is my adding code:
#IBOutlet var Label: UILabel!
#IBOutlet var imageView: UIImageView!
override func viewDidLoad() {
//Afganistan
Afghanistan.name = "Afghanistan"
Afghanistan.borders.addObjectsFromArray(relate(Afghanistan))
Label.text = String((Afghanistan.borders[0] as! develop).name)
}
Here is the relate method along with the group dictionary:
func relate(X : develop) -> Array<develop>{
var A : [develop] = []
for (_, value) in groups {
for y in value {
if y.name == X.name {
for i in value {
if i.name != X.name {
A.append(i)
}
}
}
}
}
return A
}
//Groups
var groups = [
"one": [Afghanistan]
]
Here is the class of develop:
class develop : NSObject, NSCoding {
//Shared
var power : Int!
var name : String!
var image : UIImage!
var flag : UIImage!
var militaryName : String!
//Military
var experience : Int!
var OATC : Int!
var navy : Int!
var airforce : Int!
var artillery : Int!
//Geography
var borders : NSMutableArray!
var cities : NSMutableArray!
//Biomes
var biom : NSMutableArray!
var continent : String!
var NSEW : String!
//Encoding Section
required convenience init(coder decoder: NSCoder) {
self.init()
//shared
self.power = decoder.decodeObjectForKey("power") as! Int
self.name = decoder.decodeObjectForKey("name") as! String
self.image = decoder.decodeObjectForKey("image") as! UIImage
self.flag = decoder.decodeObjectForKey("flag") as! UIImage
self.militaryName = decoder.decodeObjectForKey("militaryName") as! String
//Military
self.experience = decoder.decodeObjectForKey("experience") as! Int
self.OATC = decoder.decodeObjectForKey("OATC") as! Int
self.navy = decoder.decodeObjectForKey("navy") as! Int
self.airforce = decoder.decodeObjectForKey("airforce") as! Int
self.artillery = decoder.decodeObjectForKey("artillery") as! Int
//Geography
self.borders = decoder.decodeObjectForKey("borders") as! NSMutableArray
self.cities = decoder.decodeObjectForKey("cities") as! NSMutableArray
self.continent = decoder.decodeObjectForKey("continent") as! String
self.NSEW = decoder.decodeObjectForKey("NSEW") as! String
}
convenience init(
power: Int, name: String, image: UIImage, flag: UIImage,
relations: NSMutableArray, mName: String, experience: Int,
OATC: Int, navy: Int, airforce: Int, artillery: Int,
borders: NSMutableArray, cities: NSMutableArray,
biom: NSMutableArray, continent: String, NSEW: String )
{
self.init()
//shared
self.power = power
self.name = name
self.image = image
self.flag = flag
self.militaryName = mName
//military
self.experience = experience
self.OATC = OATC
self.navy = navy
self.airforce = airforce
self.artillery = artillery
//geography
self.borders = borders
self.cities = cities
self.biom = biom
self.continent = continent
self.NSEW = NSEW
}
func encodeWithCoder(coder: NSCoder) {
//Shared
if let power = power { coder.encodeObject(power, forKey: "power") }
if let name = name { coder.encodeObject(name, forKey: "name") }
if let image = image { coder.encodeObject(image, forKey: "image") }
if let flag = flag { coder.encodeObject(flag, forKey: "flag") }
if let militaryName = militaryName { coder.encodeObject(militaryName, forKey: "militaryName") }
//Military
if let experience = experience { coder.encodeObject(experience, forKey: "experience") }
if let OATC = OATC { coder.encodeObject(OATC, forKey: "OATC") }
if let navy = navy { coder.encodeObject(navy, forKey: "navy") }
if let airforce = airforce { coder.encodeObject(airforce, forKey: "airforce") }
if let artillery = artillery { coder.encodeObject(artillery, forKey: "artillery") }
//geography
if let borders = borders { coder.encodeObject(borders, forKey: "borders") }
if let cities = cities { coder.encodeObject(cities, forKey: "cities") }
if let biom = biom { coder.encodeObject(biom, forKey: "biom") }
if let continent = continent { coder.encodeObject(continent, forKey: "continent") }
if let NSEW = NSEW { coder.encodeObject(NSEW, forKey: "NSEW") }
}
}
"Afghanistan" is a subclass of develop
I have the following code which copies data from the iPhone's contacts into an NSMutableDictionary. I'm using optional binding as discussed in this answer.
The firstName and lastName fields copy properly (as well as phone and email fields not shown here), but I have never been able to access the kABPersonNoteProperty, nor have I seen the println statement in the log. I've tried to copy the note as both String and NSString without success. Any ideas what could be causing this problem?
var contactInfoDict:NSMutableDictionary!
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!) {
self.contactInfoDict = ["firstName":"", "lastName":"", "notes":""]
if let firstName:String = ABRecordCopyValue(person, kABPersonFirstNameProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(firstName, forKey: "firstName")
println(firstName)
}
if let lastName:String = ABRecordCopyValue(person, kABPersonLastNameProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(lastName, forKey: "lastName")
println(lastName)
}
if let notes:String = ABRecordCopyValue(person, kABPersonNoteProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(notes, forKey: "notes")
println("Note: \(notes)")
}
}
Edit Here is the full class:
import UIKit
import AddressBookUI
class ContactsVC: UIViewController, ABPeoplePickerNavigationControllerDelegate {
#IBOutlet weak var done_Btn: UIBarButtonItem!
#IBAction func dismissContacts(sender: UIBarButtonItem) {
self.dismissViewControllerAnimated(true, completion: nil)
println("ContactsVC dismissed")
}
#IBOutlet weak var viewContainer: UIView!
var object:PFObject = PFObject(className: "Contact")
let personPicker: ABPeoplePickerNavigationController
var contactInfoDict:NSMutableDictionary!
required init(coder aDecoder: NSCoder) {
personPicker = ABPeoplePickerNavigationController()
super.init(coder: aDecoder)
personPicker.peoplePickerDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
done_Btn.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Avenir Next Medium", size: 16)!], forState: UIControlState.Normal)
}
#IBAction func addContact() {
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: "Would you like to select a contact from your iPhone or create a new contact directly in the app?", preferredStyle: .ActionSheet)
let selectContactAction: UIAlertAction = UIAlertAction(title: "Select from iPhone", style: .Default) { action -> Void in
self.performPickPerson(UIAlertAction)
}
actionSheetController.addAction(selectContactAction)
let createContactAction: UIAlertAction = UIAlertAction(title: "Create App Contact", style: .Default) { action -> Void in
self.performSegueWithIdentifier("AddContact", sender: self)
}
actionSheetController.addAction(createContactAction)
let cancelAction:UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) {
action -> Void in
}
actionSheetController.addAction(cancelAction)
self.presentViewController(actionSheetController, animated: true, completion: nil)
}
func performPickPerson(sender : AnyObject) {
self.presentViewController(personPicker, animated: true, completion: nil)
}
func peoplePickerNavigationControllerDidCancel(peoplePicker: ABPeoplePickerNavigationController!) {
personPicker.dismissViewControllerAnimated(true, completion: nil)
}
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!) {
self.contactInfoDict = ["firstName":"", "lastName":"", "company":"", "mobilePhone":"", "homePhone":"", "workPhone":"", "personalEmail":"", "workEmail":"", "street":"", "city":"", "state":"", "zipCode":"", "notes":""]
if let firstName:String = ABRecordCopyValue(person, kABPersonFirstNameProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(firstName, forKey: "firstName")
println(firstName)
}
if let lastName:String = ABRecordCopyValue(person, kABPersonLastNameProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(lastName, forKey: "lastName")
println(lastName)
}
if let company:String = ABRecordCopyValue(person, kABPersonOrganizationProperty)?.takeRetainedValue() as? String {
contactInfoDict.setObject(company, forKey: "company")
println(company)
}
if let phonesRef:ABMultiValueRef = ABRecordCopyValue(person, kABPersonPhoneProperty)?.takeRetainedValue() as ABMultiValueRef? {
for (var i = 0; i < ABMultiValueGetCount(phonesRef); i++ ) {
var currentPhoneLabel:CFStringRef = ABMultiValueCopyLabelAtIndex(phonesRef, i).takeRetainedValue()
var currentPhoneValue:CFStringRef = ABMultiValueCopyValueAtIndex(phonesRef, i)?.takeRetainedValue() as! CFStringRef
if let mobileResult = CFStringCompare(currentPhoneLabel, kABPersonPhoneMobileLabel, CFStringCompareFlags.CompareCaseInsensitive) as CFComparisonResult? {
if mobileResult == CFComparisonResult.CompareEqualTo {
contactInfoDict.setObject(currentPhoneValue, forKey: "mobilePhone")
}
}
if let homeResult = CFStringCompare(currentPhoneLabel, kABHomeLabel, CFStringCompareFlags.CompareCaseInsensitive) as CFComparisonResult? {
if homeResult == CFComparisonResult.CompareEqualTo {
contactInfoDict.setObject(currentPhoneValue, forKey: "homePhone")
}
}
if let workResult = CFStringCompare(currentPhoneLabel, kABWorkLabel, CFStringCompareFlags.CompareCaseInsensitive) as CFComparisonResult? {
if workResult == CFComparisonResult.CompareEqualTo {
contactInfoDict.setObject(currentPhoneValue, forKey: "workPhone")
}
}
}
}
if let emailsRef:ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty)?.takeRetainedValue() as ABMultiValueRef? {
for (var i = 0; i < ABMultiValueGetCount(emailsRef); i++ ) {
var currentEmailLabel:CFStringRef = ABMultiValueCopyLabelAtIndex(emailsRef, i).takeRetainedValue()
var currentEmailValue:CFStringRef = ABMultiValueCopyValueAtIndex(emailsRef, i)?.takeRetainedValue() as! CFStringRef
if let email = kABHomeLabel as CFStringRef? {
if let homeResult = CFStringCompare(currentEmailLabel, kABHomeLabel, CFStringCompareFlags.CompareCaseInsensitive) as CFComparisonResult? {
if homeResult == CFComparisonResult.CompareEqualTo {
contactInfoDict.setObject(currentEmailValue as String, forKey: "personalEmail")
}
}
}
if let workResult = CFStringCompare(currentEmailLabel, kABWorkLabel, CFStringCompareFlags.CompareCaseInsensitive) as CFComparisonResult? {
if workResult == CFComparisonResult.CompareEqualTo {
contactInfoDict.setObject(currentEmailValue as String, forKey: "workEmail")
}
}
}
}
if let addressRef:ABMultiValueRef = ABRecordCopyValue(person, kABPersonAddressProperty)?.takeRetainedValue() as ABMultiValueRef? {
if ABMultiValueGetCount(addressRef) > 0 {
var addressDict:NSDictionary = ABMultiValueCopyValueAtIndex(addressRef, 0)?.takeRetainedValue() as! NSDictionary
if let street = addressDict.objectForKey(kABPersonAddressStreetKey) as? String {
contactInfoDict.setObject(street as NSString, forKey: "street")
}
if let city = addressDict.objectForKey(kABPersonAddressCityKey) as? String {
contactInfoDict.setObject(city as NSString, forKey: "city")
}
if let state = addressDict.objectForKey(kABPersonAddressStateKey) as? String {
contactInfoDict.setObject(state as NSString, forKey: "state")
}
if let zipCode = addressDict.objectForKey(kABPersonAddressZIPKey) as? String {
contactInfoDict.setObject(zipCode as NSString, forKey: "zipCode")
}
}
}
// Notes is not currently accessible
if let note:String = ABRecordCopyValue(person, kABPersonNoteProperty)?.takeRetainedValue() as? String {
println("12")
contactInfoDict.setObject(note, forKey: "notes")
println("Note: \(note)")
}
saveToContact()
}
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, shouldContinueAfterSelectingPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
return false
}
func saveToContact(){
self.object["username"] = PFUser.currentUser()!
if let firstName = contactInfoDict["firstName"] as? String{
self.object["contactFirstName"] = firstName
}
if let lastName = contactInfoDict["lastName"] as? String{
self.object["contactLastName"] = lastName
}
if let company = contactInfoDict["company"] as? String{
self.object["contactCompany"] = company
}
if let mobilePhone = contactInfoDict["mobilePhone"] as? String{
self.object["contactMobilePhone"] = mobilePhone
}
if let homePhone = contactInfoDict["homePhone"] as? String{
self.object["contactHomePhone"] = homePhone
}
if let workPhone = contactInfoDict["workPhone"] as? String{
self.object["contactWorkPhone"] = workPhone
}
if let personalEmail = contactInfoDict["personalEmail"] as? String{
self.object["contactPersonalEmail"] = personalEmail
}
if let workEmail = contactInfoDict["workEmail"] as? String{
self.object["contactWorkEmail"] = workEmail
}
if let street = contactInfoDict["street"] as? String{
self.object["contactStreet"] = street
}
if let city = contactInfoDict["city"] as? String{
self.object["contactCity"] = city
}
if let state = contactInfoDict["state"] as? String{
self.object["contactState"] = state
}
if let zipCode = contactInfoDict["zipCode"] as? String{
self.object["contactZipCode"] = zipCode
}
if let notes = contactInfoDict["notes"] as? String{
self.object["contactNotes"] = notes
}
self.object["contactType"] = "Lead"
self.object["contactIsActive"] = true
var addrObject = self.object
self.object.pinInBackgroundWithName("Contacts")
self.object.saveEventually{ (success, error) -> Void in
if (error == nil) {
println("saved in background")
} else {
println(error!.userInfo)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I just tested it and it works fine, just as you have it. This is effectively my whole code (except for getting authorization, of course):
#IBAction func doPeoplePicker (sender:AnyObject!) {
let picker = ABPeoplePickerNavigationController()
picker.peoplePickerDelegate = self
self.presentViewController(picker, animated:true, completion:nil)
}
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!,
didSelectPerson person: ABRecord!) {
if let note = ABRecordCopyValue(person, kABPersonNoteProperty)?.takeRetainedValue() as? String {
println(note)
} else {
println("no note")
}
}
When my person has a note, I see it; when my person has no note, I see "no note".
EDIT You and I played around with this for a while, sending each other actual projects, and I observed the following difference between your implementation and mine: mine, for which fetching the note works, obtains authorization to access the address book (you'll notice that I did mention that, in the first paragraph of my original answer); yours, for which fetching the note doesn't work, doesn't obtain authorization. Hence, I suggest that this is the missing piece of the puzzle.
Here's my theory. Prior to iOS 8, you needed authorization in order to use ABPeoplePickerNavigationController. Thus, my code, which goes way back, still obtains it. The way this supposedly works in iOS 8 is that, in the absence of authorization, the people picker fetches a copy of the address book data. Well, I think that this copy is faulty (and that you should file a bug report with Apple about this). But because I have authorization, I'm accessing the actual address book data, and so my code can see the note.
here is the code of the main file , it is not giving any errors but it's not working :
import UIKit
class mainVC: UIViewController,UITableViewDelegate,UITableViewDataSource , UISearchBarDelegate, UISearchDisplayDelegate {
//this is your tableview
#IBOutlet var table: UITableView!
#IBOutlet var selectedMin: NSString!
#IBOutlet var tasksList: NSArray!
#IBOutlet var searchResults :NSArray!
#IBOutlet var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// navigationItem.titleView = UIImageView(image:UIImage(named: "logo3"))
navigationItem.title="مجمع الخدمات الحكومية"
//cell height
self.table.rowHeight = 50
//tableview background
self.table.backgroundView = UIImageView(image: UIImage(named: "space.jpg"))
if let path = NSBundle.mainBundle().pathForResource(selectedMin, ofType: "plist")
{
tasksList = NSArray(contentsOfFile: path)
}
table.separatorColor = UIColor.yellowColor()
}
func filterContentForSearchText(searchText:NSString , scope: String = "All")
{
//var searchText = ""
var resultPredicate : NSPredicate = NSPredicate(format: "name contains[c] %#", searchText)
//var recipes : NSArray = NSArray()
var searchResults = self.tasksList.filteredArrayUsingPredicate(resultPredicate)
}
func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
let scopes = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
let selectedScope = scopes[self.searchDisplayController!.searchBar.selectedScopeButtonIndex] as String
self.filterContentForSearchText(searchString, scope: selectedScope)
return true
}
func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchScope searchOption: Int) -> Bool {
let scope = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
self.filterContentForSearchText(self.searchDisplayController!.searchBar.text, scope: scope[searchOption])
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(animated: Bool) {
table.reloadData()
}
func tableView(tableView :UITableView,numberOfRowsInSection section:Int)->Int{
if table == self.searchDisplayController!.searchResultsTableView {
return self.searchResults.count
} else{
return tasksList.count}
}
func tableView(tableView :UITableView,cellForRowAtIndexPath indexpath:NSIndexPath)->UITableViewCell
{
var dict :NSDictionary!
let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "TableView")
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.textLabel?.textColor=UIColor.whiteColor()
//assigning the content of var items to the textlabel of each cell
if table == self.searchDisplayController!.searchResultsTableView {
var dict = searchResults?.objectAtIndex(indexpath.row) as NSDictionary
cell.textLabel?.text = ( dict.objectForKey("NAME") as String)
}
else{
var dict = tasksList?.objectAtIndex(indexpath.row) as NSDictionary
cell.textLabel?.text = ( dict.objectForKey("NAME") as String)
}
if(indexpath.row % 2 == 0){
cell.backgroundColor = UIColor.clearColor()
}else{
//set cell opacity
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
}
return cell
}
func tableView(tableView :UITableView,didSelectRowAtIndexPath indexPath:NSIndexPath){
var dict=tasksList?.objectAtIndex(indexPath.row) as NSDictionary
//create an instance of detailVC
var detail:detailVC=self.storyboard?.instantiateViewControllerWithIdentifier("detailVC")as detailVC
//reference DetailVc s var cellName and assign it to the DetailVC s var items
detail.cellName = dict.objectForKey("NAME") as String
detail.cellDesc = dict.objectForKey("DESC") as String
//programatically push to associated vc "DetailVC"
self.navigationController?.pushViewController(detail, animated: true)
}
}
I must be incorrectly using Custom Objects for NSUserDefaults. The error " Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')". Below is my code, the Goal class is of particular interest, since this is where I am adopting the NSCoding protocol.
This code is global.
func saveGoals (goals : [Goal]) {
var updatedGoals = NSKeyedArchiver.archivedDataWithRootObject(goals)
NSUserDefaults.standardUserDefaults().setObject(updatedGoals, forKey: "Goals")
NSUserDefaults.standardUserDefaults().synchronize()
}
func loadCustomObjectWithKey() -> [Goal] {
if let encodedObject : NSData = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData {
var encodedObject : NSData? = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData
var goal : [Goal] = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as [Goal]
return goal
} else {
return [Goal]()
}
}
This code is in GoalsViewController.
class GoalsViewController: MainPageContentViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: GoalsTableView!
var cell = GoalTableViewCell()
var goalsArray : Array<Goal> = [] //
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
if var storedGoals: [Goal] = loadCustomObjectWithKey() as [Goal]? {
goalsArray = storedGoals
}
//retrieve data.
var goal = Goal(title: "Walk the Dog")
goalsArray.append(goal)
saveGoals(goalsArray)
self.tableView?.reloadData()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
var notification = NSNotificationCenter.defaultCenter()
notification.addObserver(self, selector: "finishCreatingGoal:", name: "FinishCreatingGoal", object: nil)
}
func finishCreatingGoal(notification : NSNotification) {
if (notification.name == "FinishCreatingGoal") {
var userInfo = notification.userInfo!
var text = userInfo["text"]! as String
var index = userInfo["index"]! as Int
var cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as GoalTableViewCell
goalsArray[index].title = cell.goalTextField.text
saveGoalList(goalsArray)
self.tableView.reloadData()
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0), atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
}
}
This code is in the Goal class.
import UIKit
class Goal : NSObject, NSCoding {
var title : String? = ""
var checkmarked : Bool? = false
var isLastCell : Bool? = false
var enabled : Bool? = true
var priority = Priority.defaultPriority
override init() {
}
init(title : String) {
self.title = title
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(title!, forKey: "title")
aCoder.encodeBool(checkmarked!, forKey: "checkmarked")
aCoder.encodeBool(isLastCell!, forKey: "isLastCell")
aCoder.encodeBool(enabled!, forKey: "enabled")
}
required init(coder aDecoder: NSCoder) {
title = aDecoder.decodeObjectForKey("title") as String!
checkmarked = aDecoder.decodeBoolForKey("checkmarked") as Bool
isLastCell = aDecoder.decodeBoolForKey("isLastCell") as Bool
enabled = aDecoder.decodeBoolForKey("enabled") as Bool
}
}
I am going to just copy code from a working project I have:
here is the Game object class with data from a math flash card game:
import Foundation
class GameData: NSObject {
var sign: String = "+"
var level: Int = 1
var problems: Int = 10
var time: Int = 30
var skipWrong: Bool = true
var usedTime: Int = 0
var correctCount: Int = 0
var correctTopNumber: [Int] = [Int]()
var correctBottomNumber: [Int] = [Int]()
var wrongTopNumber: [Int] = [Int]()
var wrongBottomNumber: [Int] = [Int]()
var date: NSDate = NSDate()
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(sign, forKey: "sign")
aCoder.encodeInteger(level, forKey: "level")
aCoder.encodeInteger(problems, forKey: "problems")
aCoder.encodeInteger(time, forKey: "time")
aCoder.encodeBool(skipWrong, forKey: "skipWrong")
aCoder.encodeInteger(usedTime, forKey: "usedTime")
aCoder.encodeInteger(correctCount, forKey: "correctCount")
aCoder.encodeObject(correctTopNumber, forKey: "correctTopNumber")
aCoder.encodeObject(correctBottomNumber, forKey: "correctBottomNumber")
aCoder.encodeObject(wrongTopNumber, forKey: "wrongTopNumber")
aCoder.encodeObject(wrongBottomNumber, forKey: "wrongBottomNumber")
aCoder.encodeObject(date, forKey: "date")
}
init(coder aDecoder: NSCoder!) {
sign = aDecoder.decodeObjectForKey("sign") as String
level = aDecoder.decodeIntegerForKey("level")
problems = aDecoder.decodeIntegerForKey("problems")
time = aDecoder.decodeIntegerForKey("time")
skipWrong = aDecoder.decodeBoolForKey("skipWrong")
usedTime = aDecoder.decodeIntegerForKey("usedTime")
correctCount = aDecoder.decodeIntegerForKey("correctCount")
correctTopNumber = aDecoder.decodeObjectForKey("correctTopNumber") as Array
correctBottomNumber = aDecoder.decodeObjectForKey("correctBottomNumber") as Array
wrongTopNumber = aDecoder.decodeObjectForKey("wrongTopNumber") as Array
wrongBottomNumber = aDecoder.decodeObjectForKey("wrongBottomNumber") as Array
date = aDecoder.decodeObjectForKey("date") as NSDate
}
override init() {
}
}
This part looks about the same as yours, but with more variable types. The archiver and retriever classes differ from you:
import Foundation
class ArchiveGameData:NSObject {
var documentDirectories:NSArray = []
var documentDirectory:String = ""
var path:String = ""
func ArchiveResults(#dataSet: [GameData]) {
documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
documentDirectory = documentDirectories.objectAtIndex(0) as String
path = documentDirectory.stringByAppendingPathComponent("results3.archive")
if NSKeyedArchiver.archiveRootObject(dataSet, toFile: path) {
//println("Success writing to file!")
} else {
println("Unable to write to file!")
}
}
func RetrieveGameData() -> NSObject {
var dataToRetrieve = [GameData]()
documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
documentDirectory = documentDirectories.objectAtIndex(0) as String
path = documentDirectory.stringByAppendingPathComponent("results3.archive")
if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [GameData] {
dataToRetrieve = dataToRetrieve2
}
return(dataToRetrieve)
}
}
Finally, the code for storing and retrieving from within a ViewController:
//retrieveing
var gameDataArray = ArchiveGameData().RetrieveGameData() as [GameData]
//Archiving
gameData = GameData() //create local object then append all the new data, then store it
gameData.sign = buttonStates.sign
gameData.level = buttonStates.level
gameData.problems = buttonStates.problems
gameData.time = buttonStates.time
//etc. for all properties
ArchiveGameData().ArchiveResults(dataSet: gameDataArray)