Skip to content
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

Feature/deeplink api #338

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Feature/deeplink api #338

wants to merge 8 commits into from

Conversation

castlele
Copy link
Contributor

@castlele castlele commented Jan 11, 2023

Deeplink api

Как начать использовать

Для корректной работы необходимо:

  1. создать объект имплементирующий протокол DeeplinkType;
  2. создать объект имплементирующий протокол DeeplinkMapper;
  3. создать объект имплементирующий протокол DeeplinkHandler;
  4. настроить TIDeeplinkService.

1. DeeplinkType

Сам по себе является пустым протоколом

enum ProjectDeeplink: String, DeeplinkType {
    case someScreen
    case someOtherScreen
}

2. DeeplinkMapper

Объект, соответствующий данному протоколу, должен отвечать за преобразование URL 'а в объект DeeplinkType

struct ProjectDeeplinkMapper: DeeplinkMapper {
    func map(url: URL) -> DeeplinkType? {
        let stringData = parse(url)
        return ProjectDeeplink(rawValue: host)
    }

    private func parse(_ url: URL) -> String {
        // parse url to some data
    }
}

3. DeeplinkHandler

Объект, отвечающий за управление диплинком. Если объект может обработать диплинк, то он выдает необходимый набор инструкций

extension MainFlow: DeeplinkHandler {
    func canHandle(deeplink: DeeplinkType) -> Bool {
        guard let _ = deeplink as? ProjectDeeplink else {
            return false
        }

        return true
    }

    func handle(deeplink: DeeplinkType) -> Operation? {
        guard let deeplink = deeplink as? ProjectDeeplink else {
            return nil
        }

        switch deeplink {
        case . someScreen:
            return BlockOperation { [weak self] in
                self?.openSomeView()
            }

        case . someOtherScreen:
            return BlockOperation { [weak self] in
                self?.openSomeOtherView()
            }
        }
    }
}

Существует также базовая реализация BaseNavigationStackDeeplinkHandler. Она старается найти обработчик диплинка в иерархии вью.

4. TIDeeplinkService

Синглтон класс для работы с диплинками. Для его работы необходимо произвести конфигурацию созданными объектами: DeeplinkMapper, DeeplinkHandler

let someMapper = ProjectDeeplinkMapper()
let someHandler = mainFlow
TIDeeplinksService.shared.configure(mapper: someMapper, handler: someHandler)

Теперь все готово к использованию сервиса

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        TIDeeplinksService.shared.deferredHandle(url: url)
        TIDeeplinksService.shared.tryHandle()
        return true
}

// MARK: - Open methods

open func findHandler(for deeplink: DeeplinkType) -> DeeplinkHandler? {
guard let rootController = UIApplication.shared.keyWindow?.rootViewController else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

давай лучше протоколом закроем, который будет предоставлять rootDeeplinkHandlerController (UIViewController)

Comment on lines 26 to 27
func canHandle(deeplink: DeeplinkType) -> Bool
func handle(deeplink: DeeplinkType) -> Operation?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я думаю, что нам хватит второго метода т.к. он возвращает optional
либо handler к которому мы обратились не может обработать deeplink (возвращает nil)
либо он сам найдёт внутри себя обработчика

Comment on lines 23 to 24
public protocol DeeplinkType {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а можем обойтись associatedType или generic вместо пустого протокола?

import Foundation
import TIFoundationUtils

public final class TIDeeplinksService {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сервис надо создавать самостоятельно с generic аргументом deeplink type


// MARK: - Private properties

private let operationQueue = OperationQueue.main
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

параметром в init

Comment on lines 34 to 36
private var pendingDeeplink: DeeplinkType?

private(set) var isProcessingDeeplink = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

уже есть реализация актуальней

# Conflicts:
#	LeadKit.podspec
#	TIAppleMapUtils/TIAppleMapUtils.podspec
#	TIAuth/TIAuth.podspec
#	TIEcommerce/TIEcommerce.podspec
#	TIFoundationUtils/TIFoundationUtils.podspec
#	TIGoogleMapUtils/TIGoogleMapUtils.podspec
#	TIKeychainUtils/TIKeychainUtils.podspec
#	TILogging/TILogging.podspec
#	TIMapUtils/TIMapUtils.podspec
#	TIMoyaNetworking/TIMoyaNetworking.podspec
#	TINetworking/TINetworking.podspec
#	TINetworkingCache/TINetworkingCache.podspec
#	TIPagination/TIPagination.podspec
#	TISwiftUICore/TISwiftUICore.podspec
#	TISwiftUtils/TISwiftUtils.podspec
#	TITableKitUtils/TITableKitUtils.podspec
#	TITransitions/TITransitions.podspec
#	TIUIElements/TIUIElements.podspec
#	TIUIKitCore/TIUIKitCore.podspec
#	TIYandexMapUtils/TIYandexMapUtils.podspec
Comment on lines 75 to 86
open func tryHandle() {
guard !deeplinkQueue.isEmpty else {
return
}

handle()
}

open func handle() {
guard let deeplink = deeplinkQueue.first else {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

один метод тут лишний

handle()
}

open func handle() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handlePendingDeeplinks

Comment on lines 45 to 54
public init(operationQueue: OperationQueue = .main) {
self.operationQueue = operationQueue
}

// MARK: - Open methods

open func configure(mapper: Mapper, handler: Handler) {
deeplinkMapper = mapper
deeplinkHandler = handler
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

давай лучше и Mapper и Handler в init

}

open func handle() {
guard let deeplink = deeplinkQueue.first else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

также можно сразу проверить let handler

}

@discardableResult
open func deferredHandle(url: URL) -> Bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут можно подписать в комменте к методу, что значит возвращаемый bool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants