Swift 视图控制器之间传输的数据保持为空
Swift Transferred Data between View Controllers stays empty
我是 Swift 的新手。我正在尝试在两个视图控制器之间传递数据。当第二个视图控制器使用时,我从第一个视图控制器传递的值是 nil。我不明白为什么会这样。
这是我在第一个视图控制器中的 tableView
函数调用。它获取所选 table 单元格的用户信息。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let user = User()
if(messages.count > 0) {
let message = self.messages[indexPath.row]
guard let chatPartnerID = message.chatPartnerID() else {
return
}
let ref = FIRDatabase.database().reference().child("users").child(chatPartnerID)
ref.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject]
else {
return
}
user.id = chatPartnerID
user.setValuesForKeysWithDictionary(dictionary)
self.setupChatLogControllerForUser(user)
}, withCancelBlock: nil)
}else {
let user = users[indexPath.row]
self.setupChatLogControllerForUser(user)
}
}
User
在 NSObject
中,我这样声明:
class User: NSObject {
var id: String?
var name: String?
var email: String?
var profileImageUrl: String?
}
第一个视图控制器中的 setupChatLogControllerForUser(user)
方法接收在 tableView
方法中给出的用户参数并传递给第二个视图控制器 (ChatLogController
),如下所示:
func setupChatLogControllerForUser(user: User) {
let chatLogController = ChatLogController()
chatLogController.selectedUserID = user.id!
chatLogController.user = user
}
我的第二个 View Controller 方法用这个接收数据:
var selectedUserID = String()
var user = User()
第二个视图控制器也有一个 handleSend
方法,它通过 IBAction
链接到我故事板上的一个按钮。
func handleSend() {
let ref = FIRDatabase.database().reference().child("messages")
let childRef = ref.childByAutoId()
let toID = self.selectedUserID
let fromID = FIRAuth.auth()!.currentUser!.uid
let timestamp: NSNumber = Int(NSDate().timeIntervalSince1970)
let values = ["text": messageInputField.text!, "toID": toID, "fromID": fromID, "timestamp": timestamp]
childRef.updateChildValues(values) { (error, ref) in
if error != nil {
print(error)
return
}
let userMessagesRef = FIRDatabase.database().reference().child("userMessages").child(fromID)
let messageID = childRef.key
userMessagesRef.updateChildValues([messageID: 1])
let recipientUserMessagesRef = FIRDatabase.database().reference().child("userMessages").child(toID)
recipientUserMessagesRef.updateChildValues([messageID: 1])
}
}
这个方法就是出问题的地方。我设置 toID
等于 selectedUserID
。在调试器中,当视图控制器转到 ChatLogController
时,我可以看到 selectedUserID
填充了一个字符串。为什么调用方法时selectedUserID
变量的值是nil?
我知道传入 selectedUserID
和 User
对象是多余的,我只是想看看问题是否出在 类 之间传递的 String 变量上, 但它保持为零。
任何帮助都会很棒!
编辑:
我正在使用 segue 在我的视图控制器之间切换
你不需要实例化ChatLogController来传递数据,因为如果你正确设置了NavigationController,那么他会为你实例化。
func setupChatLogControllerForUser(user: User) {
let chatLogController = ChatLogController()
chatLogController.selectedUserID = user.id!
chatLogController.user = user
}
因此,如果您想将数据传递给 ChatLogController,您应该为此目的使用 prepareForSegue 方法。
我将提供一个基本示例,您可以如何模仿此类功能:
这是结果:
这是我的故事板:
请注意,segue 的名称是 showDetail,如图所示。
这是我的表ViewController的代码:
当我触摸 TableViewController 上的单元格时,调用 didSelectRowAtIndexPath 方法,然后我访问该单元格选择并将值设置为 dataToSend 变量,最后我调用 performSegueWithIdentifier 以导航到 ViewController.
但就在它进入 ViewController 之前,prepareForSegue 方法被调用,所以你有机会在这里通过任何ViewController 期望的变量,在这种情况下,我将 dataToSend 传递给 ViewController 的 dataSent 变量。
class TableViewController: UITableViewController {
var dataToSend = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
dataToSend = cell!.textLabel!.text!
performSegueWithIdentifier("showDetail", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let viewController = segue.destinationViewController as? ViewController {
viewController.dataSent = dataToSend
}
}
}
}
这是 ViewController 的代码:
然后我可以在标签中显示值。
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var dataSent = String()
override func viewDidLoad() {
super.viewDidLoad()
label.text = dataSent
}
}
我是 Swift 的新手。我正在尝试在两个视图控制器之间传递数据。当第二个视图控制器使用时,我从第一个视图控制器传递的值是 nil。我不明白为什么会这样。
这是我在第一个视图控制器中的 tableView
函数调用。它获取所选 table 单元格的用户信息。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let user = User()
if(messages.count > 0) {
let message = self.messages[indexPath.row]
guard let chatPartnerID = message.chatPartnerID() else {
return
}
let ref = FIRDatabase.database().reference().child("users").child(chatPartnerID)
ref.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject]
else {
return
}
user.id = chatPartnerID
user.setValuesForKeysWithDictionary(dictionary)
self.setupChatLogControllerForUser(user)
}, withCancelBlock: nil)
}else {
let user = users[indexPath.row]
self.setupChatLogControllerForUser(user)
}
}
User
在 NSObject
中,我这样声明:
class User: NSObject {
var id: String?
var name: String?
var email: String?
var profileImageUrl: String?
}
第一个视图控制器中的 setupChatLogControllerForUser(user)
方法接收在 tableView
方法中给出的用户参数并传递给第二个视图控制器 (ChatLogController
),如下所示:
func setupChatLogControllerForUser(user: User) {
let chatLogController = ChatLogController()
chatLogController.selectedUserID = user.id!
chatLogController.user = user
}
我的第二个 View Controller 方法用这个接收数据:
var selectedUserID = String()
var user = User()
第二个视图控制器也有一个 handleSend
方法,它通过 IBAction
链接到我故事板上的一个按钮。
func handleSend() {
let ref = FIRDatabase.database().reference().child("messages")
let childRef = ref.childByAutoId()
let toID = self.selectedUserID
let fromID = FIRAuth.auth()!.currentUser!.uid
let timestamp: NSNumber = Int(NSDate().timeIntervalSince1970)
let values = ["text": messageInputField.text!, "toID": toID, "fromID": fromID, "timestamp": timestamp]
childRef.updateChildValues(values) { (error, ref) in
if error != nil {
print(error)
return
}
let userMessagesRef = FIRDatabase.database().reference().child("userMessages").child(fromID)
let messageID = childRef.key
userMessagesRef.updateChildValues([messageID: 1])
let recipientUserMessagesRef = FIRDatabase.database().reference().child("userMessages").child(toID)
recipientUserMessagesRef.updateChildValues([messageID: 1])
}
}
这个方法就是出问题的地方。我设置 toID
等于 selectedUserID
。在调试器中,当视图控制器转到 ChatLogController
时,我可以看到 selectedUserID
填充了一个字符串。为什么调用方法时selectedUserID
变量的值是nil?
我知道传入 selectedUserID
和 User
对象是多余的,我只是想看看问题是否出在 类 之间传递的 String 变量上, 但它保持为零。
任何帮助都会很棒!
编辑: 我正在使用 segue 在我的视图控制器之间切换
你不需要实例化ChatLogController来传递数据,因为如果你正确设置了NavigationController,那么他会为你实例化。
func setupChatLogControllerForUser(user: User) {
let chatLogController = ChatLogController()
chatLogController.selectedUserID = user.id!
chatLogController.user = user
}
因此,如果您想将数据传递给 ChatLogController,您应该为此目的使用 prepareForSegue 方法。
我将提供一个基本示例,您可以如何模仿此类功能:
这是结果:
这是我的故事板:
请注意,segue 的名称是 showDetail,如图所示。
这是我的表ViewController的代码:
当我触摸 TableViewController 上的单元格时,调用 didSelectRowAtIndexPath 方法,然后我访问该单元格选择并将值设置为 dataToSend 变量,最后我调用 performSegueWithIdentifier 以导航到 ViewController.
但就在它进入 ViewController 之前,prepareForSegue 方法被调用,所以你有机会在这里通过任何ViewController 期望的变量,在这种情况下,我将 dataToSend 传递给 ViewController 的 dataSent 变量。
class TableViewController: UITableViewController {
var dataToSend = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
dataToSend = cell!.textLabel!.text!
performSegueWithIdentifier("showDetail", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let viewController = segue.destinationViewController as? ViewController {
viewController.dataSent = dataToSend
}
}
}
}
这是 ViewController 的代码:
然后我可以在标签中显示值。
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var dataSent = String()
override func viewDidLoad() {
super.viewDidLoad()
label.text = dataSent
}
}