Skip to content
This repository has been archived by the owner on Mar 10, 2022. It is now read-only.

Commit

Permalink
Merge pull request #4 from nodes-ios/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
anho authored Oct 5, 2018
2 parents fe5c72e + cb70216 commit 72370d4
Show file tree
Hide file tree
Showing 29 changed files with 556 additions and 127 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018 Nodes Agency - iOS

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
71 changes: 27 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[![Carthage Compatible](https://img.shields.io/badge/carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![Plaforms](https://img.shields.io/badge/platforms-iOS%20-lightgrey.svg)
![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nodes-ios/Reachability-UI/blob/master/LICENSE)
### Intro

Demo Project + Framework showcasing the integration of the ReachabilityUI framework in a Nodes like VIPER architecture.
Expand All @@ -25,43 +24,31 @@ github "nodes-ios/Reachability-UI"

#### Initialise the ReachabilityUI dependencies

In your Dependencies struct, or wherever you initialise your dependencies, conform to the ReachabilityUI protocols `HasReachabilityUIRepository` and `HasReachabilityRepository` as follows:
Conform to `HasReachabilityListenerRepository` and create a `ReachabilityUIManager` instance:

```
struct Dependencies {
public static let shared = Dependencies()
public var reachabilityRepository: ReachabilityRepository
public var reachabilityUIEmbedableRepository: ReachabilityUIEmbedableRepository
public var reachabilityUIControlRepository: ReachabilityUIControlRepository
init() {
// create an instance of ReachabilityUIManager, this will later be used to get notified of the connectivity change.
// Using this you will be able to adjust your layout, in such a way, that it won't overlap the content of your
// that it won't overlap the content of your application.
let reachabilityUIManager = ReachabilityUIManager()
reachabilityUIEmbedableRepository = reachabilityUIManager
reachabilityUIControlRepository = reachabilityUIManager
// create an instance of ReachabilityManager, and call the setup function with your ReachabilityUIManager.
// This will allow the ReachabilityUIManager to get notified about connectivity changes
reachabilityRepository = ReachabilityManager()
reachabilityRepository.setup(reachabilityUIManager)
}
import UIKit
import ReachabilityUI
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
public var reachabilityListenerFactoryProtocol: ReachabilityListenerFactoryProtocol
extension Dependencies: HasReachabilityUIRepository, HasReachabilityRepository {}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
reachabilityListenerFactoryProtocol = ReachabilityUIManager()
return true
}
}
extension AppDelegate: HasReachabilityListenerRepository {}
```

#### Initialise the ReachabilityUI banner

To be able to get the Reachability banner on top of your views, in your `AppDelegate.swift` you will need to add the following code snippet:

```
import ReachabilityUI
private var reachabilityCoordinator: ReachabilityCoordinator!
private func addReachability() {
// create a ReachabilityConfiguration instance
let configuration = ReachabilityConfiguration(noConnectionTitle: "No Connection",
Expand All @@ -73,33 +60,29 @@ private func addReachability() {
height: 30,
font: UIFont.systemFont(ofSize: 12),
textAlignment: .center)
// create the ReachabilityCoordinator and pass it along the previously created ReachabilityConfiguration together with the ReachabilityUIEmbedableRepository
// create the ReachabilityCoordinator and pass it along the previously
// created ReachabilityConfiguration together with the ReachabilityUIEmbedableRepository
let coordinator = ReachabilityCoordinator(window: window,
reachabilityUIEmbedableRepository: dependencies.reachabilityUIEmbedableRepository,
with: configuration)
reachabilityListenerFactoryProtocol: dependencies.reachabilityListenerFactoryProtocol, with: configuration)
reachabilityCoordinator = coordinator
coordinator.start()
}
```

#### Subscribe to ReachabilityUI notification in order to get notified about the connectivity change and adjust your layout.
#### Subscribe to ReachabilityUI callback in order to get notified about the connectivity change and adjust your layout.

```
private var listener: ReachabilityListenerProtocol!
func subscribe() {
// create a ReachabilityListener and register it by calling your previously
// created ReachabilityUIEmbedableRepository's addListener function
// this function takes the listener and a listener id
let listener: ReachabilityListener = { [weak self] isConnected in
self?.output?.present(World.ReachabilityListener.Response(isConnected: isConnected))
let listener = reachabilityListenerFactoryProtocol.makeListener()
self.listener = listener
listener.listen { [weak self] (isConnected) in
self?.output?.present(World.ReachabilityListener.Response(isConnected: isConnected))
}
reachabilityUIEmbedableRepository.addListener(listener: listener, for: "\(self)")
}
// in your deinit, remove the reference to the listener
deinit {
reachabilityUIEmbedableRepository.removeListener(for: "\(self)")
}
```

## 👥 Credits
Expand All @@ -108,4 +91,4 @@ Made with ❤️ at [Nodes](http://nodesagency.com).
Reachability logic is as presented by Marco Santarossa on https://medium.com/@marcosantadev/network-reachability-with-swift-576ca5070e4b

## 📄 License
**Reachability-UI** is available under the MIT license. See the [LICENSE](https://github.com/nodes-ios/Serpent/blob/master/LICENSE) file for more info.
**Reachability-UI** is available under the MIT license. See the [LICENSE](https://github.com/nodes-ios/Reachability-UI/blob/master/LICENSE) file for more info.
Binary file removed ReachabilityUI/ReachabilityUI.framework.zip
Binary file not shown.
12 changes: 12 additions & 0 deletions ReachabilityUI/ReachabilityUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
42726B0B21665E4B00863414 /* ReachabilityProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42726B0221665E4B00863414 /* ReachabilityProtocols.swift */; };
42726B0C21665E4B00863414 /* ReachabilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42726B0321665E4B00863414 /* ReachabilityViewController.swift */; };
42726B0D21665E4B00863414 /* ReachabilityInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42726B0421665E4B00863414 /* ReachabilityInteractor.swift */; };
42726B102167710900863414 /* ReachabilityListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42726B0F2167710900863414 /* ReachabilityListener.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -32,6 +33,7 @@
42726B0221665E4B00863414 /* ReachabilityProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReachabilityProtocols.swift; sourceTree = "<group>"; };
42726B0321665E4B00863414 /* ReachabilityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReachabilityViewController.swift; sourceTree = "<group>"; };
42726B0421665E4B00863414 /* ReachabilityInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReachabilityInteractor.swift; sourceTree = "<group>"; };
42726B0F2167710900863414 /* ReachabilityListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReachabilityListener.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -64,6 +66,7 @@
42726AC921665DCD00863414 /* ReachabilityUI */ = {
isa = PBXGroup;
children = (
42726B0E2167704700863414 /* Model */,
42726AFD21665E4B00863414 /* Reachability */,
42726AFA21665E4B00863414 /* Shared */,
42726ACA21665DCD00863414 /* ReachabilityUI.h */,
Expand Down Expand Up @@ -95,6 +98,14 @@
path = Reachability;
sourceTree = "<group>";
};
42726B0E2167704700863414 /* Model */ = {
isa = PBXGroup;
children = (
42726B0F2167710900863414 /* ReachabilityListener.swift */,
);
path = Model;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -181,6 +192,7 @@
42726B0621665E4B00863414 /* RechabilityUIRepository.swift in Sources */,
42726B0B21665E4B00863414 /* ReachabilityProtocols.swift in Sources */,
42726B0521665E4B00863414 /* ReachabilityRepository.swift in Sources */,
42726B102167710900863414 /* ReachabilityListener.swift in Sources */,
42726B0C21665E4B00863414 /* ReachabilityViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
32 changes: 32 additions & 0 deletions ReachabilityUI/ReachabilityUI/Model/ReachabilityListener.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// ReachabilityListener.swift
// ReachabilityUI
//
// Created by Andrei Hogea on 05/10/2018.
// Copyright © 2018 Nodes Aps. All rights reserved.
//

import Foundation

public protocol ReachabilityListenerProtocol {
func listen(_ closure: @escaping Listener)
}

public final class ReachabilityListener: ReachabilityListenerProtocol {

private let ReachabilityListenerRepository: ReachabilityListenerRepository
let id: Int

init(ReachabilityListenerRepository: ReachabilityListenerRepository, id: Int) {
self.ReachabilityListenerRepository = ReachabilityListenerRepository
self.id = id
}

public func listen(_ closure: @escaping Listener) {
ReachabilityListenerRepository.addListener(closure, id: id)
}

deinit {
ReachabilityListenerRepository.removeListener(for: id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ReachabilityCoordinator {
// MARK: - Properties
private let window: UIWindow

private var reachabilityUIEmbedableRepository: ReachabilityUIEmbedableRepository
private var reachabilityListenerFactoryProtocol: ReachabilityListenerFactoryProtocol
var hasNavigationBar: Bool
private var configuration: ReachabilityConfiguration
private var vc: ReachabilityViewController! //prevent ViewController from deallocating by holding a reference
Expand All @@ -27,18 +27,18 @@ public class ReachabilityCoordinator {
/// - dependencies
/// - height of the UIViewController. Default value is 30
///
public init(window: UIWindow, reachabilityUIEmbedableRepository: ReachabilityUIEmbedableRepository, hasNavigationBar: Bool = true, with configuration: ReachabilityConfiguration) {
public init(window: UIWindow, reachabilityListenerFactoryProtocol: ReachabilityListenerFactoryProtocol, hasNavigationBar: Bool = true, with configuration: ReachabilityConfiguration) {
self.window = window
self.hasNavigationBar = hasNavigationBar
self.reachabilityUIEmbedableRepository = reachabilityUIEmbedableRepository
self.reachabilityListenerFactoryProtocol = reachabilityListenerFactoryProtocol
self.configuration = configuration
}

/// Starts the ReachabilityCoordinator and by registering observers and adding the
/// ReachabilityViewController to the window
///
public func start() {
let interactor = ReachabilityInteractor(reachabilityUIEmbedableRepository: reachabilityUIEmbedableRepository)
let interactor = ReachabilityInteractor(reachabilityListenerFactoryProtocol: reachabilityListenerFactoryProtocol)
let presenter = ReachabilityPresenter(interactor: interactor,
coordinator: self)
let vc = ReachabilityViewController.instantiate(with: presenter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@ class ReachabilityInteractor {
// MARK: - Properties

weak var output: ReachabilityInteractorOutput?
private var reachabilityUIEmbedableRepository: ReachabilityUIEmbedableRepository
private var reachabilityListenerFactoryProtocol: ReachabilityListenerFactoryProtocol
private var listener: ReachabilityListenerProtocol!


// MARK: - Init

init(reachabilityUIEmbedableRepository: ReachabilityUIEmbedableRepository) {
self.reachabilityUIEmbedableRepository = reachabilityUIEmbedableRepository
init(reachabilityListenerFactoryProtocol: ReachabilityListenerFactoryProtocol) {
self.reachabilityListenerFactoryProtocol = reachabilityListenerFactoryProtocol
}

deinit {
reachabilityUIEmbedableRepository.removeListener(for: "\(ReachabilityInteractor.self)")
}
}

// MARK: - Business Logic -

// PRESENTER -> INTERACTOR
extension ReachabilityInteractor: ReachabilityInteractorInput {
func perform(_ request: Reachability.ReachabilityListener.Request) {
let listener: ReachabilityListener = { [weak self] isConnected in
let listener = reachabilityListenerFactoryProtocol.makeListener()
self.listener = listener
listener.listen { [weak self] isConnected in
self?.output?.present(Reachability.ReachabilityListener.Response(isConnected: isConnected))
}
reachabilityUIEmbedableRepository.addListener(listener: listener, for: "\(ReachabilityInteractor.self)")
}

}
22 changes: 10 additions & 12 deletions ReachabilityUI/ReachabilityUI/Shared/ReachabilityRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@
import Foundation
import SystemConfiguration

public protocol ReachabilityRepository: class {
func setup(_ reachabilityUIControlRepository: ReachabilityUIControlRepository)
protocol ReachabilityRepository: class {
func setup(_ reachabilityDelegate: ReachabilityDelegate)
}

public protocol HasReachabilityRepository {
protocol HasReachabilityRepository {
var reachabilityRepository: ReachabilityRepository { get set }
}

public final class ReachabilityManager: ReachabilityRepository {
final class ReachabilityManager: ReachabilityRepository {

public static let shared = ReachabilityManager()

private var reachabilityUIControlRepository: ReachabilityUIControlRepository?
private var reachabilityDelegate: ReachabilityDelegate?

private var isConnected = false {
didSet {
guard reachabilityUIControlRepository != nil else { return }
reachabilityUIControlRepository?.networkStatusChanged(isConnected)
guard reachabilityDelegate != nil else { return }
reachabilityDelegate?.networkStatusChanged(isConnected)
}
}

Expand All @@ -50,7 +50,7 @@ public final class ReachabilityManager: ReachabilityRepository {

// MARK: - Init

public init() {
init() {
start()
}

Expand All @@ -60,8 +60,8 @@ public final class ReachabilityManager: ReachabilityRepository {

// MARK: - Setup

public func setup(_ reachabilityUIControlRepository: ReachabilityUIControlRepository) {
self.reachabilityUIControlRepository = reachabilityUIControlRepository
func setup(_ reachabilityDelegate: ReachabilityDelegate) {
self.reachabilityDelegate = reachabilityDelegate
}

// MARK: - Reachability Logic
Expand All @@ -88,12 +88,10 @@ public final class ReachabilityManager: ReachabilityRepository {
// Registers the callback. `callbackClosure` is the closure where we manage the callback implementation
if !SCNetworkReachabilitySetCallback(reachability, callbackClosure, &context) {
// Not able to set the callback
print("lolololo2")
}
// Sets the dispatch queue which is `DispatchQueue.main` for this example. It can be also a background queue
if !SCNetworkReachabilitySetDispatchQueue(reachability, queue) {
// Not able to set the queue
print("lolololo")
}
// Runs the first time to set the current flags
queue.async {
Expand Down
Loading

0 comments on commit 72370d4

Please sign in to comment.