hugh-h
10/27/2017 - 9:12 PM

AppServices and AppServiceProvider

providing services through a single class, supported by a protocol with a default implemenation


// Usage:
//
// Normal:
// class MyClass : AppServicesProvider { ... }
// myClass.services?.dataProcessingService.doSomething()
//
// Override:
// let myservices = AppServices(...)
// AppServices.registerServices(services:myservices)
// class MyClass : AppServicesProvider { ... }
// myClass.services?.dataProcessingService.doSomething()
//
//

protocol AppServicesProvider {
    var services: AppServices? { get }
}

extension AppServicesProvider {
    var services: AppServices? {
        return AppServices.services()
    }
}


class AppServices {
    
    private static var registeredServices:AppServices?
    var dataProcessingDataService:AppDataService?
    var viewDataService:AppDataService?

    init(dataProcessingDataService:AppDataService?, viewDataService:AppDataService?) {
        self.dataProcessingDataService = dataProcessingDataService
        self.viewDataService = viewDataService
    }
    
    static func registerServices(services:AppServices) {
        registeredServices = services
    }
    
    static func services() -> AppServices? {
        if let services = registeredServices {
            return services
        }
        else {
            print("Loading default services")
            registeredServices = defaultServices()
            return registeredServices
        }
    }
    
    private static func defaultServices() -> AppServices {
        
        let appPersistentContainer = AppPersistentContainer()
        let appCoreDataService = AppCoreDataService(context: appPersistentContainer.container.newBackgroundContext())
        let viewCoreDataService = AppCoreDataService(context: appPersistentContainer.container.viewContext)
        
        let dataProcessingDataService = AppDataService(coreDataService:appCoreDataService)
        let viewDataService = AppDataService(coreDataService:viewCoreDataService)
        
        return AppServices(dataProcessingDataService:dataProcessingDataService, viewDataService: viewDataService)
    }
}