-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IOS-8044 Fix multiple leaks #3940
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,42 +21,17 @@ class CommonUserWalletModel { | |
@Injected(\.pushNotificationsInteractor) private var pushNotificationsInteractor: PushNotificationsInteractor | ||
|
||
let walletModelsManager: WalletModelsManager | ||
|
||
var userTokensManager: UserTokensManager { _userTokensManager } | ||
|
||
private lazy var _userTokensManager = CommonUserTokensManager( | ||
userWalletId: userWalletId, | ||
shouldLoadSwapAvailability: config.isFeatureVisible(.swapping), | ||
userTokenListManager: userTokenListManager, | ||
walletModelsManager: walletModelsManager, | ||
derivationStyle: config.derivationStyle, | ||
derivationManager: derivationManager, | ||
keysDerivingProvider: self, | ||
existingCurves: config.existingCurves, | ||
longHashesSupported: config.hasFeature(.longHashes) | ||
) | ||
|
||
let userTokensManager: UserTokensManager | ||
let userTokenListManager: UserTokenListManager | ||
let keysRepository: KeysRepository | ||
let derivationManager: DerivationManager? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CommonUserWalletModel не деинитилась из-за derivationManager, который юзается в других сервисах, которые, в свою очередь лежали тут как lazy. Без изменения логики унес всю сборку из конструктора в отдельную фабрику, что в принципе чище, заодно и решило утечку |
||
let totalBalanceProvider: TotalBalanceProviding | ||
|
||
private let walletManagersRepository: WalletManagersRepository | ||
private let cardImageProvider = CardImageProvider() | ||
|
||
private var associatedCardIds: Set<String> | ||
|
||
lazy var derivationManager: DerivationManager? = { | ||
guard config.hasFeature(.hdWallets) else { | ||
return nil | ||
} | ||
|
||
let commonDerivationManager = CommonDerivationManager( | ||
keysRepository: keysRepository, | ||
userTokenListManager: userTokenListManager | ||
) | ||
|
||
commonDerivationManager.delegate = self | ||
return commonDerivationManager | ||
}() | ||
|
||
var signer: TangemSigner { _signer } | ||
|
||
var cardId: String { cardInfo.card.cardId } | ||
|
@@ -77,12 +52,6 @@ class CommonUserWalletModel { | |
|
||
let userWalletId: UserWalletId | ||
|
||
lazy var totalBalanceProvider: TotalBalanceProviding = TotalBalanceProvider( | ||
userWalletId: userWalletId, | ||
walletModelsManager: walletModelsManager, | ||
derivationManager: derivationManager | ||
) | ||
|
||
private(set) var cardInfo: CardInfo | ||
private var tangemSdk: TangemSdk? | ||
var config: UserWalletConfig | ||
|
@@ -99,44 +68,34 @@ class CommonUserWalletModel { | |
} | ||
} | ||
|
||
convenience init?(userWallet: StoredUserWallet) { | ||
let cardInfo = userWallet.cardInfo() | ||
self.init(cardInfo: cardInfo) | ||
let allIds = associatedCardIds.union(userWallet.associatedCardIds) | ||
associatedCardIds = allIds | ||
} | ||
|
||
init?(cardInfo: CardInfo) { | ||
let config = UserWalletConfigFactory(cardInfo).makeConfig() | ||
associatedCardIds = [cardInfo.card.cardId] | ||
guard let userWalletIdSeed = config.userWalletIdSeed, | ||
let walletManagerFactory = try? config.makeAnyWalletManagerFactory() else { | ||
return nil | ||
} | ||
|
||
init( | ||
cardInfo: CardInfo, | ||
config: UserWalletConfig, | ||
userWalletId: UserWalletId, | ||
associatedCardIds: Set<String>, | ||
walletManagersRepository: WalletManagersRepository, | ||
walletModelsManager: WalletModelsManager, | ||
userTokensManager: CommonUserTokensManager, | ||
userTokenListManager: UserTokenListManager, | ||
keysRepository: KeysRepository, | ||
derivationManager: DerivationManager?, | ||
totalBalanceProvider: TotalBalanceProviding | ||
) { | ||
self.cardInfo = cardInfo | ||
self.config = config | ||
keysRepository = CommonKeysRepository(with: cardInfo.card.wallets) | ||
|
||
userWalletId = UserWalletId(with: userWalletIdSeed) | ||
userTokenListManager = CommonUserTokenListManager( | ||
userWalletId: userWalletId.value, | ||
supportedBlockchains: config.supportedBlockchains, | ||
hdWalletsSupported: config.hasFeature(.hdWallets), | ||
hasTokenSynchronization: config.hasFeature(.tokenSynchronization), | ||
defaultBlockchains: config.defaultBlockchains | ||
) | ||
|
||
walletManagersRepository = CommonWalletManagersRepository( | ||
keysProvider: keysRepository, | ||
userTokenListManager: userTokenListManager, | ||
walletManagerFactory: walletManagerFactory | ||
) | ||
|
||
walletModelsManager = CommonWalletModelsManager( | ||
walletManagersRepository: walletManagersRepository, | ||
walletModelsFactory: config.makeWalletModelsFactory() | ||
) | ||
self.userWalletId = userWalletId | ||
|
||
var associatedCardIds = associatedCardIds | ||
associatedCardIds.insert(cardInfo.card.cardId) | ||
self.associatedCardIds = associatedCardIds | ||
|
||
self.walletManagersRepository = walletManagersRepository | ||
self.walletModelsManager = walletModelsManager | ||
self.userTokensManager = userTokensManager | ||
self.userTokenListManager = userTokenListManager | ||
self.keysRepository = keysRepository | ||
self.derivationManager = derivationManager | ||
self.totalBalanceProvider = totalBalanceProvider | ||
|
||
_signer = config.tangemSigner | ||
_userWalletNamePublisher = .init(cardInfo.name) | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,97 @@ | ||||||||||||||||||||||
// | ||||||||||||||||||||||
// CommonUserWalletModelFactory.swift | ||||||||||||||||||||||
// Tangem | ||||||||||||||||||||||
// | ||||||||||||||||||||||
// Created by Alexander Osokin on 24.09.2024. | ||||||||||||||||||||||
// Copyright © 2024 Tangem AG. All rights reserved. | ||||||||||||||||||||||
// | ||||||||||||||||||||||
|
||||||||||||||||||||||
import Foundation | ||||||||||||||||||||||
|
||||||||||||||||||||||
struct CommonUserWalletModelFactory { | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. По сути код без каких-либо изменений логики переехал сюда |
||||||||||||||||||||||
func makeModel(userWallet: StoredUserWallet) -> CommonUserWalletModel? { | ||||||||||||||||||||||
let cardInfo = userWallet.cardInfo() | ||||||||||||||||||||||
return makeModel(cardInfo: cardInfo, associatedCardIds: userWallet.associatedCardIds) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func makeModel(cardInfo: CardInfo, associatedCardIds: Set<String> = []) -> CommonUserWalletModel? { | ||||||||||||||||||||||
let config = UserWalletConfigFactory(cardInfo).makeConfig() | ||||||||||||||||||||||
|
||||||||||||||||||||||
guard let userWalletIdSeed = config.userWalletIdSeed, | ||||||||||||||||||||||
let walletManagerFactory = try? config.makeAnyWalletManagerFactory() else { | ||||||||||||||||||||||
return nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+20
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: как будто так чуток читабельнее
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Когда на это смотришь в гитхабе, то да) А в коде, с подсветкой синтаксиса кажется и так норм) |
||||||||||||||||||||||
|
||||||||||||||||||||||
let userWalletId = UserWalletId(with: userWalletIdSeed) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let keysRepository = CommonKeysRepository(with: cardInfo.card.wallets) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let userTokenListManager = CommonUserTokenListManager( | ||||||||||||||||||||||
userWalletId: userWalletId.value, | ||||||||||||||||||||||
supportedBlockchains: config.supportedBlockchains, | ||||||||||||||||||||||
hdWalletsSupported: config.hasFeature(.hdWallets), | ||||||||||||||||||||||
hasTokenSynchronization: config.hasFeature(.tokenSynchronization), | ||||||||||||||||||||||
defaultBlockchains: config.defaultBlockchains | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let walletManagersRepository = CommonWalletManagersRepository( | ||||||||||||||||||||||
keysProvider: keysRepository, | ||||||||||||||||||||||
userTokenListManager: userTokenListManager, | ||||||||||||||||||||||
walletManagerFactory: walletManagerFactory | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let walletModelsManager = CommonWalletModelsManager( | ||||||||||||||||||||||
walletManagersRepository: walletManagersRepository, | ||||||||||||||||||||||
walletModelsFactory: config.makeWalletModelsFactory() | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let derivationManager: CommonDerivationManager? = { | ||||||||||||||||||||||
guard config.hasFeature(.hdWallets) else { | ||||||||||||||||||||||
return nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
let commonDerivationManager = CommonDerivationManager( | ||||||||||||||||||||||
keysRepository: keysRepository, | ||||||||||||||||||||||
userTokenListManager: userTokenListManager | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
return commonDerivationManager | ||||||||||||||||||||||
}() | ||||||||||||||||||||||
|
||||||||||||||||||||||
let totalBalanceProvider = TotalBalanceProvider( | ||||||||||||||||||||||
userWalletId: userWalletId, | ||||||||||||||||||||||
walletModelsManager: walletModelsManager, | ||||||||||||||||||||||
derivationManager: derivationManager | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let userTokensManager = CommonUserTokensManager( | ||||||||||||||||||||||
userWalletId: userWalletId, | ||||||||||||||||||||||
shouldLoadSwapAvailability: config.isFeatureVisible(.swapping), | ||||||||||||||||||||||
userTokenListManager: userTokenListManager, | ||||||||||||||||||||||
walletModelsManager: walletModelsManager, | ||||||||||||||||||||||
derivationStyle: config.derivationStyle, | ||||||||||||||||||||||
derivationManager: derivationManager, | ||||||||||||||||||||||
existingCurves: config.existingCurves, | ||||||||||||||||||||||
longHashesSupported: config.hasFeature(.longHashes) | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
let model = CommonUserWalletModel( | ||||||||||||||||||||||
cardInfo: cardInfo, | ||||||||||||||||||||||
config: config, | ||||||||||||||||||||||
userWalletId: userWalletId, | ||||||||||||||||||||||
associatedCardIds: associatedCardIds, | ||||||||||||||||||||||
walletManagersRepository: walletManagersRepository, | ||||||||||||||||||||||
walletModelsManager: walletModelsManager, | ||||||||||||||||||||||
userTokensManager: userTokensManager, | ||||||||||||||||||||||
userTokenListManager: userTokenListManager, | ||||||||||||||||||||||
keysRepository: keysRepository, | ||||||||||||||||||||||
derivationManager: derivationManager, | ||||||||||||||||||||||
totalBalanceProvider: totalBalanceProvider | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
derivationManager?.delegate = model | ||||||||||||||||||||||
userTokensManager.keysDerivingProvider = model | ||||||||||||||||||||||
|
||||||||||||||||||||||
return model | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,36 +14,27 @@ typealias OnRefresh = (_ completionHandler: @escaping RefreshCompletionHandler) | |
/// Author: The SwiftUI Lab. | ||
/// Full article: https://swiftui-lab.com/scrollview-pull-to-refresh/. | ||
struct RefreshableScrollView<Content: View>: View { | ||
let onRefresh: OnRefresh | ||
let content: Content | ||
private let refreshContainer: RefreshContainer | ||
|
||
init( | ||
onRefresh: @escaping OnRefresh, | ||
@ViewBuilder content: () -> Content | ||
) { | ||
self.onRefresh = onRefresh | ||
self.content = content() | ||
refreshContainer = RefreshContainer(onRefresh: onRefresh) | ||
} | ||
|
||
var body: some View { | ||
if #available(iOS 16, *) { | ||
ScrollView(.vertical, showsIndicators: false) { | ||
content | ||
} | ||
.refreshable { | ||
await refreshAsync() | ||
.refreshable { [weak refreshContainer] in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Самая жесткая утечка, помог коммент @Vyachesl0ve. Теперь в памяти ничего не остается, это юзалось и в свопе, так что там тоже пофиксится, если конечно не найдется других утечек |
||
await refreshContainer?.refreshAsync() | ||
} | ||
} else { | ||
RefreshableScrollViewCompat(onRefresh: onRefresh, content: content) | ||
} | ||
} | ||
|
||
@MainActor | ||
private func refreshAsync() async { | ||
await withCheckedContinuation { continuation in | ||
onRefresh { | ||
continuation.resume() | ||
} | ||
RefreshableScrollViewCompat(onRefresh: refreshContainer.onRefresh, content: content) | ||
} | ||
} | ||
} | ||
|
@@ -167,6 +158,27 @@ private struct RefreshableScrollViewCompat<Content: View>: View { | |
} | ||
} | ||
|
||
// MARK: - RefreshContainer | ||
|
||
extension RefreshableScrollView { | ||
private final class RefreshContainer { | ||
let onRefresh: OnRefresh | ||
|
||
init(onRefresh: @escaping OnRefresh) { | ||
self.onRefresh = onRefresh | ||
} | ||
|
||
@MainActor | ||
func refreshAsync() async { | ||
await withCheckedContinuation { continuation in | ||
onRefresh { | ||
continuation.resume() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Previews | ||
|
||
struct RefreshableScrollViewView_Previews: PreviewProvider { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
техническая правка, чтобы завести фабрику