admin管理员组

文章数量:1316561

I want to show progress in collection view cell text label. I use this code to do it. Code from observer works and I see print progress in debug but I can't see this in cell. Why?

KVO variant (not working)

I get progress inside the observer, but the cell text is not updated. Why?

var nameObservation: NSKeyValueObservation?
@objc dynamic var progress = 0.0


func createDataSource() {
    dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
        switch self.sections[indexPath.section].identifier {
        case "carouselCell":
            let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
                self.nameObservation = self.observe(\.progress, options: .new) { vc, change in
                    cell.title.text = "\(self.progress)"
                }
            return cell
        default: return self.configure(CarouselCell.self, with: item, for: indexPath)
        }
    }
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    _ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
        guard self.progress <= 1.0 else {
            timer.invalidate()
            self.progress = 0.0
            return
        }
    }
}

Notification variant (not working).

I'm also trying to solve this problem using notifications. And my collection disappears after clicking

var nameObservation: NSKeyValueObservation?
        
    @objc func createDataSource() {
        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
            switch self.sections[indexPath.section].identifier {
            case "carouselCell":
                let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
                        cell.title.text = "\(self.progressA)"
                        print(self.progressA)
                return cell
            default: return self.configure(CarouselCell.self, with: item, for: indexPath)
            }
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        NotificationCenter.default.addObserver(
            self, selector: #selector(self.createDataSource),
            name: Notification.Name(rawValue: "sound-CarouselController"), object: nil)
                
        _ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
            guard self.progressA <= 1.0 else {
                timer.invalidate()
                self.progressA = 0.0
                return
            }
            self.progressA += 0.01
            NotificationCenter.default.post(name: Notification.Name(rawValue: "sound-CarouselController"), object: nil)

        }
                
    }

I want to show progress in collection view cell text label. I use this code to do it. Code from observer works and I see print progress in debug but I can't see this in cell. Why?

KVO variant (not working)

I get progress inside the observer, but the cell text is not updated. Why?

var nameObservation: NSKeyValueObservation?
@objc dynamic var progress = 0.0


func createDataSource() {
    dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
        switch self.sections[indexPath.section].identifier {
        case "carouselCell":
            let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
                self.nameObservation = self.observe(\.progress, options: .new) { vc, change in
                    cell.title.text = "\(self.progress)"
                }
            return cell
        default: return self.configure(CarouselCell.self, with: item, for: indexPath)
        }
    }
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    _ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
        guard self.progress <= 1.0 else {
            timer.invalidate()
            self.progress = 0.0
            return
        }
    }
}

Notification variant (not working).

I'm also trying to solve this problem using notifications. And my collection disappears after clicking

var nameObservation: NSKeyValueObservation?
        
    @objc func createDataSource() {
        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
            switch self.sections[indexPath.section].identifier {
            case "carouselCell":
                let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
                        cell.title.text = "\(self.progressA)"
                        print(self.progressA)
                return cell
            default: return self.configure(CarouselCell.self, with: item, for: indexPath)
            }
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        NotificationCenter.default.addObserver(
            self, selector: #selector(self.createDataSource),
            name: Notification.Name(rawValue: "sound-CarouselController"), object: nil)
                
        _ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
            guard self.progressA <= 1.0 else {
                timer.invalidate()
                self.progressA = 0.0
                return
            }
            self.progressA += 0.01
            NotificationCenter.default.post(name: Notification.Name(rawValue: "sound-CarouselController"), object: nil)

        }
                
    }
Share Improve this question edited Jan 30 at 15:54 User asked Jan 30 at 12:01 UserUser 1951 gold badge1 silver badge11 bronze badges 3
  • You have to update the DATA SOURCE, not the cell itself. its very hard to do! – Fattie Commented Jan 30 at 12:37
  • @Fattie Please check this answer stackoverflow/a/79398905/6818660 on my previous question. I tried updating the DATA SOURCE in the previous question, but it caused problems. And @Rob recommended that I do what I am trying to do in the current question. Also the current question is not a duplicate of the previous one – User Commented Jan 30 at 12:50
  • 1 PS I did not mark your question as a dupe, and I upvoted it! TBH I am not able to look through all the code. I fear that you have some basic problems in the nature of the cells / data source. Updating cells with live animation is really tricky! – Fattie Commented Jan 30 at 15:32
Add a comment  | 

1 Answer 1

Reset to default 1

I find it extremely challenging to animate things in cells, syncing them and so on.

You can see some old QA about it. https://stackoverflow/a/58239612/294884 Synchronise all animations on collection-view cells etc - no idea what's going on in those.

the only honest-to-God solution we have ever found

  1. Make a singleton that entirely handles all your timer(s), progress etc.

  2. So for example there might be some "progress", lets say it is "progress of download 7B" ...

  3. During any frame, anyone at all who wants to, can, get that current value, from the singleton

  4. And that's it. In your cells (or anywhere whatsoever) just draw the value in question (whether a bar or whatever it is) each frame to the value you read from the singleton

So you just completely fet about the madness of UIKit's various animation paradigms.

Just use CADisplayLink and draw everything as you wish - based only on the values in one central singleton.

Don't fet that (of course) cells are constantly changing as you scroll. ie the cell that the user thinks of as "cell 91" is of course displayed by DIFFERENT changing cells as you scroll up and down, hopefully you completely understand this basic paradigm of how recycler views work.

Note that you don't have to bother with the insanity of notifications, subscriptions etc.

It's one of those things that is much, much easier once you make the jump to using normal frame based drawing (CADisplayLink).

When you're testing this you can put the animation anywhere at all, on a normal view, in a popup, in an alert, in cells, in tab bars, whatever. The "cell problems" become nonexistent.

本文标签: iosHow to update collection view with KVOStack Overflow