数据未在视图控制器之间传输 Swift
Data not being transferred between view controllers Swift
当 EventTableViewController 继续到 UserEventViewController 或 EventViewController 时,数据不会传输,因为标签等不会更新为传输的信息。我已经尝试修复它,但它仍然不起作用。请帮助。
任何帮助将不胜感激。
Link 投射:
https://www.dropbox.com/s/1d4d8opuxzpcuk4/TicketekApp.zip?dl=0
代码:
// EventTableViewController.swift
import UIKit
class EventTableViewController: UITableViewController {
// MARK: Properties
var events = [Event]()
var isAdmin = true
override func viewDidLoad() {
super.viewDidLoad()
// Use the edit button item provided by the table view controller.
navigationItem.leftBarButtonItem = editButtonItem()
// Load any saved events, otherwise load sample data.
if let savedEvents = loadEvents() {
events += savedEvents
} else {
// Load the sample data.
loadSampleEvents()
}
}
func loadSampleEvents() {
let photo1 = UIImage(named: "event1")!
let event1 = Event(name: "ACDC", photo: photo1, rating: 4, price: 500.0, eventDescription: "Album", album: "Album1")!
let photo2 = UIImage(named: "event2")!
let event2 = Event(name: "Cold Play", photo: photo2, rating: 5, price: 500.0, eventDescription: "Album", album: "Album1")!
let photo3 = UIImage(named: "event3")!
let event3 = Event(name: "One Direction", photo: photo3, rating: 3, price: 500.0, eventDescription: "Album", album: "Album1")!
events += [event1, event2, event3]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "EventTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! EventTableViewCell
// Fetches the appropriate event for the data source layout.
let event = events[indexPath.row]
cell.nameLabel.text = event.name
cell.photoImageView.image = event.photo
cell.ratingControl.rating = event.rating
cell.priceLabel.text = event.album
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let index = self.tableView.indexPathForSelectedRow?.row
//use the index to know which cell you selected
//check for your condition here something like
if isAdmin {
performSegueWithIdentifier("eventViewControllerSegue", sender: self)
} else {
performSegueWithIdentifier("userEventTableViewControllerSegue", sender: self)
}
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
events.removeAtIndex(indexPath.row)
saveEvents()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create new instance of class, add to the array, and add a new row to the table
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "eventViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! EventViewController
// Get the cell that generated this segue.
if let selectedEventCell = sender as? EventTableViewCell {
let indexPath = tableView.indexPathForCell(selectedEventCell)!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent
}
} else if segue.identifier == "userEventTableViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! UserEventViewController
// Get the cell that generated this segue.
if let selectedEventCell = sender as? EventTableViewCell {
let indexPath = tableView.indexPathForCell(selectedEventCell)!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent
}
}
else if segue.identifier == "AddItem" {
print("Adding new event.")
}
}
@IBAction func unwindToMealList(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? EventViewController, event = sourceViewController.event {
if let selectedIndexPath = tableView.indexPathForSelectedRow {
// Update an existing event.
events[selectedIndexPath.row] = event
tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
} else {
// Add a new event.
let newIndexPath = NSIndexPath(forRow: events.count, inSection: 0)
events.append(event)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
}
// Save the events.
saveEvents()
}
}
// MARK: NSCoding
func saveEvents() {
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(events, toFile: Event.ArchiveURL.path!)
if !isSuccessfulSave {
print("Failed to save events...")
}
}
func loadEvents() -> [Event]? {
return NSKeyedUnarchiver.unarchiveObjectWithFile(Event.ArchiveURL.path!) as? [Event]
}
}
您通常希望查找与所选行相关的事件。因此,您需要记录选择了哪一行。引入一个变量叫做:
var currentlySelectedIndex = 0
到您的 EventTableViewController
然后将同一个class中的didSelectRow委托方法的实现改成-
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//Record the row selected
currentlySelectedIndex = indexPath.row
//check for your condition here something like
if isAdmin {
performSegueWithIdentifier("eventViewControllerSegue", sender: self)
} else {
performSegueWithIdentifier("userEventTableViewControllerSegue", sender: self)
}
}
第三,您需要利用这个选定的行索引来获取正确的事件对象:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "eventViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! EventViewController
//Get the associated event
eventDetailViewController.event = events[currentlySelectedIndex]
} else if segue.identifier == "userEventTableViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! UserEventViewController
//Get the associated event
eventDetailViewController.event = events[currentlySelectedIndex]
}
else if segue.identifier == "AddItem" {
print("Adding new event.")
}
}
这将解决您的问题。
Shripada 的回答是正确的,毫无疑问。但是,我想解释一下为什么您的代码无法正常工作。
您正在从 tableView:didSelectRowAtIndexPath
方法调用 performSegueWithIdentifier("eventViewControllerSegue", sender: self)
。请注意这里的 sender: self 是 ViewController 而不是 tableCell。现在,当它触发 prepareForSegue
时,您正在尝试使用 let selectedEventCell = sender as? EventTableViewCell
访问选定的单元格。但是,发送者不是 EventTableCell。这就是为什么你得到一个 nil 值并且你的 if 条件失败的原因。
一个简单的解决方法是在 prepareForSegue
中使用 tableView.indexPathForSelectedRow!
获取选定的 tableViewCell,并将适当的数据传递给目标 ViewController。
let eventDetailViewController = segue.destinationViewController as! EventViewController
// Get the indexPath of selected cell
let indexPath = self.tableView.indexPathForSelectedRow!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent
当 EventTableViewController 继续到 UserEventViewController 或 EventViewController 时,数据不会传输,因为标签等不会更新为传输的信息。我已经尝试修复它,但它仍然不起作用。请帮助。
任何帮助将不胜感激。 Link 投射: https://www.dropbox.com/s/1d4d8opuxzpcuk4/TicketekApp.zip?dl=0
代码:
// EventTableViewController.swift
import UIKit
class EventTableViewController: UITableViewController {
// MARK: Properties
var events = [Event]()
var isAdmin = true
override func viewDidLoad() {
super.viewDidLoad()
// Use the edit button item provided by the table view controller.
navigationItem.leftBarButtonItem = editButtonItem()
// Load any saved events, otherwise load sample data.
if let savedEvents = loadEvents() {
events += savedEvents
} else {
// Load the sample data.
loadSampleEvents()
}
}
func loadSampleEvents() {
let photo1 = UIImage(named: "event1")!
let event1 = Event(name: "ACDC", photo: photo1, rating: 4, price: 500.0, eventDescription: "Album", album: "Album1")!
let photo2 = UIImage(named: "event2")!
let event2 = Event(name: "Cold Play", photo: photo2, rating: 5, price: 500.0, eventDescription: "Album", album: "Album1")!
let photo3 = UIImage(named: "event3")!
let event3 = Event(name: "One Direction", photo: photo3, rating: 3, price: 500.0, eventDescription: "Album", album: "Album1")!
events += [event1, event2, event3]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "EventTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! EventTableViewCell
// Fetches the appropriate event for the data source layout.
let event = events[indexPath.row]
cell.nameLabel.text = event.name
cell.photoImageView.image = event.photo
cell.ratingControl.rating = event.rating
cell.priceLabel.text = event.album
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let index = self.tableView.indexPathForSelectedRow?.row
//use the index to know which cell you selected
//check for your condition here something like
if isAdmin {
performSegueWithIdentifier("eventViewControllerSegue", sender: self)
} else {
performSegueWithIdentifier("userEventTableViewControllerSegue", sender: self)
}
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
events.removeAtIndex(indexPath.row)
saveEvents()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create new instance of class, add to the array, and add a new row to the table
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "eventViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! EventViewController
// Get the cell that generated this segue.
if let selectedEventCell = sender as? EventTableViewCell {
let indexPath = tableView.indexPathForCell(selectedEventCell)!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent
}
} else if segue.identifier == "userEventTableViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! UserEventViewController
// Get the cell that generated this segue.
if let selectedEventCell = sender as? EventTableViewCell {
let indexPath = tableView.indexPathForCell(selectedEventCell)!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent
}
}
else if segue.identifier == "AddItem" {
print("Adding new event.")
}
}
@IBAction func unwindToMealList(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? EventViewController, event = sourceViewController.event {
if let selectedIndexPath = tableView.indexPathForSelectedRow {
// Update an existing event.
events[selectedIndexPath.row] = event
tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
} else {
// Add a new event.
let newIndexPath = NSIndexPath(forRow: events.count, inSection: 0)
events.append(event)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
}
// Save the events.
saveEvents()
}
}
// MARK: NSCoding
func saveEvents() {
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(events, toFile: Event.ArchiveURL.path!)
if !isSuccessfulSave {
print("Failed to save events...")
}
}
func loadEvents() -> [Event]? {
return NSKeyedUnarchiver.unarchiveObjectWithFile(Event.ArchiveURL.path!) as? [Event]
}
}
您通常希望查找与所选行相关的事件。因此,您需要记录选择了哪一行。引入一个变量叫做:
var currentlySelectedIndex = 0
到您的 EventTableViewController
然后将同一个class中的didSelectRow委托方法的实现改成-
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//Record the row selected
currentlySelectedIndex = indexPath.row
//check for your condition here something like
if isAdmin {
performSegueWithIdentifier("eventViewControllerSegue", sender: self)
} else {
performSegueWithIdentifier("userEventTableViewControllerSegue", sender: self)
}
}
第三,您需要利用这个选定的行索引来获取正确的事件对象:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "eventViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! EventViewController
//Get the associated event
eventDetailViewController.event = events[currentlySelectedIndex]
} else if segue.identifier == "userEventTableViewControllerSegue" {
let eventDetailViewController = segue.destinationViewController as! UserEventViewController
//Get the associated event
eventDetailViewController.event = events[currentlySelectedIndex]
}
else if segue.identifier == "AddItem" {
print("Adding new event.")
}
}
这将解决您的问题。
Shripada 的回答是正确的,毫无疑问。但是,我想解释一下为什么您的代码无法正常工作。
您正在从 tableView:didSelectRowAtIndexPath
方法调用 performSegueWithIdentifier("eventViewControllerSegue", sender: self)
。请注意这里的 sender: self 是 ViewController 而不是 tableCell。现在,当它触发 prepareForSegue
时,您正在尝试使用 let selectedEventCell = sender as? EventTableViewCell
访问选定的单元格。但是,发送者不是 EventTableCell。这就是为什么你得到一个 nil 值并且你的 if 条件失败的原因。
一个简单的解决方法是在 prepareForSegue
中使用 tableView.indexPathForSelectedRow!
获取选定的 tableViewCell,并将适当的数据传递给目标 ViewController。
let eventDetailViewController = segue.destinationViewController as! EventViewController
// Get the indexPath of selected cell
let indexPath = self.tableView.indexPathForSelectedRow!
let selectedEvent = events[indexPath.row]
eventDetailViewController.event = selectedEvent