fix: update an approach to handling operation in TIDeeplinkService
This commit is contained in:
parent
caeded9561
commit
63777fef99
|
|
@ -23,14 +23,15 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
|
||||
open class BaseNavigationStackDeeplinkHandler: DeeplinkHandler {
|
||||
open class BaseNavigationStackDeeplinkHandler<ControllerKeeper: RootViewControllerKeeper>: DeeplinkHandler {
|
||||
|
||||
public typealias DeeplinkType = ControllerKeeper.DeeplinkHandler.DeeplinkType
|
||||
public typealias Handler = ControllerKeeper.DeeplinkHandler
|
||||
|
||||
public var rootViewControllerKeeper: ControllerKeeper?
|
||||
|
||||
// MARK: - DeeplinkHandler
|
||||
|
||||
open func canHandle(deeplink: DeeplinkType) -> Bool {
|
||||
findHandler(for: deeplink) != nil
|
||||
}
|
||||
|
||||
open func handle(deeplink: DeeplinkType) -> Operation? {
|
||||
let handler = findHandler(for: deeplink)
|
||||
return handler?.handle(deeplink: deeplink)
|
||||
|
|
@ -38,8 +39,9 @@ open class BaseNavigationStackDeeplinkHandler: DeeplinkHandler {
|
|||
|
||||
// MARK: - Open methods
|
||||
|
||||
open func findHandler(for deeplink: DeeplinkType) -> DeeplinkHandler? {
|
||||
guard let rootController = UIApplication.shared.keyWindow?.rootViewController else {
|
||||
open func findHandler(for deeplink: DeeplinkType) -> Handler? {
|
||||
|
||||
guard let rootController = rootViewControllerKeeper?.rootDeeplinkHandlerController else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
import Foundation
|
||||
|
||||
public protocol DeeplinkHandler {
|
||||
func canHandle(deeplink: DeeplinkType) -> Bool
|
||||
associatedtype DeeplinkType: Hashable
|
||||
|
||||
func handle(deeplink: DeeplinkType) -> Operation?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,33 +26,40 @@ public typealias DeeplinkHandlerViewController = DeeplinkHandler & UIViewControl
|
|||
|
||||
public extension UIViewController {
|
||||
|
||||
func findHandler(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? {
|
||||
if let deeplinksHandler = self as? DeeplinkHandlerViewController,
|
||||
deeplinksHandler.canHandle(deeplink: deeplink) {
|
||||
func findHandler<DeeplinkHandler: DeeplinkHandlerViewController>(
|
||||
for deeplink: DeeplinkHandler.DeeplinkType
|
||||
) -> DeeplinkHandler? {
|
||||
|
||||
if let deeplinksHandler = self as? DeeplinkHandler,
|
||||
let _ = deeplinksHandler.handle(deeplink: deeplink) {
|
||||
return deeplinksHandler
|
||||
}
|
||||
|
||||
if let deeplinksHandler = presentedViewController?.findHandler(for: deeplink) {
|
||||
if let deeplinksHandler: DeeplinkHandler = presentedViewController?.findHandler(for: deeplink) {
|
||||
return deeplinksHandler
|
||||
}
|
||||
|
||||
return findHandlerInViewHierarchy(for: deeplink)
|
||||
}
|
||||
|
||||
private func findHandlerInViewHierarchy(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? {
|
||||
private func findHandlerInViewHierarchy<DeeplinkHandler: DeeplinkHandlerViewController>(
|
||||
for deeplink: DeeplinkHandler.DeeplinkType
|
||||
) -> DeeplinkHandler? {
|
||||
|
||||
switch self {
|
||||
case let navController as UINavigationController:
|
||||
return navController.viewControllers.reversed().findHadler(for: deeplink)
|
||||
let deeplinksHandler: DeeplinkHandler? = navController.viewControllers.reversed().findHandler(for: deeplink)
|
||||
return deeplinksHandler
|
||||
|
||||
case let tabController as UITabBarController:
|
||||
if let deeplinksHandler = tabController.selectedViewController?.findHandler(for: deeplink) {
|
||||
if let deeplinksHandler: DeeplinkHandler = tabController.selectedViewController?.findHandler(for: deeplink) {
|
||||
return deeplinksHandler
|
||||
} else if var tabControllers = tabController.viewControllers {
|
||||
if tabController.selectedIndex != NSNotFound {
|
||||
tabControllers.remove(at: tabController.selectedIndex)
|
||||
}
|
||||
|
||||
if let deeplinksHandler = tabControllers.findHadler(for: deeplink) {
|
||||
if let deeplinksHandler: DeeplinkHandler = tabControllers.findHandler(for: deeplink) {
|
||||
return deeplinksHandler
|
||||
}
|
||||
}
|
||||
|
|
@ -66,9 +73,12 @@ public extension UIViewController {
|
|||
}
|
||||
|
||||
private extension Sequence where Element: UIViewController {
|
||||
func findHadler(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? {
|
||||
func findHandler<DeeplinkHandler: DeeplinkHandlerViewController>(
|
||||
for deeplink: DeeplinkHandler.DeeplinkType
|
||||
) -> DeeplinkHandler? {
|
||||
|
||||
for controller in self {
|
||||
if let deeplinksHandler = controller.findHandler(for: deeplink) {
|
||||
if let deeplinksHandler: DeeplinkHandler = controller.findHandler(for: deeplink) {
|
||||
return deeplinksHandler
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,5 +20,10 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
public protocol DeeplinkType {
|
||||
import UIKit
|
||||
|
||||
public protocol RootViewControllerKeeper {
|
||||
associatedtype DeeplinkHandler: DeeplinkHandlerViewController
|
||||
|
||||
var rootDeeplinkHandlerController: DeeplinkHandler { get }
|
||||
}
|
||||
|
|
@ -23,5 +23,7 @@
|
|||
import Foundation
|
||||
|
||||
public protocol DeeplinkMapper {
|
||||
associatedtype DeeplinkType
|
||||
|
||||
func map(url: URL) -> DeeplinkType?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,71 +23,83 @@
|
|||
import Foundation
|
||||
import TIFoundationUtils
|
||||
|
||||
public final class TIDeeplinksService {
|
||||
|
||||
public static let shared = TIDeeplinksService()
|
||||
open class TIDeeplinksService<DeeplinkType: Hashable,
|
||||
Mapper: DeeplinkMapper,
|
||||
Handler: DeeplinkHandler> where Mapper.DeeplinkType == Handler.DeeplinkType,
|
||||
Mapper.DeeplinkType == DeeplinkType {
|
||||
|
||||
// MARK: - Private properties
|
||||
|
||||
private let operationQueue = OperationQueue.main
|
||||
private var operationQueue: OperationQueue
|
||||
|
||||
private var pendingDeeplink: DeeplinkType?
|
||||
|
||||
private(set) var isProcessingDeeplink = false
|
||||
private var deeplinkQueue: [DeeplinkType] = []
|
||||
private var inProcessingSet: Set<DeeplinkType> = []
|
||||
|
||||
// MARK: - Public properties
|
||||
|
||||
public var deeplinkMapper: DeeplinkMapper?
|
||||
public var deeplinkHandler: DeeplinkHandler?
|
||||
public var deeplinkMapper: Mapper?
|
||||
public var deeplinkHandler: Handler?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
private init() {
|
||||
|
||||
public init(operationQueue: OperationQueue = .main) {
|
||||
self.operationQueue = operationQueue
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
// MARK: - Open methods
|
||||
|
||||
public func configure(mapper: DeeplinkMapper, handler: DeeplinkHandler) {
|
||||
open func configure(mapper: Mapper, handler: Handler) {
|
||||
deeplinkMapper = mapper
|
||||
deeplinkHandler = handler
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func deferredHandle(url: URL) -> Bool {
|
||||
pendingDeeplink = deeplinkMapper?.map(url: url)
|
||||
return pendingDeeplink != nil
|
||||
open func deferredHandle(url: URL) -> Bool {
|
||||
let deeplink = deeplinkMapper?.map(url: url)
|
||||
|
||||
guard let deeplink = deeplink else {
|
||||
return false
|
||||
}
|
||||
|
||||
deeplinkQueue.append(deeplink)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
open func reset() {
|
||||
operationQueue.cancelAllOperations()
|
||||
pendingDeeplink = nil
|
||||
isProcessingDeeplink = false
|
||||
deeplinkQueue.removeAll()
|
||||
inProcessingSet.removeAll()
|
||||
}
|
||||
|
||||
public func tryHandle() {
|
||||
guard let deeplink = pendingDeeplink,
|
||||
deeplinkHandler?.canHandle(deeplink: deeplink) ?? false else {
|
||||
open func tryHandle() {
|
||||
guard !deeplinkQueue.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
handle()
|
||||
}
|
||||
|
||||
public func handle() {
|
||||
guard let deeplink = pendingDeeplink,
|
||||
let lastOperation = deeplinkHandler?.handle(deeplink: deeplink) else {
|
||||
open func handle() {
|
||||
guard let deeplink = deeplinkQueue.first else {
|
||||
return
|
||||
}
|
||||
|
||||
operationQueue.addOperation { [weak self] in
|
||||
self?.isProcessingDeeplink = true
|
||||
self?.pendingDeeplink = nil
|
||||
deeplinkQueue.remove(at: .zero)
|
||||
|
||||
guard !inProcessingSet.contains(deeplink),
|
||||
let operation = deeplinkHandler?.handle(deeplink: deeplink) else {
|
||||
return
|
||||
}
|
||||
operationQueue.addOperations(lastOperation.flattenDependencies + [lastOperation],
|
||||
waitUntilFinished: false)
|
||||
operationQueue.addOperation { [weak self] in
|
||||
self?.isProcessingDeeplink = false
|
||||
|
||||
inProcessingSet.formUnion([deeplink])
|
||||
|
||||
let competionOperation = BlockOperation { [weak self] in
|
||||
self?.inProcessingSet.subtract([deeplink])
|
||||
}
|
||||
|
||||
competionOperation.addDependency(operation)
|
||||
|
||||
competionOperation.add(to: operationQueue)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue