简体   繁体   English

通知不适用于UISegmentController

[英]Notification is not working for UISegmentController

I have a tableView. 我有一个tableView。 I register the Cell as follow: 我将单元格注册如下:

tableView.register(TVCellElementProperties.self, forCellReuseIdentifier: cellId1)

Inside TVCellElementProperties , I created manually a segment controller as follow: TVCellElementProperties内部,我手动创建了一个分段控制器,如下所示:

    let unitTypeSegmentedControl: UISegmentedControl = {
    let types = ["Blue", "White"]
    let sc = UISegmentedControl(items: types)
    sc.selectedSegmentIndex = 0
    sc.translatesAutoresizingMaskIntoConstraints = false
    sc.tintColor = UIColor.darkBlue
    sc.addTarget(self, action: #selector(handleUnitChange), for: .valueChanged)

    return sc
}()

@objc func handleUnitChange() {
    NotificationCenter.default.post(name: .unitPicked, object: self)
}

So, I think when I change the value inside the SegmentController, it should redirect me to the function handleUnitChange() 因此,我认为当我更改SegmentController中的值时,它应该将我重定向到功能handleUnitChange()

inside the tableView, I inserted this line into the ViewDidLoad: 在tableView内部,我将以下行插入到ViewDidLoad中:

NotificationCenter.default.addObserver(self, selector: #selector(unitPicked), name: .unitPicked, object: nil)

When I run the application, the function ** handleUnitChange** inside tableviewCell is not called. 当我运行应用程序时,未调用tableviewCell内部的** handleUnitChange **函数。 What I did wrong? 我做错了什么? how do I know what I clicked ? 我怎么知道我点击了什么?

EDIT: I am calling a setupView Function which responsible for insert the Segment Controller inside the Cell from init inside the UITableViewCell as follow: 编辑:我正在调用setupView函数,该函数负责从UITableViewCell内的init插入Cell内的细分控制器,如下所示:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.setupViews()
    print("test init")
}

So, when i run it, setupView is called just once, thus ** handleUnitChange** is called too just once. 因此,当我运行它时,setupView仅被调用一次,因此** handleUnitChange **也仅被调用一次。 I mean to say, when the application is up and running, and when I click on the segment controller inside TableView, the function handleUnitChange is not called anymore. 我的意思是说,当应用程序启动并运行时,以及当我单击TableView内的段控制器时,不再调用function handleUnitChange

I tried to call the function from the Cell inside CellForRow, but same as above. 我试图从CellForRow内部的Cell调用函数,但与上面相同。 the function ** handleUnitChange** is not called overtime I clicked inside the Segment Controller. 我在细分控制器中单击的函数** handleUnitChange **不被称为超时。

if let cell = tableView.dequeueReusableCell(withIdentifier: cellId1, for: indexPath) as? TVCellElementProperties {

    //cell.backgroundColor = UIColor.rgb(red: 12, green: 122, blue: 12)
    //cell.contentView.isUserInteractionEnabled = false
    cell.setupViews()
    //print("\(cell.handleUnitChange(sender: u))")
    cell.handleUnitChange(sender: cell.unitTypeSegmentedControl)
    return cell
}

Step 1 第1步

We first work on UITableViewCell . 我们首先研究UITableViewCell

class ProfileTableViewCell: UITableViewCell {
    // MARK: - IBOutlet
    @IBOutlet var firstLabel: UILabel!
    @IBOutlet var lastLabel: UILabel!
    @IBOutlet var ageLabel: UILabel!
    @IBOutlet var pictureImageView: UIImageView!
    @IBOutlet weak var segmentControl: UISegmentedControl! // (a)

    // MARK: - awakeFromNib
    override func awakeFromNib() {
        super.awakeFromNib()
        firstLabel.backgroundColor = UIColor.clear
        lastLabel.backgroundColor = UIColor.clear
        ageLabel.backgroundColor = UIColor.clear
        segmentControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) // (b)
    }

    var onSegmentChanged: ((Int, Int) -> Void)? // (c)

    // (d)
    @objc func valueChanged(sender: UISegmentedControl) {
        onSegmentChanged!(sender.tag, sender.selectedSegmentIndex)
    }
}

First, add an IBOutlet connection (a) through Interface Builder. 首先,通过Interface Builder添加IBOutlet连接(a)。 Set a selector target (b) through awakFromNib. 通过awakFromNib设置选择器目标(b)。 In order to receive user's action through UITableView , you must send a signal with the closure (c). 为了通过UITableView接收用户的操作,必须发送带有闭包(c)的信号。 Finally, add a target receiver (c). 最后,添加目标接收器(c)。

Step 2 第2步

We now work with UIViewController . 现在,我们使用UIViewController

class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard let people = fetchedResultsController.fetchedObjects else { return 0 }
        return people.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ProfileTableViewCell
        let person = fetchedResultsController.object(at: indexPath)
        cell.segmentControl.tag = indexPath.row // (e)
        // action //
        (f)
        cell.onSegmentChanged = { tag, selectedSegment in
            // (g) self.segmentTapped(tag: tag, index: selectedSegment)
            // print(tag, selectedSegment)
        }
        return cell
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            // fetching data //
            let person = fetchedResultsController.object(at: indexPath)

            // deleting data //
            person.managedObjectContext?.delete(person)

            // saving the change //
            let context = persistentContainer.viewContext
            do {
                try context.save()
                print("saved...")
            } catch {
                print("failed saving")
            }
        }
    }

    (h)
    func segmentTapped(tag: Int, index: Int) {
        print(tag, index)
    }
}

When you send user's action through UITableViewCell , you must receive it through UIViewController with UITableView 's cellForRowAt delegate method. 当您通过UITableViewCell发送用户的操作时,必须通过具有UITableViewcellForRowAt委托方法的UIViewController接收它。 In order to see which segmentControl the user has selected, you set a tag (e). 为了查看用户选择了哪个segmentControl,可以设置标签(e)。 The closure (f) is set before returning the cell . 闭包(f)在返回cell之前设置。 You can print the result inside the closure. 您可以在闭包内部打印结果。 If you want to take the result out of the delegate method, see (g) and (h). 如果要从委托方法中取出结果,请参见(g)和(h)。

Warning 警告

If you take a good look at line (e), indexPath.row is used as a tag. 如果您仔细看一下第(e)行, indexPath.row将用作标记。 This approach works only if you know that none of the table rows is removed. 仅当您知道没有删除任何表行时,此方法才有效。 Otherwise, your table data must have a dictionary value that gives each row a unique number. 否则,您的表数据必须具有一个字典值,该值必须为每行赋予唯一的编号。

Test 测试

See how it works. 看看它怎么运作。 When the user uses the segment control on the second row, you will receive a call through cellForRowAt . 当用户在第二行上使用细分控件时,您将通过cellForRowAt收到呼叫。 The result is 2 and 1, 2 as in the row, 1 as in the selectedSegmentIndex value. 结果是2和1,行中为2, selectedSegmentIndex值中为1。 The user doesn't have to select any of the table rows. 用户不必选择任何表行。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM