Escaping closure captures mutating 'self' parameter Error

Creating a simple card game (Set) and I have a function in the model that deals X cards onto the deck. Currently, when I click the deal card button they all show up at once so I added the timer so that they would appear one after another. This gives the error "Escaping closure captures mutating 'self' parameter" Any ideas on what I can fix?

Code Block
mutating func deal(_ numberOfCards: Int) {
for i in 0..<numberOfCards {
Timer.scheduledTimer(withTimeInterval: 0.3 * Double(i), repeats: false) { _ in
if deck.count > 0 {
dealtCards.append(deck.removeFirst())
}
}
}
}

Replies

Any ideas on what I can fix?

Please show more context, whole code of the type including the method, and how it is used in your app.
Simplified, but enough to reproduce the same issue, would be welcome.
Is deck a property of self? If so, you need to be explicit that the closure is capturing a reference to self because of the potential for creating a circular reference. That is, if the object keeps a reference to this closure, and this closure keeps a reference to the object, neither one of them can ever be deallocated.

Code Block
if self.deck.count > 0 {
self.dealtCards.append(self.deck.removeFirst())
}


The better question to ask is why you need an escaping closure in the first place. It doesn't look like you're trying to put work on a background queue somewhere to do later; your code looks like it just wants to wait a moment in between dealing cards. I'm not very familiar with UI frameworks, but maybe the framework you're using has APIs for this kind of animation? Those would probably work better.

For a more detailed discussion of self and closures, take a look at Escaping Closures in "The Swift Programming Language".
The immediate answer to your question is that you should add self. before each reference to a property of self.

But there’s a bigger question I need to ask: Where is this code, and how is the result displayed? Are you using UIKit/AppKit or SwiftUI? Since the method is mutating, it seems to be in a struct—is this struct a SwiftUI view, or is it a part of the model (hopefully managed by an ObservableObject-conforming class)?

Because if you’re doing this in a SwiftUI view, I’m concerned that there may be deep architectural issues with the way you’re implementing this. Mutating a SwiftUI view tends to not really work very well. It’d be better to keep your mutable state in an object outside of your views and let SwiftUI reflect the changing state of that model.
The code is within a model that is managed by a viewModel ObservableObject class that communicates with the View Struct.

My issue was that if I have the View handle the number of cards dealt I am able to use the timer to delay the cards so it happens one-by-one. However, I wanted to make it so that it is done in the model instead as this makes more sense for the gameplay as a whole.

@Developer Tools Engineer.

I have the same problem and don't understand all hints on the net...

My code is:

`@Observable struct LADVAthletes {
    var queryName : String = ""
    var athletesList : [Athlete] = [Athlete]()
    
    var subscription : AnyCancellable? = nil

    mutating func searchInLADVAthlets() {
        print("Search in LADV for \(queryName)")
        
        let url = URL(string: "https://ladv.de/api/rriekert/athletQuery?query=\(queryName)*&limit=100")

        subscription = URLSession.shared
            .dataTaskPublisher(for: url!)
            .map(\.data)
            .decode(type: [Athlete].self, decoder: JSONDecoder())
            .sink(receiveCompletion: { completion in
                if case .failure(let err) = completion {
                    print("Retrieving data failed with error \(err)")
                }
            }, receiveValue: { object in
                self.athletesList = object
                print("Retrieved object \(object)")
            })
    }
}`

I get the Escaping closure captures mutating 'self' parameter on the receiveValue-phrase....

Any hints?