# ⛔️ escaping closure captures mutating 'self' parameter

👉  StackOverflow：[What's 'Escaping closure captures mutating 'self' parameter' and how to fix it](https://stackoverflow.com/questions/58327013/swift-5-whats-escaping-closure-captures-mutating-self-parameter-and-how-t)

{% tabs %}
{% tab title="❌  error" %}

```swift
import Combine
import SwiftUI
import PlaygroundSupport

let url: URL = "https://source.unsplash.com/random"    // 🌀URL

// performs a network request to fetch a random image from Unsplash’s public API
func imagePub() -> AnyPublisher<Image?, Never> {
    URLSession.shared
        .dataTaskPublisher(for: url)
        .map { data, _ in Image(uiImage: UIImage(data: data)!)}
        .print("image")
        .replaceError(with: nil)
        .eraseToAnyPublisher()
}

struct ContentView: View {
    
    @State private var image: Image? = nil
    
    // simulate user taps on a button
    let taps = PassthroughSubject<Void, Never>()
    
    var subscriptions = Set<AnyCancellable>()
    
    init() {
        taps
            // ⭐️ map the tap to a new network request
            // ⭐️ Publisher<Void, Never> --> Publisher<Publisher<Image?, Never>, Never>
            //    — a publisher of publishers
            .map { _ in imagePub() }
            
            // ⭐️ accept only the latest tap
            .switchToLatest()
            
            // ❌ escaping closure captures mutating `self` parameter
            .sink { self.image = $0 }
            
            // ❌ 雖然下面的語法沒有出現錯誤訊息，但依然沒用
            // .assign(to: \.image, on: self)
            
            .store(in: &subscriptions)
    }
    
    var body: some View {
        VStack {
            image
            Button(action: {
                self.taps.send()
            }, label: {
                Text("Tap").padding().background(Color.pink).cornerRadius(12)
            })
        }.padding().background(Color.gray)
    }
}

PlaygroundPage.current.setLiveView(ContentView())
```

{% endtab %}

{% tab title="✅  OK" %}

```swift
/*
 https://stackoverflow.com/a/58327871/5409815
 */

import Combine
import SwiftUI
import PlaygroundSupport

let url: URL = "https://source.unsplash.com/random"

// performs a network request to fetch a random image from Unsplash’s public API
func imagePub() -> AnyPublisher<Image?, Never> {
    URLSession.shared
        .dataTaskPublisher(for: url)
        .map { data, _ in Image(uiImage: UIImage(data: data)!)}
        .print("image")
        .replaceError(with: nil)
        .eraseToAnyPublisher()
}

// ViewModel
class ViewModel: ObservableObject {
    
    // model
    @Published var image: Image?
    
    // simulate user taps on a button
    let taps = PassthroughSubject<Void, Never>()
    
    var subscriptions = Set<AnyCancellable>()
    
    init() {
        taps
            // ⭐️ map the tap to a new network request
            // ⭐️ Publisher<Void, Never> --> Publisher<Publisher<Image?, Never>, Never>
            //    — a publisher of publishers
            .map { _ in imagePub() }
            
            // ⭐️ accept only the latest tap
            .switchToLatest()
            
            .assign(to: \.image, on: self)
            .store(in: &subscriptions)
    }
    
    // user intent(s)
    func getImage() {
        taps.send()
    }
    
}

// ContentView
struct ContentView: View {
    
    // view model
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        VStack {
            
            // image
            viewModel.image?
                .resizable().scaledToFit()
                .frame(height: 400).border(Color.black)
            
            // button
            Button(action: {
                self.viewModel.getImage()
            }, label: {
                Text("Tap")
                    .padding().foregroundColor(.white)
                    .background(Color.pink).cornerRadius(12)
            })
            
        }.padding().background(Color.gray)
    }
}

PlaygroundPage.current.setLiveView(ContentView())
```

{% endtab %}

{% tab title="Result" %}
![](/files/-MLh5JGxjjez6oz1IEQ2)
{% endtab %}

{% tab title="🌀 套件" %}

* [🌀  URL](/ios/swift/scope/framework/built-in-frameworks/foundation/url/url.md)
  {% endtab %}

{% tab title="👥 相關" %}

* [📦 URLSession.DataTaskPublisher](/ios/swift/scope/framework/built-in-frameworks/combine/publishers/urlsession.datataskpublisher.md)
* [escaping closure](/ios/swift/type/category/basic/closure/escaping.md)
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/compiler-errors/escaping-closure-captures-mutating-self-parameter.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
