Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,48 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
.Trashes
*.swp
*~.nib
DerivedData/
build/

# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
Index

## Build generated
build/
DerivedData/

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/

## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
.build/
485 changes: 485 additions & 0 deletions PureExample/PureExample.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions PureExample/PureExample/Main/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// AppDelegate.swift
// PureExample
//
// Created by Łukasz Śliwiński on 19/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

let dependency: AppDependency

/// Called from the system (it's private: not accessible in the testing environment)
private override init() {
self.dependency = AppDependency.resolve()
super.init()
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}

// MARK: UISceneSession Lifecycle

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
33 changes: 33 additions & 0 deletions PureExample/PureExample/Main/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// SceneDelegate.swift
// PureExample
//
// Created by Łukasz Śliwiński on 19/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

private var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}

var window: UIWindow?

func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
guard let scene = (scene as? UIWindowScene) else { return }

self.window = UIWindow(windowScene: scene)
guard let window = self.window else { return }

let factory = appDelegate.dependency.listViewControllerFactory
window.rootViewController = factory.create()
window.makeKeyAndVisible()
}
}
103 changes: 103 additions & 0 deletions PureExample/PureExample/Models/AppDependency.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// AppDependency.swift
// PureExample
//
// Created by Łukasz Śliwiński on 20/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import UIKit
import UserNotifications
import Pure

struct AppDependency {
let networking: Networking
let remoteNotificationService: RemoteNotificationService
let listViewControllerFactory: ListViewController.Factory
}

extension AppDependency {

static func resolve() -> AppDependency {
let networking = Networking()
let remoteNotificationService = RemoteNotificationService(
notificationCenter: UNUserNotificationCenter.current()
)

return AppDependency(
networking: networking,
remoteNotificationService: remoteNotificationService,
listViewControllerFactory: ListViewController.Factory(
dependency: .init(
networking: networking,
notificationsService: remoteNotificationService,
factory: DetailViewController.Factory(
dependency: .init(
networking: networking,
imageCellConfigurator: ImageCell.Configurator()
)
)
)
)
)
}
}

// MARK: - Pure Factory Module -

// MARK: - ListViewController -

extension ListViewController: FactoryModule {
struct Dependency {
let networking: Networking
let notificationsService: RemoteNotificationService
let factory: DetailViewController.Factory
}
}

extension Factory where Module == ListViewController {

func create() -> ListViewController {
let module = ListViewController.loadFromStoryboard()
module.networking = dependency.networking
module.notificationsService = dependency.notificationsService
module.factory = dependency.factory
return module
}
}

// MARK: - DetailViewController -

extension DetailViewController: FactoryModule {
struct Dependency {
let networking: Networking
let imageCellConfigurator: ImageCell.Configurator
}

struct Payload {
let selectedItem: Item
}
}

extension Factory where Module == DetailViewController {

func create(payload: DetailViewController.Payload) -> DetailViewController {
let vc = DetailViewController.loadFromStoryboard()
vc.networking = dependency.networking
vc.imageCellConfigurator = dependency.imageCellConfigurator
vc.item = payload.selectedItem
return vc
}
}

// MARK: - ImageCell -

extension ImageCell: ConfiguratorModule {
struct Payload {
let image: UIImage
}

func configure(dependency: Void, payload: ImageCell.Payload) {
self.imageView.image = payload.image
}
}
13 changes: 13 additions & 0 deletions PureExample/PureExample/Models/Item.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Item.swift
// PureExample
//
// Created by Łukasz Śliwiński on 20/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import Foundation

struct Item {
let name: String
}
13 changes: 13 additions & 0 deletions PureExample/PureExample/Protocols/ImageDownloaderType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ImageDownloaderType.swift
// PureExample
//
// Created by Łukasz Śliwiński on 20/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import Foundation

protocol ImageDownloaderType {

}
31 changes: 31 additions & 0 deletions PureExample/PureExample/Protocols/StoryboardLoadable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// StoryboardLoadable.swift
// PureExample
//
// Created by Łukasz Śliwiński on 19/02/2020.
// Copyright © 2020 plum. All rights reserved.
//

import UIKit

protocol StoryboardLoadable: class {
static var storyboardName: String { get }
static var controllerId: String { get }
}

extension StoryboardLoadable where Self: UIViewController {

static var storyboardName: String {
return String(describing: Self.self)
}

static var controllerId: String {
return String(describing: Self.self)
}

static func loadFromStoryboard() -> Self {
let bundle = Bundle(for: Self.self)
let storyboard = UIStoryboard(name: Self.storyboardName, bundle: bundle)
return storyboard.instantiateViewController(withIdentifier: Self.controllerId) as! Self
}
}
Loading