【问题标题】:Populating fields in a custom tableView cell from data defined in a popover/popup从弹出框/弹出框中定义的数据填充自定义 tableView 单元格中的字段
【发布时间】:2021-08-23 00:08:33
【问题描述】:

在我的应用程序的设置 VC 中,我有一个带有 5 个不同自定义单元格的表格视图。我需要一些帮助的单元格设置了默认的开始和结束时间。这是使用带有日期/时间控件的弹出框/弹出窗口来完成的,该控件使用 segue 打开。此单元格包含 2 个按钮(开始和结束)和 2 个字段(开始和结束)。当点击其中一个按钮时,会显示相应的弹出框/弹出框。然后用户定义所需时间并点击完成按钮。我正在使用协议/委托方法从弹出框/弹出框传递时间字符串。这目前有效,但有一个例外。我希望新定义的时间填充单元格中相应的开始或结束字段。我的想法是将所有这些代码移动到自定义 tableViewCell 中,在那里我可以完全访问这些字段,但我似乎无法做到这一点。无法识别将 prepare(for segue: 移动到单元格文件。有没有办法从自定义单元格执行此 segue?或者有人对使用我当前的设置填充字段有想法吗?提前感谢您的帮助。

// All of this code is in the tableView controller except the last part where noted

    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
        if segue.identifier == "quote_Presets_StartTime" // # 2
        {
            let storyboard : UIStoryboard = UIStoryboard(name: K.StoryboardID.date_Picker_SB, bundle: nil)
            var popupVC : Date_Popup_VC = storyboard.instantiateViewController(withIdentifier: K.StoryboardID.date_Popup_VC) as! Date_Popup_VC
            let navigationController = UINavigationController(rootViewController: popupVC)
            
            let deviceName = UIDevice().type
            let deviceString: String = ("\(deviceName)")
            
            if deviceString.contains(K.theDevice.iPad)
            {
                popupVC = segue.destination as! Date_Popup_VC
                
                if ModelData.isInline() // Wheel
                {
                    popupVC.preferredContentSize = CGSize(width: 320, height: 300)
                    
                } else { // Inline
                    
                    popupVC.preferredContentSize = CGSize(width: 350, height: 150)
                }
                
                navigationController.isNavigationBarHidden = true
                
            } else if deviceString.contains(K.theDevice.iPhone) {
                
                present(navigationController, animated: true, completion: nil)
                navigationController.isNavigationBarHidden = false
            }
            
            popupVC.theBtn = 2
            
            let formattedTime = ModelData.formattedTime_Read(time_Db: new_Start_Time)
            popupVC.theDate = formattedTime
            
            popupVC.timeStart_Delegate = self
            
        } else if segue.identifier == "quote_Presets_EndTime" { // # 3
            let storyboard : UIStoryboard = UIStoryboard(name: K.StoryboardID.date_Picker_SB, bundle: nil)
            var popupVC : Date_Popup_VC = storyboard.instantiateViewController(withIdentifier: K.StoryboardID.date_Popup_VC) as! Date_Popup_VC
            let navigationController = UINavigationController(rootViewController: popupVC)
            
            let deviceName = UIDevice().type
            let deviceString: String = ("\(deviceName)")
            
            if deviceString.contains(K.theDevice.iPad)
            {
                popupVC = segue.destination as! Date_Popup_VC
                
                if ModelData.isInline() // Wheel
                {
                    popupVC.preferredContentSize = CGSize(width: 320, height: 300)
                    
                } else { // Inline
                    
                    popupVC.preferredContentSize = CGSize(width: 350, height: 150)
                }
                
                navigationController.isNavigationBarHidden = true
                
            } else if deviceString.contains(K.theDevice.iPhone) {
                
                present(navigationController, animated: true, completion: nil)
                navigationController.isNavigationBarHidden = false
            }
            
            popupVC.theBtn = 3
            
            let formattedTime = ModelData.formattedTime_Read(time_Db: new_End_Time)
            popupVC.theDate = formattedTime
            
            popupVC.timeEnd_Delegate = self
        }
    }

// Executed from the cellForRowAt code
    @objc
    func setTheTimes(sender: UIButton)
    {
        switch sender.tag
        {
        case 0:
            performSegue(withIdentifier: "quote_Presets_StartTime", sender: Any?.self)
            
        case 1:
            performSegue(withIdentifier: "quote_Presets_EndTime", sender: Any?.self)
            
        default: break
        }
    }

extension Quote_Presets_VC: UITableViewDelegate, UITableViewDataSource
{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        // cell_05 Time
        let cell_05 = tableView.dequeueReusableCell(withIdentifier: K.ReuseIdentifier.defaultTime_Cell, for: indexPath) as! DefaultTime_Cell
        cell_05.backgroundColor = Theme.current.darkAccentColor
        cell_05.selectionStyle = .none
        
        cell_05.delegate = self as SaveData_Time
        
        cell_05.label_Outlet.labelTextColorOnly_Attributes(txt: K.Titles.defaultStartEnd, txtWgt: .regular)
        cell_05.labelStart_Outlet.labelTextColorOnly_Attributes(txt: K.Titles.start, txtWgt: .regular)
        cell_05.labelEnd_Outlet.labelTextColorOnly_Attributes(txt: K.Titles.end, txtWgt: .regular)
        
        cell_05.startBtn_Outlet.addTarget(self, action: #selector(setTheTimes), for: .touchUpInside)
        cell_05.endButton_Outlet.addTarget(self, action: #selector(setTheTimes), for: .touchUpInside)
        
        cell_05.fldStart_Outlet.textField_Simple(text: ModelData.timeConversionTo_12(time24: new_Start_Time))
        cell_05.fldEnd_Outlet.textField_Simple(text: ModelData.timeConversionTo_12(time24: new_End_Time))
        
        switch indexPath.row
        {
        case 9: // Time
            cell_05.fldStart_Outlet.tag = 0
            cell_05.fldEnd_Outlet.tag = 1
            
            cell_05.startBtn_Outlet.tag = 0
            cell_05.endButton_Outlet.tag = 1
            
            return cell_05
            
        default: break
        }
        
        return UITableViewCell()
    }
}

// These are the delegates for the protocol to pass the time string
extension Quote_Presets_VC: TimeStart_DatePopupDelegate, TimeEnd_DatePopupDelegate
{
    func saveTimeStart(value: String)
    {
        var originalValue: String = ""
        for theValue in presetsArray
        {
            originalValue = theValue.start_Time
        }

        let formattedValue = ModelData.timeConversionTo_24(time12: value)

        if formattedValue != originalValue
        {
            new_Start_Time = value
            save_Array_Quote[6] = K.AppFacing_Titles.true_

        } else {

            save_Array_Quote[6] = K.AppFacing_Titles.false_
        }

        setSaveBtn_QuotePresets()
    }

    func clearTimeStart(value: String)
    {
        // startFld_Outlet.text = value
    }

    func saveTimeEnd(value: String)
    {
        var originalValue: String = ""
        for theValue in presetsArray
        {
            originalValue = theValue.end_Time
        }

        let formattedValue = ModelData.timeConversionTo_24(time12: value)

        if formattedValue != originalValue
        {
            new_End_Time = value
            save_Array_Quote[7] = K.AppFacing_Titles.true_

        } else {

            save_Array_Quote[7] = K.AppFacing_Titles.false_
        }

        setSaveBtn_QuotePresets()
    }

    func clearTimeEnd(value: String)
    {
        // endFld_Outlet.text = value
    }
}

// The code below is the current tableview cell code
protocol SaveData_Time: AnyObject
{
    func setSaveBtn_QuotePresets()
}

class DefaultTime_Cell: UITableViewCell
{
    @IBOutlet weak var label_Outlet: UILabel!
    @IBOutlet weak var labelStart_Outlet: UILabel!
    @IBOutlet weak var fldStart_Outlet: UITextField!
    @IBOutlet weak var fldEnd_Outlet: UITextField!
    @IBOutlet weak var labelEnd_Outlet: UILabel!
    @IBOutlet weak var startFldHgt_Constraint: NSLayoutConstraint!
    @IBOutlet weak var startBtn_Outlet: UIButton!
    @IBOutlet weak var endButton_Outlet: UIButton!
    
    weak var delegate: SaveData_Time?
    
    override func awakeFromNib()
    {
        super.awakeFromNib()
        
    }
    
    override func setSelected(_ selected: Bool, animated: Bool)
    {
        super.setSelected(selected, animated: animated)
        
    }
    
    @IBAction func startBtn_Tapped(_ sender: UIButton)
    {
        // This throws an error that cannot find performSegue in scope
        //performSegue(withIdentifier: "quote_Presets_StartTime", sender: Any?.self)
    }
    
    @IBAction func endBtn_Tapped(_ sender: UIButton)
    {
        // This throws an error that cannot find performSegue in scope
        //performSegue(withIdentifier: "quote_Presets_EndTime", sender: Any?.self)
    }
}

【问题讨论】:

    标签: ios swift xcode tableview uistoryboardsegue


    【解决方案1】:

    首先,在需要之前不要将日期转换为字符串。改为传递 Date 值。

    而且,要回答有关将更多逻辑移入单元格的问题,请不要这样做。保持你的观点简单。

    我只需在 DateCell 中添加两个闭包,以指示是否点击了按钮:

    class DateCell: UITableViewCell {
        @IBOutlet weak var startDateButton: UIButton!
        @IBOutlet weak var endDateButton: UIButton!
    
        var didTapStart: () -> Void = {}
        var didTapEnd: () -> Void = {}
    
        @IBAction func didSelectStart(_ sender: UIButton) {
            didTapStart()
        }
    
        @IBAction func didSelectEnd(_ sender: UIButton) {
            didTapEnd()
        }
    }
    

    在您的日期编辑器中,您可以使用委托或闭包来指示日期已更改。我将在这里使用闭包:

    class DateEditor: UIViewController {
    
        var dateDidChange: (Date) -> Void = { _ in }
    
        // ...
    }
    

    我不是 segues 的粉丝,但如果你真的想使用一个,那么创建两个 segues,一个用于编辑开始日期,一个用于编辑结束日期:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let cell = sender as? UITableViewCell,
            let row = tableView.indexPath(for: cell)?.row,
            let vc = segue.destination as? DateEditor else { return }
    
        if segue.identifier == "editStartDate" {
            vc.date = dates[row].start
        } else {
            vc.date = dates[row].end
        }
    
        vc.dateDidChange = { [weak self] date in
            if segue.identifier == "editStartDate" {
                self?.dates[row].start = date
            } else {
                self?.dates[row].end = date
            }
            self?.tableView.reloadRows(at: [IndexPath(row: row, section: 0)], with: .fade)
        }
    }
    

    只要点击其中一个按钮,就触发 segue:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DateCell", for: indexPath) as! DateCell
    
        cell.startDateButton.setTitle(
            DateFormatter.awesome.string(from: self.dates[indexPath.row].start),
            for: .normal
        )
        cell.endDateButton.setTitle(
            DateFormatter.awesome.string(from: self.dates[indexPath.row].end),
            for: .normal
        )
    
        cell.didTapStart = { [weak self] in
            self?.performSegue(withIdentifier: "editStartDate", sender: cell)
        }
    
        cell.didTapEnd = { [weak self] in
            self?.performSegue(withIdentifier: "editEndDate", sender: cell)
        }
        return cell
    }
    

    这是我用来格式化日期的:

    extension DateFormatter {
        static let awesome: DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateStyle = .short
            formatter.timeStyle = .medium
            return formatter
    
        }()
    }
    

    【讨论】:

    • 感谢@Rob 非常彻底的回答。非常感激。我需要一点时间来消化这些信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多