简体   繁体   中英

Notification is not working for UISegmentController

I have a tableView. I register the Cell as follow:

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

Inside TVCellElementProperties , I created manually a segment controller as follow:

    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()

inside the tableView, I inserted this line into the 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. 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:

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. 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.

I tried to call the function from the Cell inside CellForRow, but same as above. the function ** handleUnitChange** is not called overtime I clicked inside the Segment Controller.

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

We first work on 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. Set a selector target (b) through awakFromNib. In order to receive user's action through UITableView , you must send a signal with the closure (c). Finally, add a target receiver (c).

Step 2

We now work with 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. In order to see which segmentControl the user has selected, you set a tag (e). The closure (f) is set before returning the 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).

Warning

If you take a good look at line (e), indexPath.row is used as a tag. 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 . The result is 2 and 1, 2 as in the row, 1 as in the selectedSegmentIndex value. The user doesn't have to select any of the table rows.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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