Home > Mobile >  Making Offline Mode work across all screens in iOS app
Making Offline Mode work across all screens in iOS app

Time:11-05

I am trying to setup a clean way of handling when a user goes offline, currently if a user is offline I am pushing a new screen to the top of the stack with a message to connect to the internet. This is working perfectly for the one screen it is setup on, but I want this code to work on any screen the user is on. I am trying to put this into the app delegate and have the code shared across all screens but it is not working. The end goal is if the user is on any screen in my app and loses connection, to show the offline view controller - currently this is only working on the home screen.

Also I do not want to use Alamo / Firebase or any other 3rd party to handle this if possible.

This is the home screen code and everything working as expected:

import UIKit

class ViewController: UIViewController, UIAlertViewDelegate {

    let reachability = try! Reachability()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // When network is unreachable, present offline view controller
        reachability.whenUnreachable = { _ in
            let vc = self.storyboard?.instantiateViewController(withIdentifier: "OfflineViewController")
            vc?.modalPresentationStyle = .fullScreen
            self.present(vc!, animated: true, completion: nil)
        }

        do {
            try reachability.startNotifier()
        } catch {
            print("Unable to start notifier")
        }
    } 
}

This is the code for the offline view controller - it is also working as expected

import UIKit

class OfflineViewController: UIViewController {
    
    let reachability = try! Reachability()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            try reachability.startNotifier()
        } catch {
            print("Unable to start notifier")
        }

    }
    
    
    @IBAction func tapTryAgain(_ sender: Any) {
        
        reachability.whenReachable = { reachability in
                self.dismiss(animated: true, completion: nil)
        }

        
    }
}

Now when I try to put all the code in the app delegate, it does not work -- This the part I need help with - note that I am commenting out the reachability code from home screen when I try this out

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    let reachability = try! Reachability()


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


        // Note nothing happens when user goes offline with this code
        reachability.whenUnreachable = { _ in
            print("Not reachable")
            
            let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            
            let offlineVC = storyboard.instantiateViewController(withIdentifier: "OfflineViewController")
            offlineVC.modalPresentationStyle = .fullScreen
            
            let appDelegate = UIApplication.shared.delegate
            appDelegate?.window??.addSubview(offlineVC.view)
            appDelegate?.window??.bringSubviewToFront(offlineVC.view)
        }

        do {
            try reachability.startNotifier()
        } catch {
            print("Unable to start notifier")
        }
        

        
        
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }


}

CodePudding user response:

I suppose the problem is that you are trying to use window from AppDelegate, but it will always be nil, since your are using SceneDelegate. Just move this code to SceneDelegate, everything will work as it should then.

  • Related