当前使用两个视图控制器和一个处理商店详细信息(如电话号码)的快速文件。有一个主视图控制器和一个详细信息视图控制器。
我目前从谷歌地点 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
}
在prepareForSegue
中将placeDetails
分配给目标视图控制器。我知道您没有这样做,因为您已经将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
位置更好。
尝试将您的电话号码转换为字符串。
detailsVC.phoneNumberLabel.text = String(placeDetails.phoneNumber!)
此外,nil 值可能来自 API 响应的编码方法。
编辑
我认为您必须以showDetailsVC
的viewDidLoad()
方法设置UILabel
的文本.在 showDetailVC
中声明一个 string
变量,然后将placeDetails.phoneNumber
变量传递给刚刚声明的字符串。(而不是直接在 tapLabel()
方法中设置文本)。然后在你的showDetailVC 在viewDidLoad()
中将文本设置为您的 UILabel