0

Hey guys so I'm working on an application where I have imported a contacts list from my device and I am given the option to "add" the contact but it really doesn't do much when it comes to functionality. I'm not the best coder so try to hear me out. what I am trying to do is take the data/ selected table view cell and display it on another page. I "think" that this is what I should do because I have tried to display the data on another page but get an error when I move my OVERRIDE function. that makes me believe that I need to take the data, which I believe is newContact? and set that as a variable and then display it on a new page where I can create a new view controller and add the code without error.

I essentially need to figure out what my JSON data is saved as, then set that equivalent to a string if that is possible, so I can send it to my new view controller or and send it to my database with code I already have created.

I am just not sure where to enter the statements because of errors that I am getting and what the exact code would be.

Sorry for the awful description of what I am trying to perform, I have a grasp of what is needed to be done but I am a beginner.

My Master View Controller that takes the contacts from my phone and accesses them.

import UIKit
import Contacts
import ContactsUI

class MainViewController: UIViewController {

@IBOutlet weak var textField: UITextField!
@IBOutlet weak var tableView: UITableView!

var store = CNContactStore()
var contacts: [CNContact] = []

override func viewDidLoad() {
    super.viewDidLoad()
}

//MARK: - User Actions

@IBAction func contactListPressed(_ sender: AnyObject) {
    let contactPickerViewController = CNContactPickerViewController()
    contactPickerViewController.delegate = self
    present(contactPickerViewController, animated: true, completion:      nil)
}

@IBAction func addContactPressed(_ sender: AnyObject) {
    let newContact = CNMutableContact()

    newContact.givenName = "Apps"
    newContact.familyName = "Foundations"
    newContact.nickname = "AF"

    if let image = UIImage(named: "logo-apps-foundation.jpg"),
        let data = UIImagePNGRepresentation(image){
        newContact.imageData = data
    }

    let phone = CNLabeledValue(label: CNLabelWork, value:   CNPhoneNumber(stringValue: "+441234567890"))
    newContact.phoneNumbers = [phone]

    let email = "" //Your Input goes here
    let Email = CNLabeledValue(label:CNLabelWork, value: email as NSString)
    newContact.emailAddresses = [Email]


    newContact.jobTitle = "Apps Foundation"
    newContact.organizationName = "Apps Foundation"
    newContact.departmentName = "IT"

    let facebookProfile = CNLabeledValue(label: "Facebook", value:   CNSocialProfile(urlString: "https://www.facebook.com/appsfoundation", username: "AppsFoundation", userIdentifier: "appsfoundation", service: CNSocialProfileServiceFacebook))
    let twitterProfile = CNLabeledValue(label: "Twitter", value: CNSocialProfile(urlString: "https://twitter.com/AppsFoundation", username: "AppsFoundation", userIdentifier: "appsfoundation", service: CNSocialProfileServiceTwitter))
    newContact.socialProfiles = [facebookProfile, twitterProfile]

    let skypeProfile = CNLabeledValue(label: "Skype", value: CNInstantMessageAddress(username: "AppsFoundation", service: CNInstantMessageServiceSkype))
    newContact.instantMessageAddresses = [skypeProfile]

    var birthday = DateComponents()
    birthday.year = 1991
    birthday.month = 1
    birthday.day = 1
    newContact.birthday = birthday

    let request = CNSaveRequest()
    request.add(newContact, toContainerWithIdentifier: nil)
    do {
        try store.execute(request)
        let alert = UIAlertController(title: "Contacts iOS 9", message: "New contact has been created", preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
    } catch let error{
        print(error)
    }
}

@IBAction func textFieldValueChanged(_ sender: AnyObject) {
    if let query = textField.text {
        findContactsWithName(query)
    }
}

//MARK: - Private Methods

func findContactsWithName(_ name: String) {
    AppDelegate.sharedDelegate().checkAccessStatus({ (accessGranted) -> Void in
        if accessGranted {
            DispatchQueue.main.async(execute: { () -> Void in
                do {
                    let predicate: NSPredicate = CNContact.predicateForContacts(matchingName: name)
                    let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactViewController.descriptorForRequiredKeys()] as [Any]
                    self.contacts = try self.store.unifiedContacts(matching: predicate, keysToFetch:keysToFetch as! [CNKeyDescriptor])
                    self.tableView.reloadData()
                }
                catch {
                    print("Unable to refetch the selected contact.")
                }
            })
        }
    })
}

func updateContact(_ contactIdentifier: String) {
    do {
        let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactPhoneNumbersKey, CNContactViewController.descriptorForRequiredKeys()] as [Any]
        let contact = try store.unifiedContact(withIdentifier:  contactIdentifier, keysToFetch:keysToFetch as! [CNKeyDescriptor])

        let contactToUpdate = contact.mutableCopy() as! CNMutableContact
        contactToUpdate.phoneNumbers = [CNLabeledValue(label: CNLabelWork, value: CNPhoneNumber(stringValue: "+440987654321"))]

        let saveRequest = CNSaveRequest()
        saveRequest.update(contactToUpdate)
        try store.execute(saveRequest)
    } catch let error{
        print(error)
    }
}

}

 //MARK: - UITableViewDataSource

extension MainViewController: CNContactPickerDelegate {

func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
    let selectedContactID = contact.identifier
    updateContact(selectedContactID)
}

}

 //MARK: - UITableViewDataSource

    extension MainViewController: UITableViewDataSource {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return contacts.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let CellIdentifier = "MyCell"
    let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier)
    cell!.textLabel!.text = contacts[indexPath.row].givenName + " " + contacts[indexPath.row].familyName

    if let birthday = contacts[indexPath.row].birthday {
        let formatter = DateFormatter()
        formatter.dateStyle = DateFormatter.Style.long
        formatter.timeStyle = .none

        cell!.detailTextLabel?.text = formatter.string(from: ((birthday as NSDateComponents).date)!)
    }
    return cell!
}

 }

//MARK: - UITableViewDelegate

 extension MainViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let controller = CNContactViewController(for: contacts[indexPath.row])
    controller.contactStore = self.store
    controller.allowsEditing = false
    self.navigationController?.pushViewController(controller, animated: true)
}

}

I know I need to incorporate something like this but I am not sure where or how to set the JSON data to a variable or the correct type and then incorporate code of this type

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
    if let indexPath = self.tableView.indexPathForSelectedRow {
        let controller = segue.destination as! ViewControllerB
        controller.selectedName = objects[indexPath.row]
    }
}
}

sorry for the awful explanation. any help possible would be appreciated, I have been struggling for quite some time.

  • Create Model Classes, Populate Cells with the Model Classes, MVC means separation of Model and View. And then pass the [selected Model class instance to the next ViewController](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – NSNoob Mar 29 '17 at 04:51
  • 1
    Possible duplicate of [Passing Data between View Controllers](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – NSNoob Mar 29 '17 at 04:52
  • create models using json and pass those models from one vc to another vc – Ganesh Kumar Mar 29 '17 at 05:03

1 Answers1

0

First of all, you need to have the other view controller that you are trying to pass data to. It can either be on the Interface Builder or done programmatically (I'll assume it's on the IB for now). Then you'll need to setup a segue between the Main VC and the Details VC and give it an identifier e.g. showDetail.

Next would be to determine the data that Details VC needs for it to work properly. You can have individual variables for each data item (e.g. name, age, phone, email, etc) but usually if there is a lot of info, it's best to use a data model. In your case, since you are trying to display contact info, you can simply reuse CNContact.

So you simply need a CNContact in your Details VC that you'll set before transitioning from Main VC in the prepareForSegue function. And to initiate the segue, all you have to do is call performSegue function.

Hope that at least gives you some direction

Sylvan D Ash
  • 1,047
  • 13
  • 24