Swift 即使使用默认值,文本标签也为零
Swift Text Label Nil Even With Default Value
这让我发疯。函数 updateTextView()
正在被调用,由 print 语句验证,但它没有在我的视图控制器中设置标签,标签的 print 语句返回 nil,即使它设置了可见的默认值加载应用程序时。更令人费解的是,我设置了一个测试按钮来单独调用这个函数,当我用test()
调用它时,标签就会正确更新。
class GoalDetailViewController: UIViewController, TextDelegate {
@IBAction func test(sender: AnyObject) {
updateTextView()
}
func updateTextView() {
print(goalSummaryTextBox?.text)
print("delegate called")
self.goalSummaryTextBox?.text = GoalsData.summaryText
print(goalSummaryTextBox?.text)
}
@IBOutlet weak var goalTitle: UILabel?
@IBOutlet weak var goalCreationDate: UILabel?
@IBOutlet weak var goalSummaryTextBox: UITextView?
override func viewDidLoad() {
super.viewDidLoad()
goalSummaryTextBox?.text = GoalsData.summaryText
}
}
updateTextView()
在我弹出一个不同的视图控制器后通过委托方法被调用,如下所示:
class TextEditViewController: UIViewController {
var textDelegate: TextDelegate?
@IBOutlet weak var textView: UITextView?
func configureView() {
navigationItem.title = "Edit Description"
navigationItem.setRightBarButtonItem((UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "segue")), animated: true)
}
func segue() {
textDelegate = GoalDetailViewController()
if let text = textView?.text {
GoalsData.summaryText = text
}
textDelegate?.updateTextView()
self.navigationController?.popViewControllerAnimated(true)
}
}
导致问题的行在下面的 TextEditViewController
中:
textDelegate = GoalDetailViewController()
这一行所做的是创建 GoalDetailViewController
的新实例,并将其设置为 TextEditViewController
的委托。但是,您想要的是 GoalDetailViewController
的原始实例作为委托。这就是为什么您在弹出 TextEditViewController
时看到日志的原因,因为它正在执行另一个实例(它不是视图层次结构的一部分)。它还解释了为什么在委托调用中单步执行 updateTextView()
时所有 IBOutlet
都为零,并且您添加的按钮会正确更新文本。
解决方法是在prepareForSegue
方法中进行委托连接:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? TextEditViewController {
destination.textDelegate = self
}
}
将以上代码添加到您的GoalDetailViewController
。
编辑:
下面的代码将确保以后不会再出现这个问题。将代表的定义更改为:
weak var textDelegate: TextDelegate?
并将您的协议更改为:
protocol TextDelegate: class {
func updateTextView()
}
这让我发疯。函数 updateTextView()
正在被调用,由 print 语句验证,但它没有在我的视图控制器中设置标签,标签的 print 语句返回 nil,即使它设置了可见的默认值加载应用程序时。更令人费解的是,我设置了一个测试按钮来单独调用这个函数,当我用test()
调用它时,标签就会正确更新。
class GoalDetailViewController: UIViewController, TextDelegate {
@IBAction func test(sender: AnyObject) {
updateTextView()
}
func updateTextView() {
print(goalSummaryTextBox?.text)
print("delegate called")
self.goalSummaryTextBox?.text = GoalsData.summaryText
print(goalSummaryTextBox?.text)
}
@IBOutlet weak var goalTitle: UILabel?
@IBOutlet weak var goalCreationDate: UILabel?
@IBOutlet weak var goalSummaryTextBox: UITextView?
override func viewDidLoad() {
super.viewDidLoad()
goalSummaryTextBox?.text = GoalsData.summaryText
}
}
updateTextView()
在我弹出一个不同的视图控制器后通过委托方法被调用,如下所示:
class TextEditViewController: UIViewController {
var textDelegate: TextDelegate?
@IBOutlet weak var textView: UITextView?
func configureView() {
navigationItem.title = "Edit Description"
navigationItem.setRightBarButtonItem((UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "segue")), animated: true)
}
func segue() {
textDelegate = GoalDetailViewController()
if let text = textView?.text {
GoalsData.summaryText = text
}
textDelegate?.updateTextView()
self.navigationController?.popViewControllerAnimated(true)
}
}
导致问题的行在下面的 TextEditViewController
中:
textDelegate = GoalDetailViewController()
这一行所做的是创建 GoalDetailViewController
的新实例,并将其设置为 TextEditViewController
的委托。但是,您想要的是 GoalDetailViewController
的原始实例作为委托。这就是为什么您在弹出 TextEditViewController
时看到日志的原因,因为它正在执行另一个实例(它不是视图层次结构的一部分)。它还解释了为什么在委托调用中单步执行 updateTextView()
时所有 IBOutlet
都为零,并且您添加的按钮会正确更新文本。
解决方法是在prepareForSegue
方法中进行委托连接:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? TextEditViewController {
destination.textDelegate = self
}
}
将以上代码添加到您的GoalDetailViewController
。
编辑:
下面的代码将确保以后不会再出现这个问题。将代表的定义更改为:
weak var textDelegate: TextDelegate?
并将您的协议更改为:
protocol TextDelegate: class {
func updateTextView()
}