Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Instance method 'onReceive(_:perform:)' requires that 'CountdownTimer' conform to 'Publisher'

I’m currently building out a project where a user could create multiple timers however I’m running into the following error. "Instance method ‘onReceive(_:perform:)’ requires that ‘CountdownTimer’ conform to ‘Publisher’". I just can’t figure out how to get Countdown Timer to conform to Publisher.

Here is the code for my timer object:

struct CountdownTimer: Identifiable {
  let id = UUID()
  let name: String
  var minutes: Int
  var seconds: Int

  var countdown: Int  {
    let totalTime = seconds + (minutes * 60)
        return totalTime
  }
} 

func timeString(time: Int) -> String {
    return String(format: "%01i:%02i", minutes, seconds)

}
  

class CountdownTimers: ObservableObject {
  @Published var timers = [CountdownTimer]()
}

My Content View:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct ContentView: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var countdownTimers = CountdownTimers()

@State private var showingAddSheet = false


let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

var body: some View {
    NavigationView {
        GeometryReader { geometry in
            ZStack {
                Color.pastelGreen
                    .edgesIgnoringSafeArea(.all)
                VStack {
                    ScrollView {
                        ForEach(countdownTimers.timers) { timer in
                            ZStack {
                                CardView()
                                    .overlay(
                                        HStack {
                                            VStack(alignment: .leading) {
                                                Text("\(timer.countdown)")
                                                    .font(.custom("Quicksand-Bold", size: 30))
                                                Text(" \(timer.timeString(time: timer.countdown))")
                                                    .font(.custom("Quicksand-Bold", size: 40))
                                                    .onReceive(timer){ _ in
                                                        if timers.countdown > 0 {
                                                            timers.countdown -= 1
                                                        }
                                                    }

The error is happening on the .OnReceive(timer) line. the minutes and seconds are created on a different "AddView" but I don’t believe that the issue is related to that section.

Any help would be greatly appreciated.

>Solution :

You’re shadowing the name timer. It appears first here:

let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

Then, later, you use it again here:

ForEach(countdownTimers.timers) { timer in

Swift is going to assume you always mean the timer in the most-recently-defined scope, so when you use .onReceive, it assumes you mean timer from the ForEach (which is of type CountdownTimer) and not the Timer defined earlier.

To fix this, use a different name in your ForEach and adjust your code (such as the Text elements) to use the new name.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading