如何将步进值传递给 ViewController?

Posted

技术标签:

【中文标题】如何将步进值传递给 ViewController?【英文标题】:How to pass stepper value to ViewController? 【发布时间】:2020-09-09 17:18:32 【问题描述】:

我有一个自定义单元格,它有 2 个标签,myLabel 和 numLabel,以及一个步进器。我在 Swift 文件和 XIB 文件中有我的自定义单元格。我希望当我单击步进器上的 + 或 - 按钮时,我的 numLabel 会随着步进器的值而变化。我不知道如何将步进值传递给我有 tableView 的 viewController。后来想将步进值保存到 CoreDate 我该怎么做?我只是一个初学者。感谢您的帮助。

MyCell.swift

import UIKit

class MyCell: UITableViewCell 
    
    static let identifier = "MyCell"
    
    static func nib() -> UINib 
        return UINib(nibName: "MyCell", bundle: nil)
    
    
    public func configure(with name: String, number: String) 
        myLabel.text = name
        numLabel.text = number
    
    
    @IBOutlet var myLabel: UILabel!
    @IBOutlet var numLabel: UILabel!
        
    

    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
    
    

ViewController.swift

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 
    
    @IBOutlet var table: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()
        table.register(MyCell.nib(), forCellReuseIdentifier: MyCell.identifier)
        table.delegate = self
        table.dataSource = self
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 10
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.identifier, for: indexPath) as! MyCell
        cell.configure(with: "Item 1", number: "1")
        return cell
    



My Screen Shot

【问题讨论】:

【参考方案1】:

您可以使用“回调”闭包轻松做到这一点:

class MyCell: UITableViewCell 
    static let identifier: String = "MyCell"
    
    @IBOutlet var myStepper: UIStepper!
    @IBOutlet var numLabel: UILabel!
    @IBOutlet var myLabel: UILabel!

    // "callback" closure - set my controller in cellForRowAt
    var callback: ((Int) -> ())?
    
    public func configure(with name: String, number: String) 
        myLabel.text = name
        numLabel.text = number
    

    @IBAction func stepperChanged(_ sender: UIStepper) 
        let val = Int(sender.value)
        numLabel.text = "\(val)"
        // send value back to controller via closure
        callback?(val)
    

    static func nib() -> UINib 
        return UINib(nibName: "MyCell", bundle: nil)
    


然后,在cellForRowAt

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.identifier, for: indexPath) as! MyCell
    cell.configure(with: "Item 1", number: "1")
    
    // set the "callback' closure
    cell.callback =  (val) in
        print("Stepper in cell at \(indexPath) changed to: \(val)")
        // do what you want when the stepper value was changed
        //  such as updating your data array
    

    return cell

【讨论】:

【参考方案2】:

对通用方法使用委托。这允许您的单元格与 tableview 交互的灵活性,并启用您对 Swift 所期望的类型检查。

通常,对于 UITableView,您将拥有一个驱动单元格内容的数据数组。在您的情况下,假设它是 MyStruct (在您的视图控制器内):

struct MyStruct 
    let name: String
    var value: Int

var myStructs: [ MyStruct ] = [
    MyStruct( name: "Name 1", value: 1 ),
    MyStruct( name: "Name 2", value: 2 ),
    MyStruct( name: "Name 3", value: 3 ) ]

创建MyCellDelegate,并在其中放置您需要的任何方法,以便将更改从单元格传递到视图控制器。例如:

protocol MyCellDelegate: class 
    func didSet( value: Int, for myStructIndex: Int )


class MyCell: UITableViewCell 
    weak var delegate: MyCellDelegate!
    var myStructIndex: Int!
    ...

对于您的表格视图,在出列单元格时分配委托,并实现协议。

class ViewController: MyCellDelegate, UITableViewDelegate, UITableViewDataSource 
    func tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.identifier, for: indexPath) as! MyCell
        let myStruct = myStructs[indexPath.row]  // You may want to ensure that you are in bounds
        cell.delegate = self
        cell.myStructIndex = indexPath.row
        cell.configure( with: myStruct.name, number: myStruct.value )
        return cell
    

    func didSet( value: Int, for myStructIndex: Int ) 
        //  Now MyViewController sees the change.
        myStructs[myStructIndex].value = value
    

最后,在您的 MyCell 中,每当值发生变化时,例如在您的步进器中,调用:

@IBAction func stepperChanged( _ sender: UIStepper ) 
    let integerValue = Int( sender.value.round() )
    numLabel.text = "\(integerValue)"

    //  Tell the view controller about the change: what happened, and to what cell.
    self.delegate.didSet( value: integerValue, for: self.myStructIndex )

【讨论】:

以上是关于如何将步进值传递给 ViewController?的主要内容,如果未能解决你的问题,请参考以下文章

如何将嵌入式collectionView中选定单元格的值传递给另一个viewController?

将数组从 ViewController 传递给 AppDelegate

从按钮将值传递给视图控制器字典

不能将值传递给另一个 viewController?

禁用UIStepper的一半

如何将 CoreLocation 值从一个 VIewController 传递到 iOS 中的 AppDelegate?