我在iOS中做了一个表视图,显示了Buddy(friend)请求列表。对于Buddy请求单元,我将其制成了原型单元格,并给了它一个自定义类,该类别从UaithitViewCell延伸。当我单击单元格上的"接受"按钮时,我想从我的请求数组中删除该行,并将其从表视图中删除。
我考虑的三个选项是
1)给自定义单元一个行的属性,该属性与表中的行相对应,因此,请求数组中的行。然后,当调用接受时,将该行传递到委托功能并调用
requests.removeAtIndex(row)
tableView.reloadData()
更新所有自定义单元的行属性。此方法有效。但是,这是重新加载表数据的不良习惯(仅从存储的数组重新加载,而不是进行网络请求)
)2)将自定义单元格属于行属性,但随后调用
self.requests.removeAtIndex(row)
self.requestsTableView.beginUpdates()
self.requestsTableView.deleteRowsAtIndexPaths([NSIndexPath(forRow:row, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade)
self.requestsTableView.endUpdates()
但是,这不会更新已删除的单元格之后的每个单元格中的行值,我要么以某种方式必须全部更新它们,要么调用ReloDdata(),而不是我想做的。
3)而不是传递行值时,单击"接受"按钮时,请在"好友列表中搜索用户名",获取找到位置的索引,然后使用该索引在表中删除表中的行和deleterowsatIndExpaths。这似乎可以做到,尤其是因为我永远不会立即有大量的好友请求,并且搜索根本不需要太多时间,但是我认为如果我可以立即访问该行值,它将使事情变得更加干净。
这是代码:
查看控制器
class RequestsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, RequestTableViewCellDelegate
{
// Outlet to our table view
@IBOutlet weak var requestsTableView: UITableView!
let buddyRequestCellIdentifier: String = "buddyRequestCell"
// List of buddies who have sent us friend requests
var requests = [Buddy]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
self.getBuddyRequests()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: -Table View
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return requests.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: RequestTableViewCell = tableView.dequeueReusableCellWithIdentifier(buddyRequestCellIdentifier) as! RequestTableViewCell
let buddy = requests[indexPath.row]
let fullName = "(buddy.firstName) (buddy.lastName)"
cell.titleLabel?.text = fullName
cell.buddyUsername = buddy.username
cell.row = indexPath.row
cell.delegate = self
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let buddy = self.requests[indexPath.row]
}
func didAccpetBuddyRequest(row: Int) {
// Remove buddy at the 'row' index
// idea 1: update all cells' 'row' value
//self.requests.removeAtIndex(row)
// reloading data will reload all the cells so they will all get a new row number
//self.requestsTableView.reloadData()
// idea 2
// Using row doesn't work here becuase these values don't get changed when other cells are added/deleted
self.requests.removeAtIndex(row)
self.requestsTableView.beginUpdates()
self.requestsTableView.deleteRowsAtIndexPaths([NSIndexPath(forRow:row, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade)
self.requestsTableView.endUpdates()
// idea 3: don't use row, but search for the index by looking for the username
}
// MARK: -API
func getBuddyRequests() {
// self.requests = array of buddy requests from API request
self.requestsTableView.reloadData()
}
}
定制uitaiteViewCell和代表呼叫的协议
protocol RequestTableViewCellDelegate {
func didAccpetBuddyRequest(row: Int)
}
class RequestTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var acceptButton: UIButton!
var delegate: RequestTableViewCellDelegate?
var buddyUsername: String?
var row: Int?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func touchAccept(sender: AnyObject) {
// <code goes here to make API request to accept the buddy request>
self.delegate?.didAccpetBuddyRequest(self.row!)
}
}
感谢您抽出宝贵的时间阅读此书,感谢您知道在这种情况下对我有帮助的任何帮助/最佳实践。
允许单元格给indexPath
和delegate
属性,然后何时敲击"接受"按钮时通知委托。但是,您确实需要致电reloadData()
来更新受影响的单元格中的引用。
如果您想最大程度地减少重新加载行的数量,请致电reloadRowsAtIndexPaths()
,但是我认为创建创建NSIndexPath
对象的循环会使您的应用程序慢慢降低。
作为替代方案,我可以另一种建议:
首先在ViewController中将操作方法添加到AcceptButton。在该方法内部,您可以获取包含按钮的单元格的indexpath。这是实施
@IBAction func acceptDidTap(sender: UIButton) {
let point = tableView.convertPoint(CGPoint.zeroPoint, fromView: button)
if let indexPath = tableView.indexPathForRowAtPoint(point) {
// here you got which cell's acceptButton triggered the action
}
}