Skip to content

Router Example

TeChengHung edited this page Nov 15, 2022 · 3 revisions
public protocol APIRouter {
  var environment: Environment { get }
  var scheme: String { get }
  var host: String { get }
  var basePath: String { get }
  var path: String { get }
  var parameters: [String: String]? { get }
  var url: URL { get }
}

extension APIRouter {
  public var environment: Environment {
    let isDev = ProcessInfo.processInfo.environment[buildForKey] == Environment.dev.rawValue

    return isDev ? .dev : .prod
  }

  public var scheme: String {
    return "https"
  }

  public var host: String {
    switch environment {
    case .prod:
      return "api.prod.com"
    case .dev:
      return "api.dev.tw"
    }
  }

  public var basePath: String {
    return "/base/v3"
  }

  public var url: URL {
    var components = URLComponents()
    components.scheme = scheme
    components.host = host
    components.path = basePath + path

    if let parameters = parameters {
      components.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
    }

    return components.url!
  }

  func unwrap(_ id: String?) -> String {
    switch id {
    case let .some(value):
      return "/\(value)"
    case .none:
      return ""
    }
  }
}

ActivityRouter 為例:

public enum ActivityRouter {
  public typealias Parameters = [String: String]

  case badges(parameters: Parameters)
  case meActivity(parameters: Parameters?)
  case meDashboard
}

extension ActivityRouter: APIRouter {
  public var parameters: Parameters? {
    switch self {
    case let .meActivity(parameters):
      return parameters

    case let .badges(parameters):
      return parameters

    case .meDashboard:
      return nil
    }
  }

  public var path: String {
    switch self {
    case .badges:
      return "/badges"

    case .meActivity:
      return "/me/activity"

    case .meDashboard:
      return "/me/dashboard"
    }
  }
}

How to use

  private func fetchData(completion: @escaping (Set<String>) -> Void) {
    let parameters = getParameters()
    let url = ActivityRouter.meDailyReadings(parameters: parameters).url
    cancellable = loader(url)
      .dispatchOnMainQueue()
      .sink(receiveCompletion: { _ in
      }, receiveValue: { value in
        let completedSet = Set(value.filter(\.completed).map(\.id))
        completion(completedSet)
      })
  }
Clone this wiki locally