Swift:单击时更改 table 视图中的按钮图像
Swift: Change button image in table view on click
我使用 Swift 为 iPhone 创建了一个 Xcode 项目,后端使用 Parse。我当前的问题是将待办事项列表应用程序创建为较大应用程序的一个选项卡。
在自定义原型单元格内,我想要一个复选框按钮,它在单击时更改其图像以及更改该单元格的 isChecked:Bool 变量。我已经了解了大部分内容,但是我 运行 遇到了有关设置和访问此按钮的适当变量的问题。
编辑:感谢下面的答案和其他资源,我终于为这个复选框功能编写了工作代码。本质上,按钮的标签 属性 设置为等于 PFObject 的 indexPath.row。由于我最初的问题有点宽泛,我正在更新下面的代码,以便它可以帮助其他正在处理类似功能的新开发人员。可能有更好的方法,但这似乎有效。
// TasksVC.swift
var taskObjects:NSMutableArray! = NSMutableArray()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.fetchAllObjects()
}
func fetchAllObjects() {
var query:PFQuery = PFQuery(className: "Task")
query.whereKey("username", equalTo: PFUser.currentUser()!)
query.orderByAscending("dueDate")
query.addAscendingOrder("desc")
//fetches values within pointer object
query.includeKey("deal")
query.findObjectsInBackgroundWithBlock { (tasks: [AnyObject]!, error:NSError!) -> Void in
if (error == nil) {
var temp:NSArray = tasks! as NSArray
self.taskObjects = temp.mutableCopy() as NSMutableArray
self.tableView.reloadData()
println("Fetched objects from server")
} else {
println(error?.userInfo)
}
}
}
//MARK: - Tasks table view
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.taskObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as TaskCell
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/dd/yy"
var task:PFObject = self.taskObjects.objectAtIndex(indexPath.row) as PFObject
cell.desc_Lbl?.text = task["desc"] as? String
cell.date_Lbl.text = dateFormatter.stringFromDate(task["dueDate"] as NSDate)
//value of client within Deal pointer object
if let deal = task["deal"] as? PFObject {
// deal column has data
if let client = deal["client"] as? String {
// client has data
cell.client_Lbl?.text = client
}
}
//set the tag for the cell's UIButton equal to the indexPath of the cell
cell.checkbox_Btn.tag = indexPath.row
cell.checkbox_Btn.addTarget(self, action: "checkCheckbox:", forControlEvents: UIControlEvents.TouchUpInside)
cell.checkbox_Btn.selected = task["isCompleted"] as Bool
if (task["isCompleted"] != nil) {
cell.checkbox_Btn.setBackgroundImage(UIImage(named:(cell.checkbox_Btn.selected ? "CheckedCheckbox" : "UncheckedCheckbox")), forState:UIControlState.Normal)
}
cell.selectionStyle = .None
return cell
}
func checkCheckbox(sender:UIButton!) {
var senderBtn:UIButton = sender as UIButton
println("current row: \(senderBtn.tag)")
//retrieve the PFObject for the row we have selected
var task:PFObject = self.taskObjects.objectAtIndex(senderBtn.tag) as PFObject
println("objectID: \(task.objectId)")
if task["isCompleted"] as NSObject == true {
task["isCompleted"] = false
} else {
task["isCompleted"] = true
}
task.saveInBackgroundWithBlock { (success, error) -> Void in
if (error == nil) {
println("saved checkbox object in background")
} else {
println(error!.userInfo)
}
}
self.tableView.reloadData()
}
override func tableView(tableView: UITableView?, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView?, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
var task:PFObject = self.taskObjects.objectAtIndex(indexPath.row) as PFObject
task.deleteInBackgroundWithBlock({ (success, error) -> Void in
self.fetchAllObjects()
self.taskObjects.removeObjectAtIndex(indexPath.row)
})
} else if editingStyle == .Insert {
}
}
使用表和集合视图时,自定义单元格中的所有对象都可以在 cellForRowAtIndexPath(用于 UITables)中轻松访问
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("ActionCell", forIndexPath: indexPath) as ActionCell
var action = actions[indexPath.row] as Action
cell.nameLabel?.text = action.name
cell.listLabel?.text = action.list
cell.dateLabel?.text = action.date
cell.checkboxButton = action.isChecked
cell.checkBoxButton.setImage(UIImage(named:"checkedImage"), forState:UIControlState.Normal)
return cell
}
此外,我建议将常量更改为变量。我也是 Swift 的新手,"let" 声明了一个静态变量。
我发现在这些情况下使用条件运算符 (?:) 非常酷:
cell.checkBoxButton.setImage(UIImage(named:(any_boolean_condition ? "checkedImage" : "uncheckedImage")), forState:UIControlState.Normal)
因此它可以 return 一个图像名称用于条件 True,另一个名称用于条件 False。
我使用 Swift 为 iPhone 创建了一个 Xcode 项目,后端使用 Parse。我当前的问题是将待办事项列表应用程序创建为较大应用程序的一个选项卡。
在自定义原型单元格内,我想要一个复选框按钮,它在单击时更改其图像以及更改该单元格的 isChecked:Bool 变量。我已经了解了大部分内容,但是我 运行 遇到了有关设置和访问此按钮的适当变量的问题。
编辑:感谢下面的答案和其他资源,我终于为这个复选框功能编写了工作代码。本质上,按钮的标签 属性 设置为等于 PFObject 的 indexPath.row。由于我最初的问题有点宽泛,我正在更新下面的代码,以便它可以帮助其他正在处理类似功能的新开发人员。可能有更好的方法,但这似乎有效。
// TasksVC.swift
var taskObjects:NSMutableArray! = NSMutableArray()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.fetchAllObjects()
}
func fetchAllObjects() {
var query:PFQuery = PFQuery(className: "Task")
query.whereKey("username", equalTo: PFUser.currentUser()!)
query.orderByAscending("dueDate")
query.addAscendingOrder("desc")
//fetches values within pointer object
query.includeKey("deal")
query.findObjectsInBackgroundWithBlock { (tasks: [AnyObject]!, error:NSError!) -> Void in
if (error == nil) {
var temp:NSArray = tasks! as NSArray
self.taskObjects = temp.mutableCopy() as NSMutableArray
self.tableView.reloadData()
println("Fetched objects from server")
} else {
println(error?.userInfo)
}
}
}
//MARK: - Tasks table view
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.taskObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as TaskCell
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/dd/yy"
var task:PFObject = self.taskObjects.objectAtIndex(indexPath.row) as PFObject
cell.desc_Lbl?.text = task["desc"] as? String
cell.date_Lbl.text = dateFormatter.stringFromDate(task["dueDate"] as NSDate)
//value of client within Deal pointer object
if let deal = task["deal"] as? PFObject {
// deal column has data
if let client = deal["client"] as? String {
// client has data
cell.client_Lbl?.text = client
}
}
//set the tag for the cell's UIButton equal to the indexPath of the cell
cell.checkbox_Btn.tag = indexPath.row
cell.checkbox_Btn.addTarget(self, action: "checkCheckbox:", forControlEvents: UIControlEvents.TouchUpInside)
cell.checkbox_Btn.selected = task["isCompleted"] as Bool
if (task["isCompleted"] != nil) {
cell.checkbox_Btn.setBackgroundImage(UIImage(named:(cell.checkbox_Btn.selected ? "CheckedCheckbox" : "UncheckedCheckbox")), forState:UIControlState.Normal)
}
cell.selectionStyle = .None
return cell
}
func checkCheckbox(sender:UIButton!) {
var senderBtn:UIButton = sender as UIButton
println("current row: \(senderBtn.tag)")
//retrieve the PFObject for the row we have selected
var task:PFObject = self.taskObjects.objectAtIndex(senderBtn.tag) as PFObject
println("objectID: \(task.objectId)")
if task["isCompleted"] as NSObject == true {
task["isCompleted"] = false
} else {
task["isCompleted"] = true
}
task.saveInBackgroundWithBlock { (success, error) -> Void in
if (error == nil) {
println("saved checkbox object in background")
} else {
println(error!.userInfo)
}
}
self.tableView.reloadData()
}
override func tableView(tableView: UITableView?, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView?, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
var task:PFObject = self.taskObjects.objectAtIndex(indexPath.row) as PFObject
task.deleteInBackgroundWithBlock({ (success, error) -> Void in
self.fetchAllObjects()
self.taskObjects.removeObjectAtIndex(indexPath.row)
})
} else if editingStyle == .Insert {
}
}
使用表和集合视图时,自定义单元格中的所有对象都可以在 cellForRowAtIndexPath(用于 UITables)中轻松访问
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("ActionCell", forIndexPath: indexPath) as ActionCell
var action = actions[indexPath.row] as Action
cell.nameLabel?.text = action.name
cell.listLabel?.text = action.list
cell.dateLabel?.text = action.date
cell.checkboxButton = action.isChecked
cell.checkBoxButton.setImage(UIImage(named:"checkedImage"), forState:UIControlState.Normal)
return cell
}
此外,我建议将常量更改为变量。我也是 Swift 的新手,"let" 声明了一个静态变量。
我发现在这些情况下使用条件运算符 (?:) 非常酷:
cell.checkBoxButton.setImage(UIImage(named:(any_boolean_condition ? "checkedImage" : "uncheckedImage")), forState:UIControlState.Normal)
因此它可以 return 一个图像名称用于条件 True,另一个名称用于条件 False。