如何获取数据以保存到表视图中的特定类别而不是所有类别?
how to get data to save to specific category in tableview instead on all categories?
我有一个 groceryList 应用程序
当您将一个项目添加到类别列表时,它会添加到整个类别列表,而这是不应该的!
https://github.com/mrbryankmiller/Grocery-TableView-.git
class GroceryItemsTableViewController: UITableViewController {
//var groceryItem = ["Item1", "Item2", "Item3"]
//var groceryList = ["Breakfast","Lunch", "Dinner"]
@IBOutlet var groceryItemTableView: UITableView!
@IBAction func addGroceryItemButtonPressed(sender: UIBarButtonItem) {
///new way///
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Item", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
let textField = alertController.textFields![0]
groceryItem.items.append(textField.text!)
self.tableView.reloadData()
}
alertController.addAction(saveAction)
//Add text field
// alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
// textField.textColor = UIColor.blackColor()
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return groceryItem.items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("groceryItem1", forIndexPath: indexPath)
cell.textLabel!.text = groceryItem.items [indexPath.row]
return cell
}
}
如果您仔细查看 class groceryItem
的声明,您的购物清单中的每个项目都有一个 static
元素数组,因此每次添加新元素时在所有杂货中共享。
相反,对于每个杂货项目,您应该有一个与其每个项目关联的列表。
您可以定义一个新的 struct
来为每个杂货项目保存其关联的项目列表,如下所示:
struct GroceryItem {
var name: String
var items: [String]
}
我们将对您 GroceryListTableViewController
中的代码稍作改动,以根据您的新模型重构代码,因此它应该如下所示:
GroceryListTableViewController
:
class GroceryListTableViewController: UITableViewController, GroceryItemsTableViewControllerProtocol {
var groceryList = [GroceryItem]()
@IBAction func addButton(sender: UIBarButtonItem) {
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Category", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
let textField = alertController.textFields![0]
self.groceryList.append(GroceryItem(name: textField.text!, items: [String]()))
self.tableView.reloadData()
}
alertController.addAction(saveAction)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//edit button
self.navigationItem.leftBarButtonItem = self.editButtonItem()
groceryList.append(GroceryItem(name: "Breakfast", items: ["Item1", "Item2", "Item3"]))
groceryList.append(GroceryItem(name: "Lunch", items: ["Item1", "Item2", "Item3"]))
groceryList.append(GroceryItem(name: "Dinner", items: ["Item1", "Item2", "Item3"]))
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return groceryList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("prototype1", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = groceryList [indexPath.row].name
return cell
}
// pass a tableview cell value to navigationBar title in swift//
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationVC = segue.destinationViewController as! GroceryItemsTableViewController
let cell = sender as! UITableViewCell
let idx = self.tableView.indexPathForSelectedRow?.row
destinationVC.delegate = self
destinationVC.itemList = groceryList[idx!].items
destinationVC.navigationItem.title = cell.textLabel?.text
}
func didAddGroceryItem(itemName: String) {
let idx = self.tableView.indexPathForSelectedRow?.row
groceryList[idx!].items.append(itemName)
}
func didRemoveGroceryItem(index: Int) {
let idx = self.tableView.indexPathForSelectedRow?.row
groceryList[idx!].items.removeAtIndex(index)
}
}
上面我已经重构了所有关于新模型的代码,我只把代码更改的地方放在那里,其余保持不变。
您需要将与所选单元格关联的项目传递给另一个 UIViewController
,您可以在 prepareForSegue
中轻松完成。为此,我们需要获取所选单元格的索引并将元素传递给另一个 UIViewController
,我们在其中创建了一个 [String]
的新数组作为数据源来显示项目。
代码中的另一个重点是 GroceryListTableViewController
现在实现了一个名为 GroceryItemsTableViewControllerProtocol
的新协议。该协议是每次将新项目添加到列表时从 GroceryListTableViewController
通知 GroceryListTableViewController
的方式,它称为委托模式。
GroceryItemsTableViewController
:
protocol GroceryItemsTableViewControllerProtocol: class {
func didAddGroceryItem(itemName: String)
func didRemoveGroceryItem(index: Int)
}
class GroceryItemsTableViewController: UITableViewController {
weak var delegate: GroceryItemsTableViewControllerProtocol?
var itemList: [String]!
@IBAction func addGroceryItemButtonPressed(sender: UIBarButtonItem) {
///new way///
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Item", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { [weak self] action -> Void in
guard let s = self else { return }
let textField = alertController.textFields![0]
s.itemList.append(textField.text!)
s.delegate?.didAddGroceryItem(textField.text!)
s.tableView.reloadData()
}
alertController.addAction(saveAction)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("groceryItem1", forIndexPath: indexPath)
cell.textLabel!.text = itemList[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
itemList.removeAtIndex(indexPath.row)
delegate?.didRemoveGroceryItem(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
}
编辑:
要正确处理删除,您应该创建一个新的委托方法,不通知 GroceryListTableViewController
项目已被删除,然后正确删除它,您可以在上面的更新代码中看到。
希望对你有所帮助。
我有一个 groceryList 应用程序 当您将一个项目添加到类别列表时,它会添加到整个类别列表,而这是不应该的!
https://github.com/mrbryankmiller/Grocery-TableView-.git
class GroceryItemsTableViewController: UITableViewController {
//var groceryItem = ["Item1", "Item2", "Item3"]
//var groceryList = ["Breakfast","Lunch", "Dinner"]
@IBOutlet var groceryItemTableView: UITableView!
@IBAction func addGroceryItemButtonPressed(sender: UIBarButtonItem) {
///new way///
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Item", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
let textField = alertController.textFields![0]
groceryItem.items.append(textField.text!)
self.tableView.reloadData()
}
alertController.addAction(saveAction)
//Add text field
// alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
// textField.textColor = UIColor.blackColor()
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return groceryItem.items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("groceryItem1", forIndexPath: indexPath)
cell.textLabel!.text = groceryItem.items [indexPath.row]
return cell
}
}
如果您仔细查看 class groceryItem
的声明,您的购物清单中的每个项目都有一个 static
元素数组,因此每次添加新元素时在所有杂货中共享。
相反,对于每个杂货项目,您应该有一个与其每个项目关联的列表。
您可以定义一个新的 struct
来为每个杂货项目保存其关联的项目列表,如下所示:
struct GroceryItem {
var name: String
var items: [String]
}
我们将对您 GroceryListTableViewController
中的代码稍作改动,以根据您的新模型重构代码,因此它应该如下所示:
GroceryListTableViewController
:
class GroceryListTableViewController: UITableViewController, GroceryItemsTableViewControllerProtocol {
var groceryList = [GroceryItem]()
@IBAction func addButton(sender: UIBarButtonItem) {
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Category", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
let textField = alertController.textFields![0]
self.groceryList.append(GroceryItem(name: textField.text!, items: [String]()))
self.tableView.reloadData()
}
alertController.addAction(saveAction)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//edit button
self.navigationItem.leftBarButtonItem = self.editButtonItem()
groceryList.append(GroceryItem(name: "Breakfast", items: ["Item1", "Item2", "Item3"]))
groceryList.append(GroceryItem(name: "Lunch", items: ["Item1", "Item2", "Item3"]))
groceryList.append(GroceryItem(name: "Dinner", items: ["Item1", "Item2", "Item3"]))
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return groceryList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("prototype1", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = groceryList [indexPath.row].name
return cell
}
// pass a tableview cell value to navigationBar title in swift//
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationVC = segue.destinationViewController as! GroceryItemsTableViewController
let cell = sender as! UITableViewCell
let idx = self.tableView.indexPathForSelectedRow?.row
destinationVC.delegate = self
destinationVC.itemList = groceryList[idx!].items
destinationVC.navigationItem.title = cell.textLabel?.text
}
func didAddGroceryItem(itemName: String) {
let idx = self.tableView.indexPathForSelectedRow?.row
groceryList[idx!].items.append(itemName)
}
func didRemoveGroceryItem(index: Int) {
let idx = self.tableView.indexPathForSelectedRow?.row
groceryList[idx!].items.removeAtIndex(index)
}
}
上面我已经重构了所有关于新模型的代码,我只把代码更改的地方放在那里,其余保持不变。
您需要将与所选单元格关联的项目传递给另一个 UIViewController
,您可以在 prepareForSegue
中轻松完成。为此,我们需要获取所选单元格的索引并将元素传递给另一个 UIViewController
,我们在其中创建了一个 [String]
的新数组作为数据源来显示项目。
代码中的另一个重点是 GroceryListTableViewController
现在实现了一个名为 GroceryItemsTableViewControllerProtocol
的新协议。该协议是每次将新项目添加到列表时从 GroceryListTableViewController
通知 GroceryListTableViewController
的方式,它称为委托模式。
GroceryItemsTableViewController
:
protocol GroceryItemsTableViewControllerProtocol: class {
func didAddGroceryItem(itemName: String)
func didRemoveGroceryItem(index: Int)
}
class GroceryItemsTableViewController: UITableViewController {
weak var delegate: GroceryItemsTableViewControllerProtocol?
var itemList: [String]!
@IBAction func addGroceryItemButtonPressed(sender: UIBarButtonItem) {
///new way///
let alertController: UIAlertController = UIAlertController(title: "Add Grocery Item", message: "", preferredStyle: .Alert)
//Cancel Button
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//cancel code
}
alertController.addAction(cancelAction)
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { [weak self] action -> Void in
guard let s = self else { return }
let textField = alertController.textFields![0]
s.itemList.append(textField.text!)
s.delegate?.didAddGroceryItem(textField.text!)
s.tableView.reloadData()
}
alertController.addAction(saveAction)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter an Item"
//alertController.textFields
}
//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemList.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("groceryItem1", forIndexPath: indexPath)
cell.textLabel!.text = itemList[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
itemList.removeAtIndex(indexPath.row)
delegate?.didRemoveGroceryItem(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
}
编辑:
要正确处理删除,您应该创建一个新的委托方法,不通知 GroceryListTableViewController
项目已被删除,然后正确删除它,您可以在上面的更新代码中看到。
希望对你有所帮助。