【问题标题】:Retrieve TextField User Entries from SpreadsheetView从 SpreadsheetView 检索 TextField 用户条目
【发布时间】:2025-12-08 11:10:02
【问题描述】:

早安,

我已经设法让我的电子表格视图工作,但没有从电子表格视图中检索用户输入数据的功能,只有一个填充单元格的功能,如下所示。有人可以帮我解决这个问题。电子表格视图中的第一列是使用填充到标签中的数组自动填充的,效果很好。然后第二列由 TextFields 组成,允许用户输入自己的数据,现在我想在按下下一个选项卡时将该数据保存到一个数组中并显示一个图表。我试图填充数组

            func spreadsheetView(_ spreadsheetView: SpreadsheetView, cellForItemAt indexPath: IndexPath) -> Cell? {
        if case (0, 0) = (indexPath.column, indexPath.row) {
            let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: CellInfo.identifier, for: indexPath) as! CellInfo
            cell.label.text = "STATION"
            cell.backgroundColor = .systemGray
            return cell
            
        } else if case (1, 0) = (indexPath.column, indexPath.row) {
            let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: CellInfo.identifier, for: indexPath) as! CellInfo
            cell.Rlabel.text = "MAG READING"
            cell.backgroundColor = .systemGray

        return cell
            
        } else if case (0, 1...(GlobalVariable.sharedInstance.numberOfStations)) = (indexPath.column, indexPath.row) {
            let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: MyLabelCell.identifier, for: indexPath) as! MyLabelCell
            cell.setup(with: GlobalVariable.sharedInstance.arrayProfileStations[indexPath.row-1])
            //print(GlobalVariable.sharedInstance.arrayProfileStations[indexPath.row-1])
            cell.backgroundColor = .systemGray6
            return cell
            
        } else if case (1, 1...(GlobalVariable.sharedInstance.numberOfStations)) = (indexPath.column, indexPath.row) {
            let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: CellInfo.identifier, for: indexPath) as! CellInfo
            var array = [String]()
            cell.TextField.text = "-"
//            if GlobalVariable.sharedInstance.MagDataEntries {
//                cell.TextField.text = GlobalVariable.sharedInstance.MagDataEntries[indexPath.row-1]
//            }else{
                //Populate the array with user data
                
                //
            
                array.append(cell.TextField.text ?? "0")
                //GlobalVariable.sharedInstance.MagDataEntries.append(contentsOf: array)
                //print(indexPath.row-1)
                print(array)
                
          //}
           
            return cell
//        } else if case (1, 1...(GlobalVariable.sharedInstance.numberOfStations)) = (indexPath.column, indexPath.row) {
//
//            let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: MyLabelCell.identifier, for: indexPath) as! MyLabelCell
//            cell.setup(with: GlobalVariable.sharedInstance.arrayProfileStations[indexPath.row-1])
//            spreadsheetView.
//            return cell
    }
        return nil
    }

以下是标签文本字段的创建方式:

     class MyLabelCell:Cell{
    
    static let identifier = "MyLabelCell"
    
    public let label = UILabel()
    public func setup(with text:String){
        label.text = text
        label.textAlignment = .center
        //label.isUserInteractionEnabled = true
        
        contentView.addSubview(label)
        
    }
    
    override func layoutSubviews() {
        
            super.layoutSubviews()
            label.frame = contentView.bounds
        }
    }

     class CellInfo: Cell {
    let label = UILabel()
    let Rlabel = UILabel()
    let TextField = UITextField()
    static let identifier = "CellID"
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        label.frame = bounds
        label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        label.font = UIFont.boldSystemFont(ofSize: 14)
        label.textAlignment = .center
        //label.backgroundColor = .darkGray

        contentView.addSubview(label)
        
        Rlabel.frame = bounds
        Rlabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        Rlabel.font = UIFont.boldSystemFont(ofSize: 14)
        Rlabel.textAlignment = .center
        //Rlabel.backgroundColor = .darkGray

        contentView.addSubview(Rlabel)
        
        TextField.frame = bounds
        TextField.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        TextField.font = UIFont.boldSystemFont(ofSize: 16)
        TextField.textAlignment = .center
        
        contentView.addSubview(TextField)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    首先,注意几点:

    • 开始简单一点。更容易学习基础知识。
    • 对类使用UpperCase,对变量/属性使用lowerCase

    你可以通过使用“回调”闭包来完成你想做的事情。

    将这样的属性添加到您的单元格类中:

    // closure to send data back to controller
    var callback: ((String) -> ())?
    

    在您的控制器类中,当您将单元格出列时,您还设置了它的关闭:

    cell.callback = { [weak self] (fieldText) in
        // handle the text
    }
    

    回到你的单元类,使用UITextFieldDelegate,当文本字段被编辑后,将文本发送回控制器类:

    func textFieldDidEndEditing(_ textField: UITextField) {
        guard let s = textField.text else {
            return
        }
        // send the field's text to the controller
        callback?(s)
    }
    

    这是一个完整的例子。要对其进行测试(并从中学习),请添加一个新的UICollectionViewController 并将其自定义类分配给FieldsCollectionViewController。您不需要配置原型单元格——只需像这样设置集合视图的单元格大小:

    这将为您提供一个“列”单元格,每个单元格都有一个 UITextField。每次文本字段结束编辑(例如点击另一个单元格)时,都会触发回调并更新数据源。

    class CellInfo: UICollectionViewCell, UITextFieldDelegate {
        
        let textField = UITextField()
        static let identifier = "CellInfoID"
    
        // closure to send data back to controller
        var callback: ((String) -> ())?
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        func commonInit() -> Void {
            
            textField.frame = bounds
            textField.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            textField.font = UIFont.boldSystemFont(ofSize: 16)
            textField.textAlignment = .center
            textField.borderStyle = .line
        
            textField.delegate = self
            
            contentView.addSubview(textField)
    
        }
        
        func textFieldDidEndEditing(_ textField: UITextField) {
            guard let s = textField.text else {
                return
            }
            // send the field's text to the controller
            callback?(s)
        }
        
    }
    
    class FieldsCollectionViewController: UICollectionViewController {
        
        var myData: [String] = []
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // just for example,
            //  fill data array with strings from "1" to "20"
            myData = (1...20).map({ String($0) })
            
            collectionView.register(CellInfo.self, forCellWithReuseIdentifier: CellInfo.identifier)
        }
        
        override func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return myData.count
        }
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellInfo.identifier, for: indexPath) as! CellInfo
    
            cell.textField.text = myData[indexPath.item]
    
            cell.callback = { [weak self] (fieldText) in
                print("editing ended for cell: \(indexPath) with text: \(fieldText)")
                // update data source with text from edited field
                self?.myData[indexPath.item] = fieldText
            }
    
            return cell
        }
    }
    

    【讨论】:

    • 非常感谢我今天学到了很多,您对示例的解释再次感谢。我犯的唯一错误是忘记实现 textField Delegate,这让我有点摸不着头脑。 :)