属性值打印,但当分配给标签时,它显示为零

时间:2016-05-26 20:51:56

标签: ios swift debugging properties null

目前正在使用两个视图控制器和一个处理商店详细信息的swift文件,例如电话号码。有一个主ViewController和一个DetailsViewController。

我目前从google places api获取数据,并且能够成功地将值存储在PlaceDetails类中。测试数据 - 我可以打印到控制台。但是,当我尝试将从API获取的值分配给UILabel时,应用程序崩溃并显示该属性的值为nil。我不确定为什么会这样。我觉得在两个视图控制器中我正确地实例化PlaceDetails类并正确访问它的属性但是有一些我不知道这是错误的。

class ViewController: UIViewController
{
   let placeDetails = PlaceDetails()
   let detailsVC = DetailsViewController()

   func tapLabel( sender: UITapGestureRecognizer )
   {

    // print statement successfully prints out the stored value as - Optional("1 888-555-5555")
    print(placeDetails.phoneNumber)

    // assigning value to label causes a crash stating value is nil
    detailsVC.phoneNumberLabel.text = placeDetails.phoneNumber!

    self.performSegueWithIdentifier("showDetailsVC", sender: self)

   }
}

class DetailsViewController: UIViewController
{
    @IBOutlet weak var phoneNumberLabel  : UILabel!

    let placeDetails = PlaceDetails()

    override func viewDidLoad()
    {
       super.viewDidLoad()
       //This approach does not cause a crash but outputs nil to the console for both the print statement and the assignment statement
       print(placeDetails.phoneNumber)
       phoneNumberLabel.text = placeDetails.phoneNumber! 
    }  
}

class PlaceDetails
{
     override init()
     {
         super.init()
     }
     var phoneNumber : String? //viewcontroller actions give this class property its value
}

2 个答案:

答案 0 :(得分:0)

您需要在placeDetails中将prepareForSegue分配给目标视图控制器。我知道你不是这样做的,因为你创建了placeDetails作为let常量而不是变量,所以它不能从你最初的空PlaceDetails改变分配。

您应该将其声明为可选变量,然后在使用时将其正确打开;

class ViewController: UIViewController
{
    let placeDetails = PlaceDetails()

    func tapLabel( sender: UITapGestureRecognizer )
    {
        self.performSegueWithIdentifier("showDetailsVC", sender: self)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if (segue.identifier == "showDetailsVC") {
            let destVC = segue.destinationViewController as! DetailsViewController
            destVC.placeDetails = self.placeDetails
        }
    }
}

class DetailsViewController: UIViewController
{
    @IBOutlet weak var phoneNumberLabel  : UILabel!

    var placeDetails: PlaceDetails?

    override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        if let placeDetails = self.placeDetails {
            if let phoneNumber = placeDetails.phoneNumber {
                self.phoneNumberLabel.text = phoneNumber
            }
        }
    }
}

您无法使用viewDidLoad中的值,因为此方法将在设置属性之前执行;在调用prepareForSegue之前加载了视图控制器,因此viewWillAppear是一个更好的地方。

答案 1 :(得分:-1)

尝试将phoneNumber转换为字符串。

detailsVC.phoneNumberLabel.text = String(placeDetails.phoneNumber!)

此外,nil值可能来自API响应的编码方法。

编辑

我认为您必须在UILabel的{​​{1}}方法中设置viewDidLoad()的文字。在showDetailsVC中声明string变量,然后将showDetailVC变量传递给刚刚声明的字符串。 (而不是直接在placeDetails.phoneNumber方法中设置文本)。然后在你的 showDetailVC将文本设置为tapLabel()

中的UILabel