I want logout a user after 1 hour once they go offline if they come online withn that 1 hour it should stop - ios

I tried saving my time in UserDefaults and adding 1 hour after once they go offline. I tried this too:
if isNetworkAvailable {
print(isNetworkAvailable)
}
else {
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
self.logginout()
})
}
I'm checking my Reachibility through Reachibility pod I have written a network manager like this:
import UIKit
class NetworkManager: NSObject {
var reachability: Reachability!
// Create a singleton instance
static let sharedInstance: NetworkManager = { return NetworkManager() }()
override init() {
super.init()
// Initialise reachability
reachability = Reachability()!
// Register an observer for the network status
NotificationCenter.default.addObserver(
self,
selector: #selector(networkStatusChanged(_:)),
name: .reachabilityChanged,
object: reachability
)
do {
// Start the network status notifier
try reachability.startNotifier()
} catch {
print("Unable to start notifier")
}
}
#objc func networkStatusChanged(_ notification: Notification) {
// Do something globally here!
}
static func stopNotifier() -> Void {
do {
// Stop the network status notifier
try (NetworkManager.sharedInstance.reachability).startNotifier()
} catch {
print("Error stopping notifier")
}
}
// Network is reachable
static func isReachable(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection != .none {
completed(NetworkManager.sharedInstance)
}
}
// Network is unreachable
static func isUnreachable(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .none {
completed(NetworkManager.sharedInstance)
}
}
// Network is reachable via WWAN/Cellular
static func isReachableViaWWAN(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .cellular {
completed(NetworkManager.sharedInstance)
}
}
// Network is reachable via WiFi
static func isReachableViaWiFi(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .wifi {
completed(NetworkManager.sharedInstance)
}
}
}
And in delegate I'm checking it like this:
network.reachability.whenUnreachable = { unreach in
isNetworkAvailable = false
let banner = NotificationBanner(title: "Your offline", subtitle: "Please Connect to internet", style: .danger)
banner.onSwipeUp = {
banner.dismiss()
}
print(time)
banner.show()
}
Is there a way to achieve this? I have written this block inside didLaunchWithOptions.

Related

Connecting wifi without internet not recognised with NetworkReachabilityManager or Reachability

When trying to check internet connectivity I have a problem.
When using alamofire NetworkReachabilityManager on a wifi with no internet like so:
import Alamofire
class Connectivity {
class func isConnectedToInternet() ->Bool {
return NetworkReachabilityManager()!.isReachable
}
}
This is the implementation:
if Connectivity.isConnectedToInternet() {
print("Yes! internet is available.")
} else {
print("No! internet is not available.")
}
I am getting: "Yes! internet is available." when there is no active internet connection (checked with Safari).
Tried also this one with Reachability:
import Reachability
class ReachabilityManager: NSObject {
var reachability: Reachability!
static let sharedInstance: NetworkManager = { return NetworkManager() }()
override init() {
super.init()
reachability = Reachability()!
NotificationCenter.default.addObserver(
self,
selector: #selector(networkStatusChanged(_:)),
name: .reachabilityChanged,
object: reachability
)
do {
try reachability.startNotifier()
} catch {
print("Unable to start notifier")
}
}
#objc func networkStatusChanged(_ notification: Notification) {
// Do something globally here!
}
static func stopNotifier() -> Void {
do {
try (NetworkManager.sharedInstance.reachability).startNotifier()
} catch {
print("Error stopping notifier")
}
}
static func isReachable(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection != .none {
completed(NetworkManager.sharedInstance)
}
}
static func isUnreachable(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .none {
completed(NetworkManager.sharedInstance)
}
}
static func isReachableViaWWAN(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .cellular {
completed(NetworkManager.sharedInstance)
}
}
static func isReachableViaWiFi(completed: #escaping (NetworkManager) -> Void) {
if (NetworkManager.sharedInstance.reachability).connection == .wifi {
completed(NetworkManager.sharedInstance)
}
}
}
The implementation is:
NetworkManager.isReachable { networkManagerInstance in
print("Network is available")
}
NetworkManager.isUnreachable { networkManagerInstance in
print("Network is Unavailable")
}
What am I doing wrong?
How did you check connection? did you try to reach any host something like below.
do {
Network.reachability = try Reachability(hostname: "www.google.com")
do {
try Network.reachability?.start()
} catch let error as Network.Error {
print(error)
} catch {
print(error)
}
} catch {
print(error)
}

How can we use Alamofire NetworkReachabilityManager in a singleton?

How to solve this issue in swift. I have to check the network connection. If the internet is not connected to the device I have to show this offlineViewController. if it is connected then it shows Normal screen.
I am using this class to control network change -> Reachability.swift :
import Foundation
import SystemConfiguration
class Reachability {
var hostname: String?
var isRunning = false
var isReachableOnWWAN: Bool
var reachability: SCNetworkReachability?
var reachabilityFlags = SCNetworkReachabilityFlags()
let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue")
init?(hostname: String) throws {
guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else {
throw Network.Error.failedToCreateWith(hostname)
}
self.reachability = reachability
self.hostname = hostname
isReachableOnWWAN = true
}
init?() throws {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let reachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}}) else {
throw Network.Error.failedToInitializeWith(zeroAddress)
}
self.reachability = reachability
isReachableOnWWAN = true
}
var status: Network.Status {
return !isConnectedToNetwork ? .unreachable :
isReachableViaWiFi ? .wifi :
isRunningOnDevice ? .wwan : .unreachable
}
var isRunningOnDevice: Bool = {
#if (arch(i386) || arch(x86_64)) && os(iOS)
return false
#else
return true
#endif
}()
deinit { stop() }
}
extension Reachability {
func start() throws {
guard let reachability = reachability, !isRunning else { return }
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque()
guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop()
throw Network.Error.failedToSetCallout
}
guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop()
throw Network.Error.failedToSetDispatchQueue
}
reachabilitySerialQueue.async { self.flagsChanged() }
isRunning = true
}
func stop() {
defer { isRunning = false }
guard let reachability = reachability else { return }
SCNetworkReachabilitySetCallback(reachability, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
self.reachability = nil
}
var isConnectedToNetwork: Bool {
return isReachable &&
!isConnectionRequiredAndTransientConnection &&
!(isRunningOnDevice && isWWAN && !isReachableOnWWAN)
}
var isReachableViaWiFi: Bool {
return isReachable && isRunningOnDevice && !isWWAN
}
/// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection.
var flags: SCNetworkReachabilityFlags? {
guard let reachability = reachability else { return nil }
var flags = SCNetworkReachabilityFlags()
return withUnsafeMutablePointer(to: &flags) {
SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0))
} ? flags : nil
}
/// compares the current flags with the previous flags and if changed posts a flagsChanged notification
func flagsChanged() {
guard let flags = flags, flags != reachabilityFlags else { return }
reachabilityFlags = flags
NotificationCenter.default.post(name: .flagsChanged, object: self)
}
/// The specified node name or address can be reached via a transient connection, such as PPP.
var transientConnection: Bool { return flags?.contains(.transientConnection) == true }
/// The specified node name or address can be reached using the current network configuration.
var isReachable: Bool { return flags?.contains(.reachable) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set.
var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection.
var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established.
var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection.
var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true }
/// The specified node name or address is one that is associated with a network interface on the current system.
var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true }
/// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system.
var isDirect: Bool { return flags?.contains(.isDirect) == true }
/// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS.
var isWWAN: Bool { return flags?.contains(.isWWAN) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set
/// The specified node name or address can be reached via a transient connection, such as PPP.
var isConnectionRequiredAndTransientConnection: Bool {
return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true
}
}
func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
guard let info = info else { return }
DispatchQueue.main.async {
Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue().flagsChanged()
}
}
extension Notification.Name {
static let flagsChanged = Notification.Name("FlagsChanged")
}
struct Network {
static var reachability: Reachability?
enum Status: String, CustomStringConvertible {
case unreachable, wifi, wwan
var description: String { return rawValue }
}
enum Error: Swift.Error {
case failedToSetCallout
case failedToSetDispatchQueue
case failedToCreateWith(String)
case failedToInitializeWith(sockaddr_in)
}
}
And I add this code to AppDelegate.swift :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
do {
Network.reachability = try Reachability(hostname: "www.google.com")
do {
try Network.reachability?.start()
} catch let error as Network.Error {
print(error)
} catch {
print(error)
}
} catch {
print(error)
}
return true
}
And I add this code to viewDidLoad() in the class I want to control the network:
NotificationCenter.default.addObserver(self, selector: #selector(statusManager), name: .flagsChanged, object: Network.reachability)
You can make checks in this function when the network changes.
func statusManager(_ notification: NSNotification) {
guard let status = Network.reachability?.status else { return }
if status == .wifi || status == .wwan {
offlineViewController.dismiss(animated: true, completion: nil)
}
print("Status:", status)
print("HostName:", Network.reachability?.hostname ?? "nil")
print("Reachable:", Network.reachability?.isReachable ?? "nil")
print("Wifi:", Network.reachability?.isReachableViaWiFi ?? "nil")
}
import Alamofire
struct Connectivity {
static let sharedInstance = NetworkReachabilityManager()!
static var isConnectedToInternet:Bool {
return self.sharedInstance.isReachable
}
}
Usage :
if Connectivity.isConnectedToInternet {
return true
} else {
self.setErrorMessage(message: "No internet connection", view: view)
return false
}
NetworkManager Class
class NetworkManager {
//shared instance
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
let offlineViewController = OfflineViewController()
let currentViewController: UIViewController?
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
offlineViewController.dismiss(animated: false, completion: nil)
currentViewController.present(offlineViewController, animated: true, completion: nil)
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
offlineViewController.dismiss(animated: true, completion: nil)
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
offlineViewController.dismiss(animated: true, completion: nil)
print("The network is reachable over the WWAN connection")
}
}
// start listening
reachabilityManager?.startListening()
}
}
Start Network Reachability Observer
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// add network reachability observer on app start
NetworkManager.shared.startNetworkReachabilityObserver()
return true
}
}
On each ViewController need to detect network
override func viewDidLoad() {
super.viewDidLoad()
NetworkManager.shared.currentViewController = self
}
Here I use Alamofire version 5.2
NetworkReachabilityManager handler
import Alamofire
class NetworkReachability{
let sceneDelegate: SceneDelegate = {
let scene = UIApplication.shared.connectedScenes.first
let sd = scene?.delegate as? SceneDelegate
return sd ?? SceneDelegate()
}()
var manager:NetworkReachabilityManager?
init(
manager:NetworkReachabilityManager? = NetworkReachabilityManager()
) {
self.manager = manager
self.managerHandler()
}
private func managerHandler(){
self.manager?.startListening(onUpdatePerforming: { (status) in
switch status{
case .unknown:
self.sceneDelegate.showOfflineViewController()
case .notReachable:
print("Not Reachable")
self.sceneDelegate.showOfflineViewController()
case .reachable(.cellular),.reachable(.ethernetOrWiFi):
print("Reachable")
self.sceneDelegate.hideOfflineViewController()
}
})
}
}
SceneDelegate
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var offlineWindow:UIWindow?
private var networkReachability:NetworkReachability?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
self.networkReachability = NetworkReachability()
}
}
extension SceneDelegate{
func showOfflineViewController(){
guard let offlineWindow = window?.windowScene else { return }
let offlineViewController = OfflineViewController
self.offlineWindow = UIWindow(windowScene: offlineWindow)
self.offlineWindow?.rootViewController = offlineViewController
self.offlineWindow?.makeKeyAndVisible()
}
func hideOfflineViewController(){
UIView.animate(withDuration: 0.3) {
self.offlineWindow?.alpha = 0
} completion: { (_) in
self.offlineWindow?.isHidden = true
self.offlineWindow = nil
}
}
}

How to use NEDNSProxyProvider in iOS 11

On the networking side, DNS Proxy is one of the biggest features of iOS 11. But they haven't provided much documentation or samples regarding it. There's a talk on it as well where they have just given a description of what is possible with DNS Proxy.
I want to create a working sample of it but didn't get success till now. So I have created a Network Extension with DNS Proxy entitlements and added a DNS Proxy Provider. Here's the code:
class DNSProxyProvider: NEDNSProxyProvider {
let defaults = UserDefaults(suiteName: "group.com.securly.dnsProxy")
override init() {
NSLog("QNEDNSProxy.Provider: init")
super.init()
// +++ might want to set up KVO on `systemDNSSettings`
}
override func startProxy(options:[String: Any]? = nil, completionHandler: #escaping (Error?) -> Void) {
NSLog("QNEDNSProxy.Provider: start")
// self.defaults?.set("DidStart", forKey: "DidStart")
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: #escaping () -> Void) {
NSLog("QNEDNSProxy.Provider: stop")
completionHandler()
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
NSLog("QNEDNSProxy.Provider: new flow (denied)")
// self.defaults?.set("DidHandleNewFlow", forKey: "DidHandleNewFlow")
return true
}
}
Then in AppDelegate, I declare a NEDNSProxyManager and use it as:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let manager = NEDNSProxyManager.shared()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.enable()
return true
}
private func enable() {
self.update {
self.manager.localizedDescription = "DNSProxySample"
let proto = NEDNSProxyProviderProtocol()
// proto.providerConfiguration = +++
proto.providerBundleIdentifier = "com.securly.dnsProxy"
self.manager.providerProtocol = proto
self.manager.isEnabled = true
}
}
private func disable() {
self.update {
self.manager.isEnabled = false
}
}
private func update(_ body: #escaping () -> Void) {
self.manager.loadFromPreferences { (error) in
guard error == nil else {
NSLog("DNSProxySample.App: load error")
return
}
body()
self.manager.saveToPreferences { (error) in
guard error == nil else {
NSLog("DNSProxySample.App: save error")
return
}
NSLog("DNSProxySample.App: saved")
}
}
}
}
Questions/Issues:
Why isn't startProxy or handleNewFlow called? Is there anything wrong in the setup?
How do I mention custom DNS address?
I managed to trigger startProxy and handleFlow on DNSProxyProvider by system. My configurations are like this:
Entitlements on app target
Entitlements on DNSProxy Extension
Red line is something similar to: group.com.xzy.project_name
Info.plist file on Extension
AppDelegate
import UIKit
import NetworkExtension
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let manager = NEDNSProxyManager.shared()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.enable()
return true
}
private func enable() {
self.update {
self.manager.localizedDescription = "DNS"
let proto = NEDNSProxyProviderProtocol()
proto.providerBundleIdentifier = "EXTENSION_BUNDLE_IDENTIFIER_WHICH_HAS_DNS_PROXY"
self.manager.providerProtocol = proto
self.manager.isEnabled = true
}
}
private func disable() {
self.update {
self.manager.isEnabled = false
}
}
private func update(_ body: #escaping () -> Void) {
self.manager.loadFromPreferences { (error) in
guard error == nil else {
NSLog("DNS Test App: load error")
return
}
body()
self.manager.saveToPreferences { (error) in
guard error == nil else {
NSLog("DNS Test App: save error")
return
}
NSLog("DNS Test App: saved")
}
}
}
}
DO NOT FORGET TO CHANGE BUNDLE IDENTIFIER at here proto.providerBundleIdentifier = "EXTENSION_BUNDLE_IDENTIFIER_WHICH_HAS_DNS_PROXY"
DNSProxyProvider
import NetworkExtension
class DNSProxyProvider: NEDNSProxyProvider {
override init() {
NSLog("DNSProxyProvider: init")
super.init()
}
override func startProxy(options:[String: Any]? = nil, completionHandler: #escaping (Error?) -> Void) {
NSLog("DNSProxyProvider: startProxy")
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: #escaping () -> Void) {
NSLog("DNSProxyProvider: stopProxy")
completionHandler()
}
override func sleep(completionHandler: #escaping () -> Void) {
NSLog("DNSProxyProvider: sleep")
completionHandler()
}
override func wake() {
NSLog("DNSProxyProvider: wake")
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
NSLog("DNSProxyProvider: handleFlow")
if let tcpFlow = flow as? NEAppProxyTCPFlow {
let remoteHost = (tcpFlow.remoteEndpoint as! NWHostEndpoint).hostname
let remotePort = (tcpFlow.remoteEndpoint as! NWHostEndpoint).port
NSLog("DNSProxyProvider TCP HOST : \(remoteHost)")
NSLog("DNSProxyProvider TCP PORT : \(remotePort)")
} else if let udpFlow = flow as? NEAppProxyUDPFlow {
let localHost = (udpFlow.localEndpoint as! NWHostEndpoint).hostname
let localPort = (udpFlow.localEndpoint as! NWHostEndpoint).port
NSLog("DNSProxyProvider UDP HOST : \(localHost)")
NSLog("DNSProxyProvider UDP PORT : \(localPort)")
}
return true
}
}
As a last step run the app on a real iOS Device.
If you want to display extension logs open Console.app from your Mac.
To debug the extension: Your main app should be selected from run menu. Select Attach to Process by PID or Name... from Xcode's Debug menu and then type your extension's name, press Attach button. After you see the Waiting to attach to EXTENSION_NAME on XYZ's iPhone. Run your app target on a iOS device.

xcode 8.3 error with generics

protocol PubSubEvent {
associatedtype EventResult
static func eventName() -> String
func event() -> EventResult
func send()
}
class BGEventBus: EventBus {
static let sharedInstance = BGEventBus()
init() {
super.init(queue: OperationQueue())
}
}
class BGEventBusEvent: PubSubEvent {
typealias EventResult = BGEventBusEvent
class func eventName() -> String {
return String(describing: self)
}
func send() {
BGEventBus.sharedInstance.send(event: self)
}
func event() -> BGEventBusEvent.EventResult {
return self
}
}
class BGDidLoginEvent: BGEventBusEvent {
typealias EventResult = BGDidLoginEvent
var password: String?
var facebookToken: String?
init(password: String? = nil, facebookToken: String? = nil) {
self.password = password
self.facebookToken = facebookToken
}
}
class EventBus {
var queue: OperationQueue
init(queue: OperationQueue) {
self.queue = queue
}
func send(event: AnyObject) {
}
func handleEvent<T: PubSubEvent>(target:EventBusObservable, handleBlock: ((T.EventResult) -> Void)!) where T.EventResult == T {
}
}
class EventBusObserver {
var objectProtocol: NSObjectProtocol?
func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: #escaping (Notification) -> Swift.Void) {
self.objectProtocol = NotificationCenter.default.addObserver(forName: name, object: obj, queue: queue, using: block)
}
deinit {
if let obj = self.objectProtocol {
NotificationCenter.default.removeObserver(obj)
}
self.objectProtocol = nil
print("deinit observer!")
}
}
protocol EventBusObservable {
func handleBGEvent<T: PubSubEvent>(handleBlock: ((T.EventResult) -> Void)!) where T.EventResult == T
}
extension EventBusObservable {
func handleBGEvent<T>(handleBlock: ((T) -> Void)!) where T : PubSubEvent, T.EventResult == T {
BGEventBus.sharedInstance.handleEvent(target: self, handleBlock:handleBlock)
}
}
class sample: EventBusObservable {
func test() {
self.handleBGEvent { (event: BGDidLoginEvent) in
}
}
}
Hello guys I updated the Xcode to 8.3 and now I'm getting some errors like this:
Cannot convert value of type '(BGDidLoginEvent) -> ()' to expected argument type '((_) -> Void)!''
can anybody help me?
here the sample file https://drive.google.com/open?id=0B1zPtsTG7crPQncxYnEyWTBpSXM
I think you have to write the generic requirement exactly the same way every time. So, in EventBus:
class EventBus {
// ...
func handleEvent<T>(target:EventBusObservable, handleBlock: ((T) -> Void)!) where T : PubSubEvent, T.EventResult == T {
}
}
In EventBusObservable:
protocol EventBusObservable {
func handleBGEvent<T>(handleBlock: ((T) -> Void)!) where T : PubSubEvent, T.EventResult == T
}
In the EventBusObservable extension:
extension EventBusObservable {
func handleBGEvent<T>(handleBlock: ((T) -> Void)!) where T : PubSubEvent, T.EventResult == T {
BGEventBus.sharedInstance.handleEvent(target: self, handleBlock: handleBlock)
}
}
That compiles. Finally we are left with your class sample. This one wasn't so easy; I found I had to declare event as a BGEventBusEvent:
class sample: EventBusObservable {
func test() {
self.handleBGEvent {
(event:BGEventBusEvent) in
}
}
}

How to get notifications for Network change(Connect,Disconnect,Change)

In my app I have to alert whenever a network change happens for example when a app is connected or disconnected or changed(wifi to data) network.
But finding it by reaching a url seems expensive.
Is there any public api available in iOS to do this.
I followed this tutorial
https://www.youtube.com/watch?v=wDZmz9IsB-8
credit --> Vasil Nunev
Download this class and import to my project --> Reachability.swift
https://github.com/ashleymills/Reachability.swift
(Reachability.swift) --> Unzip -->Sources/Reachability.swift
This is my view controller
import UIKit
class ViewController: UIViewController {
let reachability = Reachability()!
override func viewDidLoad() {
super.viewDidLoad()
reachability.whenReachable = { _ in
DispatchQueue.main.async {
self.view.backgroundColor = UIColor.green
}
}
reachability.whenUnreachable = { _ in
DispatchQueue.main.async {
self.view.backgroundColor = UIColor.red
}
}
NotificationCenter.default.addObserver(self, selector: #selector(internetChanged), name: Notification.Name.reachabilityChanged , object: reachability)
do{
try reachability.startNotifier()
} catch {
print("Could not strat notifier")
}
}
#objc func internetChanged(note:Notification) {
let reachability = note.object as! Reachability
if reachability.isReachable{
if reachability.isReachableViaWiFi{
self.view.backgroundColor = UIColor.green
}
else{
DispatchQueue.main.async {
self.view.backgroundColor = UIColor.orange
}
}
} else{
DispatchQueue.main.async {
self.view.backgroundColor = UIColor.red
}
}
}
}
Look at this official Apple documentation
Using Reachability you can recognize the type of your connection.
There is also a complete example on how detect the changes and the documentation is updated now for ARC.
I hope this can help you
Possible help:
Reachability
Event notification for network activity
If you're using Alamofire in your application, you can use it's NetworkReachabilityManager.swift class to listen for network's connectivity.
This is the piece of code.
#discardableResult
open func startListening(onQueue queue: DispatchQueue = .main,
onUpdatePerforming listener: #escaping Listener) -> Bool {
stopListening()
$mutableState.write { state in
state.listenerQueue = queue
state.listener = listener
}
var context = SCNetworkReachabilityContext(version: 0,
info: Unmanaged.passUnretained(self).toOpaque(),
retain: nil,
release: nil,
copyDescription: nil)
let callback: SCNetworkReachabilityCallBack = { _, flags, info in
guard let info = info else { return }
let instance = Unmanaged<NetworkReachabilityManager>.fromOpaque(info).takeUnretainedValue()
instance.notifyListener(flags)
}
let queueAdded = SCNetworkReachabilitySetDispatchQueue(reachability, reachabilityQueue)
let callbackAdded = SCNetworkReachabilitySetCallback(reachability, callback, &context)
// Manually call listener to give initial state, since the framework may not.
if let currentFlags = flags {
reachabilityQueue.async {
self.notifyListener(currentFlags)
}
}
return callbackAdded && queueAdded
}
/// Stops listening for changes in network reachability status.
open func stopListening() {
SCNetworkReachabilitySetCallback(reachability, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
$mutableState.write { state in
state.listener = nil
state.listenerQueue = nil
state.previousStatus = nil
}
}
You can also use Apple's SCNetworkReachbility class instead.

Resources