![](/img/trans.png)
[英]How do I set calculations in labels using a delegate method from UITableViewCell?
[英]How to set a UISlider using a delegate method from UITableViewCell
我正在設置MainViewController
和PopUpViewController
。
在MainVC
我有一個滑塊,它代表從0到800厘米的高度。 同樣在這里,我有2個標簽,分別表示以公尺+英寸和米+厘米為單位的厘米的轉換。
在HeightTableViewCell
,我具有所有的插座和滑塊,並且那里有一個與MainVC
通信的MainVC
。
在PopUpViewController
,我有一個保存按鈕和3個UITextFields
(厘米,英尺和英寸)。 當我按下保存按鈕時,我想在MainVC
中將滑塊設置為正確的值,並在標簽中顯示轉換。
我需要使用該委托方法設置UISlider
,因為我無法訪問TableViewCell
的UISlider
嗎?
我已經嘗試過將數據傳遞給代表。 還有其他更好的方法嗎?
這是我的MainVC:
class MainViewController: UIViewController {
var sliderValue: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension MainViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "heightCell", for: indexPath) as! HeightTableViewCell
cell.configVehicleHeightCell(sliderValue)
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.row {
case 0: return 150
default:
return 150
}
}
}
// Receive data from the Cell to MainVC
extension MainViewController: HeightCellDelegate {
func heightSliderValueChanged(_ slider: UISlider, _ feetsLabel: UILabel, _ metersLabel: UILabel) {
let currentValue = Int(slider.value)
let meters = currentValue / 100
let centimeters = currentValue % 100
let inches = currentValue < 3 ? 0 : round(Double(currentValue) / 2.54)
let feet = round(inches / 12)
let inch = round(inches.truncatingRemainder(dividingBy: 12))
feetsLabel.text = "\(feet) ft" + " \(inch)\""
metersLabel.text = "\(meters) m" + " \(centimeters) cm"
}
}
// Receive data (centimeters) from the PopUp to MainVC
extension MainViewController: HeightPopUpDelegate {
func receiveHeightMetric(centimeters: Float?) {
print("\n\nMetric Data received")
print("Centimeters: \(centimeters ?? 0)")
sliderValue = Float(centimeters ?? 0)
tableView.reloadData()
}
func receiveHeightImperial(feet: Int?, inches: Int?) {
print("\n\nImperial Data received")
print("Feet: \(feet ?? 0)")
print("Inches: \(inches ?? 0)")
}
// Receive the data from PopUpViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToHeight" {
let vc: PopUpViewController = segue.destination as! PopUpViewController
vc.delegate = self
}
}
}
這是我的MainVC單元:
protocol HeightCellDelegate {
func heightSliderValueChanged(_ slider: UISlider, _ feetsLabel: UILabel, _ metersLabel: UILabel)
}
class HeightTableViewCell: UITableViewCell {
// Interface Links
@IBOutlet weak var heightLabelTitle: UILabel!
@IBOutlet weak var heightSlider: UISlider!
@IBOutlet weak var heightFeetsLabel: UILabel!
@IBOutlet weak var heightMetersLabel: UILabel!
// Properties
var delegate: HeightCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func configVehicleHeightCell(_ value : Float){
heightSlider.value = value
heightLabelTitle.text = "Height"
let meters = Int((value) / 100)
let centimeters = Int(value.truncatingRemainder(dividingBy: 100))
let inches = Int(value) < 3 ? 0 : round((value) / 2.54)
let feet = Int(round(inches / 12))
let inch = Int(round(inches.truncatingRemainder(dividingBy: 12)))
heightFeetsLabel.text = "\(feet) ft" + " \(inch)\""
heightMetersLabel.text = "\((meters)) m" + " \((centimeters)) cm"
}
@IBAction func heightValueChanged(_ sender: UISlider) {
configVehicleHeightCell(sender.value)
}
}
這是我的PopUpVC代碼:
protocol HeightPopUpDelegate {
func receiveHeightMetric(centimeters: Int?)
func receiveHeightImperial(feet: Int?, inches: Int?)
}
class PopUpViewController: UIViewController {
// Interface Links
@IBOutlet weak var centimetersTextField: UITextField!
@IBOutlet weak var feetTextField: UITextField!
@IBOutlet weak var inchesTextField: UITextField!
@IBOutlet weak var labelForOr: UILabel!
@IBOutlet weak var popUpView: UIView!
@IBOutlet weak var cancelBtnOutlet: UIButton!
@IBOutlet weak var saveBtnOutlet: UIButton!
// Properties
var delegate: HeightPopUpDelegate?
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
// Dismiss the popup when user press the Cancel btn
@IBAction func cancelBtnTapped(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
// Save the data and send it back when user press the Save btn
@IBAction func saveBtnTapped(_ sender: UIButton) {
checkImperialOrMetricTextfields()
dismiss(animated: true, completion: nil)
}
// Check if the textfields contains Metric or Imperial height. If everything is OK then send the data back.
func checkImperialOrMetricTextfields(){
if ((!(centimetersTextField.text?.isEmpty)!) && (!(feetTextField.text?.isEmpty)! || !(inchesTextField.text?.isEmpty)!)) {
showAlertWithTitle(title: "Error", message: "Enter either metric OR imperial height.")
clearTextFields()
}
if ((centimetersTextField.text?.isEmpty)! && (feetTextField.text?.isEmpty)! && (inchesTextField.text?.isEmpty)!) {
showAlertWithTitle(title: "Error", message: "Enter either metric OR imperial height.")
clearTextFields()
}
else{
sendDataBack()
}
}
// Clear textfields
func clearTextFields(){
centimetersTextField.text = ""
feetTextField.text = ""
inchesTextField.text = ""
}
// Function used to send data back from the PopUp to MainVC
func sendDataBack(){
if delegate != nil{
delegate?.receiveHeightMetric(centimeters: Int(centimetersTextField?.text ?? "0"))
delegate?.receiveHeightImperial(feet: Int(feetTextField?.text ?? "0"), inches: Int(inchesTextField?.text ?? "0"))
}
}
// Setup the design for outlets
func setupViews(){
popUpView.layer.cornerRadius = 20
popUpView.layer.masksToBounds = true
cancelBtnOutlet.layer.cornerRadius = 5
cancelBtnOutlet.layer.borderWidth = 0.5
cancelBtnOutlet.layer.borderColor = UIColor.black.cgColor
saveBtnOutlet.layer.cornerRadius = 5
saveBtnOutlet.layer.borderWidth = 0.5
saveBtnOutlet.layer.borderColor = UIColor.black.cgColor
}
// Function to hide the Popup when the user click anywhere on the screen
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if touch?.view == self.view {
dismiss(animated: true, completion: nil)
}
}
// Show an alert view with Title
func showAlertWithTitle(title: String = "", message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
}
當我在PopUp中設置某些內容並單擊“保存”時,我會在控制台中從該文本字段中獲取值:
Metric Data received
Centimeters: 0
Imperial Data received
Feet: 23
Inches: 45
如果正在幫助任何人,這是這個小例子的鏈接: https : //github.com/tygruletz/ImperialAndMetricMeasurement
非常感謝您閱讀本文,希望我提供正確的信息。
我進行了一些更改,以下是cm/m
的工作示例,
在HeightTableViewCell
,在HeightTableViewCell
設置標簽和滑塊。 我將Int設置為Float的地方很少。
func configVehicleHeightCell(_ value : Float){ heightSlider.value = value heightLabelTitle.text = "Height" let meters = Int((value) / 100) let centimeters = Int(value.truncatingRemainder(dividingBy: 100)) let inches = Int(value) < 3 ? 0 : round((value) / 2.54) let feet = Int(round(inches / 12)) let inch = Int(round(inches.truncatingRemainder(dividingBy: 12))) heightFeetsLabel.text = "\\(feet) ft" + " \\(inch)\\"" heightMetersLabel.text = "\\((meters)) m" + " \\((centimeters)) cm" }
在heightValueChanged
,您不再需要委托
@IBAction func heightValueChanged(_ sender: UISlider) { configVehicleHeightCell((sender.value)) }
在MainVC
,創建var sliderValue : Float = 0.0
在cellForRow中, cell.configVehicleHeightCell(sliderValue)
最后,當用戶在警報中輸入數據時(在cm文本字段中有效)
func receiveHeightMetric(centimeters: Float?) { print("\\n\\nMetric Data received") print("Centimeters: \\(centimeters ?? 0)") sliderValue = centimeters ?? 0 mtTableView.reloadData() }
輸出:
編輯
對於feet/inch
,僅在下面做
func receiveHeightImperial(feet: Int?, inches: Int?){
// 1. convert feet, inch into centimeter.
// 2. If either of feet/inch is nil then consider it as zero, for safety
// 3. Now, sliderValue = new_cm_value (value that you calculated from feet/inch)
// 4. Now reloadData().
}
您只有一個單元格,因此您可以:
MainVC
@IBOutlet weak var tableView: UITableView!
func receiveHeightMetric(centimeters: Int?) {
print("\n\nMetric Data received")
print("Centimeters: \(centimeters ?? 0)")
let cell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! HeightTableViewCell
cell.refresh(centimeters: centimeters)
}
func receiveHeightImperial(feet: Int?, inches: Int?) {
print("\n\nImperial Data received")
print("Feet: \(feet ?? 0)")
print("Inches: \(inches ?? 0)")
let cell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! HeightTableViewCell
cell.refresh(feet: feet, inches: inches)
}
HeightTableViewCell
func refresh(centimeters: Int?) {
print("\n\nMetric Data received in cell")
print("Centimeters: \(centimeters ?? 0)")
}
func refresh(feet: Int?, inches: Int?) {
print("\n\nImperial Data received in cell")
print("Feet: \(feet ?? 0)")
print("Inches: \(inches ?? 0)")
}
您可以為UIViewController
創建一個協議,該協議將由UITableViewCell
遵循。
說-
protocol UpdateSlider : class {
func updateSlider(with value : CGFloat)
}
現在您的MainViewController將具有該協議的變量,並且您將通過單元格的引用在cellForRowAt
方法中為該變量分配一個值。
class MainViewController : UIViewController {
weak var delegate : UpdateSlider?
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "heightCell", for: indexPath) as! HeightTableViewCell
cell.configVehicleHeightCell()
cell.delegate = self
self.delegate = cell
return cell
}
每當您想更新滑塊的值時,只需調用MainViewController
的委托方法即可。
self.delegate?.updateSlider(with value : <#CustomValue#>)
PS-您隨時可以在cellForRowAt
設置當前值,並在需要時重新加載單元格。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.