Ios 观察一个单元格';来自视图控制器的s变量
我在视图控制器中有一个表视图。单击单元中的视图时,它会隐藏或显示另一个视图,并更改单元的高度 我需要在表视图上调用一个方法来重新加载此单元格。或者我需要从我的视图控制器上观察这个单元格 这就是我的代码。非常感谢您的帮助或建议。如果我的问题不清楚,请让我知道,我会尝试更详细 细胞 视图控制器Ios 观察一个单元格';来自视图控制器的s变量,ios,swift,Ios,Swift,我在视图控制器中有一个表视图。单击单元中的视图时,它会隐藏或显示另一个视图,并更改单元的高度 我需要在表视图上调用一个方法来重新加载此单元格。或者我需要从我的视图控制器上观察这个单元格 这就是我的代码。非常感谢您的帮助或建议。如果我的问题不清楚,请让我知道,我会尝试更详细 细胞 视图控制器 import UIKit class CheckoutViewController: UIViewController { let cellSpacingHeight:CGFloat = 30.0
import UIKit
class CheckoutViewController: UIViewController {
let cellSpacingHeight:CGFloat = 30.0
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.allowsSelection = false
tableView.keyboardDismissMode = .onDrag
NotificationCenter.default.addObserver(self, selector: #selector(CheckoutViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(CheckoutViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Keyboard Notifications
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
}
}
@objc func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.2, animations: {
// For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
})
}
}
// datasource
extension CheckoutViewController: UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
// Set the spacing between sections
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return cellSpacingHeight
}
// Make the background color show through
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellID = "CheckoutAddressTableViewCellReuseID"
let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as! CheckoutAddressTableViewCell
cell.setUp(setUpCase: .billing)
cell.headerLabel.text = "BILLING INFORMATION"
// watch cell.sameAsButtonIsChecked
return cell
return UITableViewCell()
}
}
// delegate
extension CheckoutViewController:UITableViewDelegate {
}
委托模式最适合您的情况。 您需要做几件事:
protocol CheckoutAddressCellActionDelegate {
func didUpdateLayout(forCell cell: UITableViewCell)
}
CheckoutAddressTableViewCell
:
weak var delegate: CheckoutAddressCellActionDelegate?
CheckoutViewController
中,首先需要在cellForRowAt
方法中设置单元格的委托:
cell.delegate = self
CheckoutViewController
,该扩展实现了CheckoutAddressCellActionDelegate
,并重新加载单元格的indexPath:
extension CheckoutViewController: CheckoutAddressCellActionDelegate {
func didUpdateLayout(forCell cell: UITableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
}
委托模式最适合您的情况。 您需要做几件事:
protocol CheckoutAddressCellActionDelegate {
func didUpdateLayout(forCell cell: UITableViewCell)
}
CheckoutAddressTableViewCell
:
weak var delegate: CheckoutAddressCellActionDelegate?
CheckoutViewController
中,首先需要在cellForRowAt
方法中设置单元格的委托:
cell.delegate = self
CheckoutViewController
,该扩展实现了CheckoutAddressCellActionDelegate
,并重新加载单元格的indexPath:
extension CheckoutViewController: CheckoutAddressCellActionDelegate {
func didUpdateLayout(forCell cell: UITableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
}
您可以创建一个协议,并将
UIViewController
设置为每个单元格的代理,例如:
@objc protocol YourCellProtocol {
cell(_ cell: CheckoutAddressTableViewCell, didChangeState state: Bool)
}
将委托属性添加到UITableViewCell
子类中,并在状态更改时调用委托
class CheckoutAddressTableViewCell: UITableViewCell {
weak var delegate: YourCellProtocol?
let addressFieldsHeight:CGFloat = 330
var initialized = false;
var sameAsButtonIsChecked:Bool = false {
didSet {
//call the delegate with state change
delegate?.cell(self, didChangeState: sameAsButtonIsChecked)
if sameAsButtonIsChecked {
sameAsCheckboxImageView.image = #imageLiteral(resourceName: "iconCheckboxChecked")
addressFieldsView.isHidden = true
addressFieldsHeightConstraint.constant = 0
}else{
sameAsCheckboxImageView.image = #imageLiteral(resourceName: "iconCheckbox")
addressFieldsView.isHidden = false
addressFieldsHeightConstraint.constant = addressFieldsHeight
}
}
}
}
在您的UIViewController
中,您遵守YourCellProtocol
并实施它
func cell(_ cell: CheckoutAddressTableViewCell, didChangeState state: Bool) {
//state changed for a cell
}
在cellForRowAt:
中,您将UIViewController
设置为代理:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.delegate = self
...
}
或者,当单元格状态随时间变化时,您也可以转到NotificationCenter
发送通知的路线
let notificatioName = Notification.Name("CellStateChanged")
NotificationCenter.default.post(name: notificatioName, object: nil, userInfo: ["state": sameAsButtonIsChecked])
然后在UIViewController
中观察此通知
let notificatioName = Notification.Name("CellStateChanged")
NotificationCenter.default.addObserver(self, selector: #selector(cellDidChangeState(_:)), name: notificatioName, object: nil)
@objc func cellDidChangeState(_ notification: Notification) {
if let userData = notification.userInfo, let state = userData["state"] {
//you have cells state here
}
}
您可以创建一个协议,并将
UIViewController
设置为每个单元格的代理,例如:
@objc protocol YourCellProtocol {
cell(_ cell: CheckoutAddressTableViewCell, didChangeState state: Bool)
}
将委托属性添加到UITableViewCell
子类中,并在状态更改时调用委托
class CheckoutAddressTableViewCell: UITableViewCell {
weak var delegate: YourCellProtocol?
let addressFieldsHeight:CGFloat = 330
var initialized = false;
var sameAsButtonIsChecked:Bool = false {
didSet {
//call the delegate with state change
delegate?.cell(self, didChangeState: sameAsButtonIsChecked)
if sameAsButtonIsChecked {
sameAsCheckboxImageView.image = #imageLiteral(resourceName: "iconCheckboxChecked")
addressFieldsView.isHidden = true
addressFieldsHeightConstraint.constant = 0
}else{
sameAsCheckboxImageView.image = #imageLiteral(resourceName: "iconCheckbox")
addressFieldsView.isHidden = false
addressFieldsHeightConstraint.constant = addressFieldsHeight
}
}
}
}
在您的UIViewController
中,您遵守YourCellProtocol
并实施它
func cell(_ cell: CheckoutAddressTableViewCell, didChangeState state: Bool) {
//state changed for a cell
}
在cellForRowAt:
中,您将UIViewController
设置为代理:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.delegate = self
...
}
或者,当单元格状态随时间变化时,您也可以转到NotificationCenter
发送通知的路线
let notificatioName = Notification.Name("CellStateChanged")
NotificationCenter.default.post(name: notificatioName, object: nil, userInfo: ["state": sameAsButtonIsChecked])
然后在UIViewController
中观察此通知
let notificatioName = Notification.Name("CellStateChanged")
NotificationCenter.default.addObserver(self, selector: #selector(cellDidChangeState(_:)), name: notificatioName, object: nil)
@objc func cellDidChangeState(_ notification: Notification) {
if let userData = notification.userInfo, let state = userData["state"] {
//you have cells state here
}
}
对于您的案例,使用委托是一个不错的解决方案,但我建议在单元格上使用闭包。现在,与单元相关的逻辑位于实际创建单元的同一位置,与委托模式相比,这提供了额外的可见性 可以将以下内容添加到单元格类中
typealias CellAction: () -> Void
var onMyAction: CellAction?
这可以是触发操作的任何函数
func yourFuncThatTriggersTheAction() {
onMyAction?()
}
现在在您的cellForRowAt
cell.onMyAction = {
//do whatever necessary when action is invoked
}
请注意,在cellForRowAt中使用此方法还可以解决获取触发某些操作的单元格的indexPath的问题 对于您的案例,使用委托是一个不错的解决方案,我建议在单元格上使用闭包。现在,与单元相关的逻辑位于实际创建单元的同一位置,与委托模式相比,这提供了额外的可见性 可以将以下内容添加到单元格类中
typealias CellAction: () -> Void
var onMyAction: CellAction?
这可以是触发操作的任何函数
func yourFuncThatTriggersTheAction() {
onMyAction?()
}
现在在您的cellForRowAt
cell.onMyAction = {
//do whatever necessary when action is invoked
}
请注意,在cellForRowAt中使用此方法还可以解决获取触发某些操作的单元格的indexPath的问题 您可以为此使用
通知
,或者使用委派传递tableview的引用。您可以为此使用通知
,或者使用委派传递tableview的引用。