0

I am learning Swift and attempting to make use of code from the iOS8 Swift Dev's Cookbook, but am having difficulty using a variable produced from a custom function in the viewDidLoad function to put that product in a UILabel object.

The optional phone toward the top is not corresponding to the phone created peoplePickerNavigationController function. Thus, the labelPhone object displays nothing rather than displaying the phone number selected out of the peoplePickerNavigationController function.

How does one get a variable/constant from one function into an object in the viewDidLoad function so that it can be used in the UI?

For reference, my Storyboard contains a UIButton "Contacts" that can be tapped to execute the peoplePickerNavigationController function.

import UIKit
import AddressBookUI

class ViewController: UIViewController, ABPeoplePickerNavigationControllerDelegate {

    var phone : String?
    //I'm trying to pull up the phone variable down below, but the two are not corresponding. The optional above is what appears in the `labelPhone` object below rather than the contents of the phone way below.

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var labelPhone = UILabel(frame: CGRectMake(0, 0, 200, 21))
        labelPhone.center = CGPointMake(160, 284)
        labelPhone.textAlignment = NSTextAlignment.Center
        labelPhone.text = phone
        self.view.addSubview(labelPhone)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    let personPicker: ABPeoplePickerNavigationController

    required init(coder aDecoder: NSCoder) {
        personPicker = ABPeoplePickerNavigationController()
        super.init(coder: aDecoder)
        personPicker.peoplePickerDelegate = self
    }

    func peoplePickerNavigationControllerDidCancel(peoplePicker: ABPeoplePickerNavigationController!) {
        /* Mandatory */
    }

    func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
        /* A property in a person was picked */
    }

    @IBAction func performPickPerson(sender : AnyObject) {
        self.presentViewController(personPicker, animated: true, completion: nil)
    }

    func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecordRef!) {
        /* Do we know which picker it is? */
        if peoplePicker != personPicker{
            return
        }

    /* Get all phone numbers this user has */
        let phones: ABMultiValueRef = ABRecordCopyValue(person, kABPersonPhoneProperty).takeRetainedValue()

        let countOfPhones = ABMultiValueGetCount(phones)

        for index in 0..<countOfPhones{
            let phone = ABMultiValueCopyValueAtIndex(phones, index).takeRetainedValue() as String

            println(phone)


        }
    }

}

Thanks <3

Current code:

import UIKit
import AddressBookUI

class ViewController: UIViewController, ABPeoplePickerNavigationControllerDelegate {

var phone : String?
var labelPhone: UILabel?
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    labelPhone = UILabel(frame: CGRectMake(0, 0, 200, 21))
    labelPhone!.center = CGPointMake(160, 284)
    labelPhone!.textAlignment = NSTextAlignment.Center
    labelPhone!.text = phone
}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

let personPicker: ABPeoplePickerNavigationController

required init(coder aDecoder: NSCoder) {
    personPicker = ABPeoplePickerNavigationController()
    super.init(coder: aDecoder)
    personPicker.peoplePickerDelegate = self
}

func peoplePickerNavigationControllerDidCancel(peoplePicker: ABPeoplePickerNavigationController!) {
    /* Mandatory */
}

func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
    /* A property in a person was picked */
}

@IBAction func performPickPerson(sender : AnyObject) {
    self.presentViewController(personPicker, animated: true, completion: nil)
}

func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecordRef!) {
    /* Do we know which picker it is? */
    if peoplePicker != personPicker{
        return

    }

/* Get all phone numbers this user has */
    let phones: ABMultiValueRef = ABRecordCopyValue(person, kABPersonPhoneProperty).takeRetainedValue()

    let countOfPhones = ABMultiValueGetCount(phones)

    for index in 0..<countOfPhones{
        //let phone = ABMultiValueCopyValueAtIndex(phones, index).takeRetainedValue() as String

        phone = ABMultiValueCopyValueAtIndex(phones, index).takeRetainedValue() as? String
        labelPhone!.text = phone


        println(phone)



    }
}

}
4
  • viewDidLoad happens long before anything else. So how could it possible be affected by what didSelectPerson will do in the future? It doesn't have a time machine... Commented Jan 24, 2015 at 3:38
  • 2
    Also the phone in didSelectPerson is not the same phone up at the top, because you said let which declares a completely different local variable. But even if it were, it wouldn't matter, because it happens later. Try to think about the order in which methods are called. Use logging to help you understand. Commented Jan 24, 2015 at 3:40
  • I see. Is it possible to use the phone constant in the UI? I'm trying to put that phone number in the constant phone into a UILabel Commented Jan 24, 2015 at 3:41
  • Of course it's possible but not by using viewDidLoad; it happened earlier. You want to set the label's text to phone, then set it. Don't wait and pray for it to happen magically. Commented Jan 24, 2015 at 3:44

1 Answer 1

1

First, viewDidLoad only execute once when the view is loaded. To change the text of the label you need to do something like:

var phone : String?
var labelPhone: UILabel?

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    labelPhone = UILabel(frame: CGRectMake(0, 0, 200, 21))
    labelPhone.center = CGPointMake(160, 284)
    labelPhone.textAlignment = NSTextAlignment.Center
    self.view.addSubview(labelPhone)
}

func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecordRef!) {
    // Got the phone 
    phone = ABMultiValueCopyValueAtIndex(phones, index).takeRetainedValue() as String
    labelPhone.text = phone
}
Sign up to request clarification or add additional context in comments.

6 Comments

This is almost right, but not quite... In swift "self." is not required when accessing the global variables so setting self.phone = phone doesn't make sense. Simply ditch the "let" in phone = ABMultiValueCopyValueAtIndex(phones, index).takeRetainedValue() as String
Also since phone will equal nil originally, labelPhone.text = phone shouldn't at all be in the viewDidLoad.
I've been tweaking this (labelPhone needs to be unwrapped it seems otherwise I get errors among a couple other small tweaks) and have it to a point where I feel like it should be working, but I'm still not getting anything in the label. In fact when I change the labelPhone!.text to "test", "test" doesn't show up now the way it was before. About to post code above
@user3246092 Is setNeedsDisplay helping?
@user3246092 Did you forget to add UILabel to self.view?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.