[英]Outlets are nil?
我在故事板中為標簽創建(並鏈接)了一些出口,當我嘗試修改文本時,我的應用程序會拋出異常並凍結,因為它們顯然是nil
。
碼:
import UIKit
class QuoteView : UITableViewController {
@IBOutlet var quoteCategory: UILabel!
@IBOutlet var quoteTitle: UILabel!
@IBOutlet var quoteAuthor: UILabel!
@IBOutlet var quoteContent: UILabel!
@IBOutlet var quoteTimestamp: UILabel!
}
我試圖在前一個視圖控制器的prepareForSegue
方法中設置它們,如下所示:
overide func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "indivQuoteSegue") {
let svc = segue.destinationViewController as! QuoteView
let quote = quoteArray[(tableView.indexPathForSelectedRow?.row)!];
svc.quoteTitle.text = quote.getQuoteTitle()
svc.quoteAuthor.text = quote.getQuoteAuthor()
svc.quoteContent.text = quote.getQuoteContent()
svc.quoteCategory.text = quote.getCategory()
svc.quoteTimestamp.text = quote.getQuoteTimestamp()
}
}
在prepareForSegue
您的出口尚未初始化,因此您無法設置它們的屬性。 你應該創建String屬性並設置它們,或者更好,只需傳遞你的quote
對象。 例如:
overide func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "indivQuoteSegue") {
let svc = segue.destinationViewController as! QuoteView
let quote = quoteArray[(tableView.indexPathForSelectedRow?.row)!];
svc.quoteTitleString = quote.getQuoteTitle()
svc.quoteAuthorString = quote.getQuoteAuthor()
svc.quoteContentString = quote.getQuoteContent()
svc.quoteCategoryString = quote.getCategory()
svc.quoteTimestampString = quote.getQuoteTimestamp()
}
}
然后在QuoteView
的viewDidLoad
中設置標簽的文本
override func viewDidLoad(){
self.quoteTitle.text = self.quoteTitleString
etc...
}
它的發生是因為通常UI(視圖)元素在調用viewDidLoad之前還沒有准備好進行操作。
這里一個優雅的解決方案是在QuoteView中創建一個“quote”屬性並將其設置為“prepareForSegue”。 然后使用該quote屬性在viewDidLoad或viewWillAppear方法中加載UI元素。 有關詳細信息,請參閱@Duncan C的答案。
overide func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "indivQuoteSegue") {
let svc = segue.destinationViewController as! QuoteView
svc.quote = quoteArray[(tableView.indexPathForSelectedRow?.row)!];
}
}
然后在QuoteView中
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
self.quoteTitle.text = self.quote.getQuoteTitle()
self.quoteAuthor.text = self.quote.getQuoteAuthor()
self.quoteContent.text = self.quote.getQuoteContent()
self.quoteCategory.text = self.quote.getCategory()
self.quoteTimestamp.text = self.quote.getQuoteTimestamp()
}
稍微退一步“為什么它不起作用”的問題試圖從視圖控制器外部設置視圖控制器的出口,我給你一個平坦的規則:
“不要這樣做。”
您應該將另一個視圖控制器出口視為私有,而不是試圖操縱它們。 這違反了封裝原則,也是OO設計中的重要思想。
想象一下:我有一個立體聲設備的控制面板對象。 控制面板上有一堆控制UI對象,可以讓用戶設置均衡,降噪等。然后它有一個公共API,用於與系統的其他軟件組件連接。
如果其他對象進入我的控制面板並執行諸如更改均衡滑塊的值之類的操作,那么我以后就無法返回並將均衡器的UI元素替換為使用撥號,數字輸入或其他一些UI元素,沒有打破應用程序的其余部分。 我已將程序中的其他對象緊密耦合到應該是我的控制面板對象的私有實現的一部分。
在您的情況下,它是平面不起作用,因為在prepareForSegue中尚未加載目標視圖控制器的視圖。
即使在它可以工作的情況下,你仍然不應該這樣做。
相反,您應該創建視圖控制器的公共屬性,讓外部對象指定設置的值。 然后視圖控制器的viewWillAppear方法應該將這些屬性中的值應用於UI。
當您這樣做時,如果您稍后對UI進行更改,您所要做的就是確保公共屬性仍然按預期工作。
@beyowulf和@harshitgupta詳細介紹了如何以正確的方式做到這一點。 (雖然我認為將屬性安裝到UI中的代碼應該在viewWillAppear中,而不是viewDidLoad。這樣,如果顯示視圖控制器,由另一個更改其值的視圖控制器覆蓋,然后被覆蓋,它會更新再次顯示時,屏幕上的值會更改。)
您不能在segue中分配它們,因為它們尚未初始化,您可能會考慮使用可選綁定但它也不會起作用,解決方案是將您的數據結構或類作為var傳遞給segued視圖然后更新將它放在viewDidLoad()中的新ViewController中或使用didSet {}。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.