Skip to content

Commit

Permalink
feat: 路由 添加参数
Browse files Browse the repository at this point in the history
  • Loading branch information
foxdock committed Aug 25, 2024
1 parent e5fad82 commit 1575bda
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 154 deletions.
4 changes: 2 additions & 2 deletions Demo/Demo/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ struct ContentView: View {
// }
Text(item.timestamp!, formatter: itemFormatter)
.onTapGesture {
let request = RouteRequest(.detail)
request.options["data"] = item
let request = RouteRequest(page: .detail)
request.param = item
Router.shared.go(request)
}

Expand Down
6 changes: 3 additions & 3 deletions Demo/Demo/providers/AppServiceProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ class AppServiceProvider: ServiceProvider {
app.provider(provider)
}
super.register()
Router.shared.add(pid: .root) { _ in
Router.shared.addPage(.root) { _ in
self.buildRoot()
}

Router.shared.add(pid: .detail) { req in
let item = req.options["data"] as? Item ?? Item()
Router.shared.addPage(.detail) { req in
let item = req.param as? Item ?? Item()
let timestap = item.timestamp ?? Date()
Text("Select an item \(timestap)")
}
Expand Down
4 changes: 2 additions & 2 deletions Demo/Demo/providers/RouteServiceProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ class RouteServiceProvider: ServiceProvider {
}
}

extension Router.PagePath {
static let detail = Router.PagePath(rawValue: "page/detail")
extension Router.RoutePath {
static let detail = Router.RoutePath(rawValue: "page/detail")
}
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
开发App常用工具和默认服务.


## 常用协议
- DFApplication 应用
## 常用组件 ServiceValues管理常用服务
- AppService 应用服务, 管理任务启动
- RouteService 路由服务


## 命名空间 app
- UIView/NSView 转SwiftUI View
Expand Down
1 change: 0 additions & 1 deletion Sources/DFService/exported.swift
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

@_exported import SwiftUI
144 changes: 0 additions & 144 deletions Sources/DFService/service/RouteService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,147 +3,3 @@ public struct RouteService: DFApiService {
return Value.shared
}
}

import SwiftUI

public class Router: ObservableObject {
typealias PageBuilder = (RouteRequest) -> any View
public static let shared = Router()

public var handler:(RouteRequest) -> PagePath = { _ in
return .page404
}

public var page404: (RouteRequest) -> any View = { _ in
return EmptyView()
}
@Published
public var rootPath = PagePath.root.request

@Published
public var pagePath = [RouteRequest]()
@Published
public var presentingSheet: RouteRequest?

private var pageBuilderMap = [PagePath: PageBuilder]()
public init() {}

var sheetBind: Binding<Bool> {
return .init {
return self.presentingSheet != nil
} set: { _ in
self.presentingSheet = nil
}

}
}

public extension Router {
func add(pid: PagePath,
@ViewBuilder
builder: @escaping (RouteRequest) -> some View) {
pageBuilderMap[pid] = builder
}
func page(_ request: RouteRequest) -> AnyView {
if(!request.isHandle) {
request.routePath = handler(request)
request.isHandle = true
}
let pid = request.routePath
guard let builder = pageBuilderMap[pid] else {
return AnyView(page404(request))
}
return AnyView(builder(request))
}


}
public extension Router {
func go(_ request: RouteRequest) {
if !request.isHandle {
request.routePath = handler(request)
request.isHandle = true
}
if(request.routePath == .root) {
popToRoot()
self.rootPath = request
return
}
switch request.routeType {
case .push:
pagePath.append(request)
case .present:
presentingSheet = request
}
}
func pop() {
if presentingSheet != nil {
presentingSheet = nil
} else if !pagePath.isEmpty {
pagePath.removeLast()
}
}
func popToRoot() {
if presentingSheet != nil {
presentingSheet = nil
}
pagePath.removeAll()
}
}


extension Router {
public struct PagePath: RawRepresentable, Equatable, Hashable {
public static let page404 = PagePath(rawValue: "page/404")
public static let root = PagePath(rawValue: "page/root")
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}

public var request: RouteRequest {
return RouteRequest(self)
}
}
}

extension EnvironmentValues {
var pageRouter: Router {
return serviceValues[RouteService.self]
}
}

public class RouteRequest: ObservableObject {

public let url: URL?
public var options = [String: Any]()
public var routeType = RouterType.push
public init(_ url: URL) {
self.url = url
self.isHandle = false
}
public init(_ routePath: Router.PagePath) {
self.url = nil
self.routePath = routePath
self.isHandle = true
}
/// 是否需要经过router handler
internal var isHandle: Bool = false
var routePath: Router.PagePath = .page404
}

extension RouteRequest: Hashable {
public static func == (lhs: RouteRequest, rhs: RouteRequest) -> Bool {
return lhs.routePath == rhs.routePath && lhs.url == rhs.url
}
public func hash(into hasher: inout Hasher) {
hasher.combine(routePath)
}
}

public extension RouteRequest {
enum RouterType {
case push
case present
}
}
55 changes: 55 additions & 0 deletions Sources/DFService/service/router/RouteRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

public class RouteRequest: ObservableObject {
public enum RouterType {
case push
case present
}
/// 路由操作
public var routeAction: Router.RouteAction = .empty
public let url: URL?
/// 参数
public var param: Any?
public var options = [String: Any]()
public var routeType = RouterType.push
public required init(url: URL) {
self.url = url
self.isHandle = false
}
public required init(action: Router.RouteAction, url: URL? = nil) {
self.url = url
self.routeAction = action
self.isHandle = true
}
/// 是否需要经过router handler
internal var isHandle: Bool = false
}


public extension RouteRequest {
/// 跳转到指定页面
convenience init(page: Router.RoutePath, url: URL? = nil){
self.init(action: .page(page), url: url)
}
var routePath: Router.RoutePath {
switch routeAction {
case .page(let path):
return path
default:
return .page404
}
}
}
public extension Router.RoutePath {
var request: RouteRequest {
return RouteRequest(page: self)
}
}
extension RouteRequest: Hashable {
public static func == (lhs: RouteRequest, rhs: RouteRequest) -> Bool {
return lhs.routeAction == rhs.routeAction && lhs.url == rhs.url
}
public func hash(into hasher: inout Hasher) {
hasher.combine(routePath)
hasher.combine(routeAction)
}
}
50 changes: 50 additions & 0 deletions Sources/DFService/service/router/Router.action.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
extension Router {
fileprivate func handlePage(_ request: RouteRequest) {
if(request.routePath == .root) {
popToRoot()
self.rootPath = request
return
}
switch request.routeType {
case .push:
pagePath.append(request)
case .present:
presentingSheet = request
}
}
fileprivate func handleAction(_ request: RouteRequest) {
guard let builder = self.actionBuilderMap[request.routePath] else {
return
}
builder(request)
}
}
public extension Router {
func go(_ request: RouteRequest) {
if !request.isHandle {
request.routeAction = handler(request)
request.isHandle = true
}
switch request.routeAction {
case .empty: break
case .page:
handlePage(request)
case .action:
handleAction(request)
}

}
func pop() {
if presentingSheet != nil {
presentingSheet = nil
} else if !pagePath.isEmpty {
pagePath.removeLast()
}
}
func popToRoot() {
if presentingSheet != nil {
presentingSheet = nil
}
pagePath.removeAll()
}
}
83 changes: 83 additions & 0 deletions Sources/DFService/service/router/Router.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
public class Router: ObservableObject {
public enum RouteAction: Equatable, Hashable {
case empty
case page(Router.RoutePath)
case action(Router.RoutePath)
}

public struct RoutePath: RawRepresentable, Equatable, Hashable {
public static let page404 = RoutePath(rawValue: "page/404")
public static let root = RoutePath(rawValue: "page/root")
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
}

typealias PageBuilder = (RouteRequest) -> any View
typealias ActionBuilder = (RouteRequest) -> Void
public static let shared = Router()

public var handler:(RouteRequest) -> RouteAction = { _ in
return .empty
}

public var page404: (RouteRequest) -> any View = { _ in
return EmptyView()
}
@Published
public var rootPath = RoutePath.root.request

@Published
public var pagePath = [RouteRequest]()
@Published
public var presentingSheet: RouteRequest?

internal var pageBuilderMap = [RoutePath: PageBuilder]()
internal var actionBuilderMap = [RoutePath: ActionBuilder]()
public init() {}

var sheetBind: Binding<Bool> {
return .init {
return self.presentingSheet != nil
} set: { _ in
self.presentingSheet = nil
}

}
}

public extension Router {
func addPage(_ path: RoutePath,
@ViewBuilder
builder: @escaping (RouteRequest) -> some View) {
pageBuilderMap[path] = builder
}
func addAction(_ path: RoutePath,
@ViewBuilder
builder: @escaping (RouteRequest) -> Void) {
actionBuilderMap[path] = builder
}
func page(_ request: RouteRequest) -> AnyView {
if(!request.isHandle) {
request.routeAction = handler(request)
request.isHandle = true
}
let pid = request.routePath
guard let builder = pageBuilderMap[pid] else {
return AnyView(page404(request))
}
return AnyView(builder(request))
}
}


extension Router {

}

extension EnvironmentValues {
var pageRouter: Router {
return serviceValues[RouteService.self]
}
}

0 comments on commit 1575bda

Please sign in to comment.