※ SwiftUI 2.0 の iOS 14+, macOS 11+ (Big Sur / Monterey), tvOS 14+, watchOS 7+ のみ解決方法を掲載します。
サンプルコード
import SwiftUI final class LoginViewModel: ObservableObject { var cancellables = Set<AnyCancellable>() // MARK: - Input @Published var email = "" @Published var password = "" // MARK: - Output @Published private(set) var canLogin = false init() { $password.map { password in let count = password.count return count >= 8 || count <= 32 } .assign(to: \.canLogin, on: self) .store(in: &cancellables) } }
これ、リークします。具体的には「.assign(to: \.canLogin, on: self)
」で self
への強参照 strong reference を持っているから。
書き換えは、以下の通り
init() { $password.map { password in let count = password.count return count >= 8 || count <= 32 } .assign(to: &$canLogin) }
一応 memory management 見ておくかーって思ってみたらリークしてるので、Combine あたり怪しいな、って思ってたんですが、assign は強参照を常に持つとはね。一応詳しい記事は以下に。
WWDC 2021 の Swift in ARC も必聴です。