Skip to content

Commit

Permalink
新增 Application (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
foxdock authored Aug 29, 2024
1 parent 4be7e09 commit b8d5e22
Show file tree
Hide file tree
Showing 21 changed files with 160 additions and 156 deletions.
6 changes: 3 additions & 3 deletions Demo/Demo/DemoApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ struct DemoApp: App {
appService.bootstrap(.eager)
}
@ObservedObject
var appService = ServiceValues[AppService.self]
var appService = Application.shared
@SceneBuilder
public var body: some Scene {
WindowGroup {
appService.rootView
.chain { view in
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
view.task {
appService.bootstrap(.root)
appService.bootstrap(.splash)
}
} else {
view.onAppear {
appService.bootstrap(.root)
appService.bootstrap(.splash)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Demo/Demo/Persistence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import CoreData
import DFService
struct PersistenceController {
static var runtime: PersistenceController {
if ServiceValues[RuntimeService.self].isPreview {
if Application.shared[RuntimeService.self].isPreview {
return Self.preview
} else {
return Self.shared
Expand Down
5 changes: 3 additions & 2 deletions Demo/Demo/providers/RouteServiceProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import DFService
import SwiftUI
class RouteServiceProvider: ServiceProvider {

override func performAsyncStartup() async {
override func performAsyncStartup() async throws {
// app.rootView = AnyView(buildRoot())
throw CommonError.unImplemented()
}
override var when: ServiceProvider.ProviderWhen {
return .window
return .eager
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
public struct ServiceValues {
import SwiftUI

public class Application {
public static let version = "0.1.0"

public static var shared = ServiceValues()
fileprivate static var _instance: Application?
public var loadProviders: [DFService.ServiceProvider] = []
@Published
public var rootView: AnyView = AnyView(RouterView())
private var storage: [FactoryKey: Any] = [:]
private var serviceNames: [ServiceName: FactoryKey] = [:]

public init() {}

public required init() {}
}

extension ServiceValues {
public static subscript<Service: DFApiService>(service: Service.Type, tag: String = "")
-> Service.Value
{
get {
return Self.shared[service, tag]
}
set {
Self.shared[service, tag] = newValue
}
}
public subscript<Service: DFApiService>(service: Service.Type, tag: String = "") -> Service.Value
{
extension Application: DFApplication {
public subscript<Service>(service: Service.Type, tag: String = "") -> Service.Value where Service : DFServiceKey {
get {
let key = FactoryKey(type: service, tag: tag)
if let value = storage[key] as? Service.Value {
Expand All @@ -34,7 +25,29 @@ extension ServiceValues {
storage[key] = newValue
}
}
public subscript<Service: DFApiService>(_ name: ServiceName, tag: String = "") -> Service.Type? {

public var providerType: [DFService.ServiceProvider.Type] {
return []
}

public static var shared: Application {
if let value = _instance {
return value
}
let value = Application()
_instance = value
do {
let provider = try Bundle.main.app.loadClass(ofType: ServiceProvider.self, named: "AppServiceProvider")
value.provider(provider)
} catch {

}
return value
}
}

extension Application {
public subscript<Service: DFServiceKey>(_ name: ServiceName, tag: String = "") -> Service.Type? {
set {
guard newValue != nil else {
serviceNames[name] = nil
Expand Down Expand Up @@ -63,11 +76,19 @@ extension ServiceValues {
}
}

#if canImport(SwiftUI)
import SwiftUI
extension Application: ObservableObject {}

struct AppEnvironmentKey: EnvironmentKey {
static var defaultValue = Application.shared
}

extension EnvironmentValues {
public var serviceValues: ServiceValues {
return ServiceValues.shared
public var application: Application {
get {
return self[AppEnvironmentKey.self]
}
set {
self[AppEnvironmentKey.self] = newValue
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation
/// 常用错误定义
public enum DFError: Error {
public enum CommonError: Error {
/// 业务错误
case biz(code: Int, msg: String)
/// 未实现
Expand Down
1 change: 1 addition & 0 deletions Sources/DFService/contract/DFApiCall.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
public class ApiCallConext {
let method: String
let param: Codable
public var options = [String: Any]()

public init(method: String, param: Codable) {
self.method = method
Expand Down
26 changes: 0 additions & 26 deletions Sources/DFService/contract/DFApiKey.swift

This file was deleted.

35 changes: 1 addition & 34 deletions Sources/DFService/contract/DFApplication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,6 @@ public protocol DFApplication: AnyObject {
var providerType: [ServiceProvider.Type] { get }
/// 已注册的服务提供者
var loadProviders: [ServiceProvider] { get set }
var rootView: AnyView { get set }
var serviceValues: ServiceValues { get }
}


public extension DFApplication {
var serviceValues: ServiceValues {
return .shared
}

@discardableResult
func provider<T: ServiceProvider>(_ serviceType: T.Type = T.self) -> T {

let loadProvider = loadProviders.first { loaded in
return loaded.name == serviceType.name
}
if let provider = loadProvider as? T {
return provider
}
let provider = serviceType.init(self)
loadProviders.append(provider)
provider.register()
self[LogService.self].debug("注册服务\(provider)")
return provider
}


func bootstrap(_ when: ServiceProvider.ProviderWhen) {
provider(BootstrapServiceProvider.self).bootstrap(when)
}
/// 重置启动,执行provider Shutdown
func reset(_ when: ServiceProvider.ProviderWhen) {
provider(BootstrapServiceProvider.self).bootstrap(when)
}

subscript<Service: DFServiceKey>(service: Service.Type, tag: String) -> Service.Value { get set }
}
32 changes: 32 additions & 0 deletions Sources/DFService/contract/DFHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
public protocol DFHandler {
associatedtype Input
associatedtype Output = Void

func handleSync(_ input: Input) throws -> Output
func handle(_ input: Input) async throws-> Output
}

public extension DFHandler {
func handle(_ input: Input) async throws -> Output {
return try self.handleSync(input)
}
}


public struct AnyHandler<Input,Output>: DFHandler {
public func handleSync(_ input: Input) throws -> Output {
return try _handlerSync(input)
}
public func handle(_ input: Input) async throws -> Output {
return try await _handler(input)
}

private let _handlerSync:(Input) throws -> Output
private let _handler:(Input) async throws -> Output
public init<T: DFHandler>(_ handler: T) where T.Input == Input, T.Output == Output {
self._handler = handler.handle(_:)
self._handlerSync = handler.handleSync(_:)
}
}


5 changes: 5 additions & 0 deletions Sources/DFService/contract/DFServiceKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import SwiftUI
public protocol DFServiceKey {
associatedtype Value
static var defaultValue: Self.Value { get }
}
4 changes: 2 additions & 2 deletions Sources/DFService/core/ServiceName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ extension ServiceName: DFApiCall {
@discardableResult
public func callAsFunction(_ context: ApiCallConext) async throws -> Any {

guard let value = ServiceValues.shared.findBy(self) else {
throw DFError.unImplemented()
guard let value = Application.shared.findBy(self) else {
throw CommonError.unImplemented()
}
return try await value.callAsFunction(context)
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/DFService/core/ServiceProvider.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
/// 应用内服务提供者
/// 在应用不同时机启动服务
open class ServiceProvider {
public let app: DFApplication
public let app: Application
/// 服务是否启动
public internal(set) var isBooted: Bool = false
public required init(_ app: DFApplication) {
public required init(_ app: Application) {
self.app = app
}
/// 注册服务
open func register() {}
/// 模拟异步启动逻辑
open func performAsyncStartup() async {
open func performAsyncStartup() async throws {
// 重写此方法以实现实际的异步启动逻辑
// try? await Task.sleep(nanoseconds: 1_000_000_000)// 模拟1秒的异步启动
// try await Task.sleep(nanoseconds: 1_000_000_000)// 模拟1秒的异步启动
}

/// 模拟异步关闭逻辑
open func performAsyncShutdown() async {
open func performAsyncShutdown() async throws {
// 重写此方法以实现实际的异步关闭逻辑
// try await Task.sleep(nanoseconds: 1_000_000_000) // 模拟1秒的异步关闭
}
open var when: ProviderWhen {
return .root
return .splash
}

var name: String {
Expand Down Expand Up @@ -58,8 +58,8 @@ extension ServiceProvider {
public static let eager = ProviderWhen(rawValue: 0)
/// 窗口创建后启动
public static let window = ProviderWhen(rawValue: 4)
/// 主窗口后启动
public static let root = ProviderWhen(rawValue: 8)
/// 主窗口创建的第一个页面
public static let splash = ProviderWhen(rawValue: 8)

public static func + (lhs: ProviderWhen, rhs: Int) -> ProviderWhen {
return ProviderWhen(rawValue: lhs.rawValue + rhs)
Expand Down
6 changes: 3 additions & 3 deletions Sources/DFService/extension/app.bundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ extension Space where Base == Bundle {
name = namespace.replacingOccurrences(of: " ", with: "_") + "." + name
}
guard name.components(separatedBy: ".").count > 1 else {
throw DFError.notFound("module")
throw CommonError.notFound("module")
}
guard let loadedClass = base.classNamed(name) else { throw DFError.notFound(type) }
guard let loadedClass = base.classNamed(name) else { throw CommonError.notFound(type) }
guard let castedClass = loadedClass as? T.Type else {
throw DFError.convert(from: String(describing: loadedClass), to: name)
throw CommonError.convert(from: String(describing: loadedClass), to: name)
}

return castedClass
Expand Down
27 changes: 2 additions & 25 deletions Sources/DFService/service/AppService.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,3 @@
public struct AppService: DFApiService {
public static var defaultValue: Value {
return Value.shared
}
}

extension AppService {
open class Value: DFApplication, ObservableObject {

internal static var shared = Value()
public init() {}
public var providerType: [ServiceProvider.Type] {
do {
let provider = try Bundle.main.app.loadClass(ofType: ServiceProvider.self, named: "AppServiceProvider")
return [provider]
} catch {
return []
}
}

public var loadProviders: [ServiceProvider] = []

@Published
public var rootView: AnyView = AnyView(RouterView())
}
public struct AppService: DFServiceKey {
public static var defaultValue = Application.shared
}
2 changes: 1 addition & 1 deletion Sources/DFService/service/LogService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public extension DFLogHandle {
}


public struct LogService: DFApiService {
public struct LogService: DFServiceKey {
public static var defaultValue: DFLogHandle {
return MockApiServiceImpl()
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/DFService/service/RouteService.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public struct RouteService: DFApiService {
public struct RouteService: DFServiceKey {
public static var defaultValue: Router {
return Value.shared
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/DFService/service/RuntimeService.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public struct RuntimeService: DFApiService {
public struct RuntimeService: DFServiceKey {
public static var defaultValue: Value = Value()

public struct Value {}
Expand Down
3 changes: 2 additions & 1 deletion Sources/DFService/service/impl/MockApiServiceImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ struct MockApiServiceImpl {
}



extension MockApiServiceImpl: DFApiCall {
func callAsFunction(_ context: ApiCallConext) async throws -> Any {
ServiceValues[LogService.self].debug("api 未实现 \(context.method):\(context.param)")
Application.shared[LogService.self].debug("api 未实现 \(context.method):\(context.param)")
return ()
}
}
Loading

0 comments on commit b8d5e22

Please sign in to comment.