Navigation system in my app contains coordinator pattern. when my application starts for the first time, everything works well. But when the app recedes into the background and phone system terminate it and I'm trying to get back to it, app starts for the first time again. So I need to restore my app state if system terminate app in background.
My AppDelegate class
import UIKit
import Swinject
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let container = Container()
private var appCoordinator: AppCoordinator!
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
setupDependecies()
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
appCoordinator = AppCoordinator(window: window!, container: container)
appCoordinator.start()
window?.makeKeyAndVisible()
return true
}
func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool {
return true
}
func application(_ application: UIApplication, shouldRestoreSecureApplicationState coder: NSCoder) -> Bool {
return true
}
}
AppCoordinator class
import Foundation
import UIKit
import Swinject
enum AppChildCoordinator {
case serial
case topic
}
final class AppCoordinator: Coordinator {
private let window: UIWindow
let container: Container
private var childCoordinators = [AppChildCoordinator: Coordinator]()
private let navigationController: UINavigationController
private let plistService: PlistService
init(window: UIWindow, container: Container) {
self.window = window
self.container = container
navigationController = UINavigationController()
self.window.rootViewController = navigationController
plistService = container.resolve(PlistService.self)!
}
func start() {
let isActivated: Bool?
isActivated = plistService.readPlist(namePlist: "Preferences", key: Constans.isActivated) as! Bool?
if isActivated != nil && isActivated! {
showTopic()
} else {
showSerial()
}
}
private func showSerial() {
let serialCoordinator = SerialCoordinator(container: container, navigationController: navigationController)
childCoordinators[.serial] = serialCoordinator
serialCoordinator.delegate = self
serialCoordinator.start()
}
private func showTopic() {
let topicCoordinator = TopicCoordinator(container: container, navigationController: navigationController)
childCoordinators[.topic] = topicCoordinator
topicCoordinator.delegate = self
topicCoordinator.start()
}
}
extension AppCoordinator: SerialCoordinatorDeligate {
func serialCoordinatorDidFinish() {
childCoordinators[.serial] = nil
showTopic()
}
}
extension AppCoordinator: TopicCoordinatorDeligate {
func topicCoordinatorDidFinish() {
childCoordinators[.topic] = nil
}
}
I understand that when my app starts it run Serial or Topic coordinator without restore logic. For example if user go to Topic coordinator, then to Auth coordinator (child of Topic coordinator), then to Home coordinator (child of Auth coordinator), how can I restore Home coordinator after start terminated by system app?
Related
I currently have the problem that I don't know how to give native a screen in iOS a callback function and a string.
It is currently implemented as follows:
import UIKit
import Flutter
import PostidentSDK
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let kycChannel = FlutterMethodChannel(name: "kyc",
binaryMessenger: controller.binaryMessenger)
kycChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "startProcess" else {
result(FlutterMethodNotImplemented)
return
}
let mainVC = ViewController() // Your viewController
let navigationController = UINavigationController(rootViewController: mainVC)
self?.window.rootViewController = navigationController
self?.window.makeKeyAndVisible()
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
someFunction()
}
}
The Screen ViewController is then called and on this I want to have the string caseId & then execute the Flutter result there and close the screen.
I am creating a custom framework. I need a reference to the AppDelegate to perform operations e.g get window or some other delegates.
example code:
static var safeArea: UIEdgeInsets {
var padding: UIEdgeInsets = UIEdgeInsets.zero
if #available(iOS 11.0, *) {
if let b = appDel.window?.safeAreaInsets {
padding = b
}
}
return padding
}
The main issue I have is that I need the AppDelegate reference on multiple levels.
Any help regarding this should be appreciated.
Sample Source for comments below :). Create a sampleManager inside framework. Import the framework into appdelegate and set SampleManager.shared.delegate to self as weak reference.
public class SampleManager {
public static let shared = SampleManager()
public weak var delegate: UIApplicationDelegate?
func doWhateverYouWant() {
}
}
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private let dependencyManager = DependencyManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
SampleManager.shared.delegate = self
startAppCoordinator()
return true
}
}
I'm using Firebase Remote Config, I have some troubles to update values.
My values are updated only if I close and relaunch the app.
But never if my app enters in foreground.
The developer is activated, with no cache delay.
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
let _ = RCFirebaseValues.sharedInstance
}
}
My Firebase Remote Config class:
enum ValueKey: String {
case force_update
}
class RCFirebaseValues {
static let sharedInstance = RCFirebaseValues()
var loadingDoneCallback: (() -> ())?
var fetchComplete: Bool = false
private init() {
loadDefaultValues()
fetchCloudValues()
}
func loadDefaultValues() {
RemoteConfig.remoteConfig().setDefaults(fromPlist: "RemoteConfigDefaults")
}
func fetchCloudValues() {
#if DEBUG
let expirationDuration: TimeInterval = 0
RemoteConfig.remoteConfig().configSettings = RemoteConfigSettings(developerModeEnabled: true)
#else
let expirationDuration: TimeInterval = 3600
#endif
RemoteConfig.remoteConfig().fetch(withExpirationDuration: expirationDuration) {
[weak self] (status, error) in
guard error == nil else {
DLog(message:"Uh-oh. Got an error fetching remote values \(String(describing: error))")
return
}
RemoteConfig.remoteConfig().activateFetched()
self?.fetchComplete = true
self?.loadingDoneCallback?()
}
}
func bool(forKey key: ValueKey) -> Bool {
return RemoteConfig.remoteConfig()[key.rawValue].boolValue
}
func string(forKey key: ValueKey) -> String {
return RemoteConfig.remoteConfig()[key.rawValue].stringValue ?? ""
}
func double(forKey key: ValueKey) -> Double {
if let numberValue = RemoteConfig.remoteConfig()[key.rawValue].numberValue {
return numberValue.doubleValue
} else {
return 0.0
}
}
}
What's wrong?
EDIT after Mosbah's response:
class AppDelegate: UIResponder, UIApplicationDelegate {
var remoteConfig:RCFirebaseValues!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self. remoteConfig = RCFirebaseValues.sharedInstance
}
}
Your RCFirebaseValues scope is wrong, it will be nil as soon as you are out of application: didFinishLaunchingWithOptions: so you should keep a strong reference to your object (create a var on AppDelegate).
Hi I want to show a view controller only at the first use (i.e: the first time someone starts the app up and never again).
I think I have the right code but for some reason it's just not working. Does anyone know why?
AppDelegate.swift
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let userDefaults = UserDefaults.init()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
userDefaults.set(true, forKey: "isFirstTime")
userDefaults.set("RealmNotChosenOrSuggested", forKey: "RegionPreference")
userDefaults.set([], forKey: "PreferredRealms")
// Not using Storyboard instantiation code
window = UIWindow(frame:UIScreen.main.bounds) //canvas
window?.makeKeyAndVisible()
if (userDefaults.bool(forKey: "isFirstTime")){
userDefaults.set(false, forKey: "isFirstTime")
window?.rootViewController = StartupViewController()
} else{
window?.rootViewController = DashboardViewController()
}
return true
}
StartupViewController.swift
class StartupViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
DashboardViewController.swift
import UIKit
class DashboardViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
}
Because every time app opens this runs you overwrite the key isFirstTime in the first line
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// userDefaults.set(true, forKey: "isFirstTime") // firs line comment it
if !(userDefaults.bool(forKey: "isFirstTime")){
userDefaults.set(true, forKey: "isFirstTime")
userDefaults.set("RealmNotChosenOrSuggested", forKey: "RegionPreference")
userDefaults.set([], forKey: "PreferredRealms")
window?.rootViewController = StartupViewController()
} else{
window?.rootViewController = DashboardViewController()
}
I am new to IOS and swift. Does anyone know how to assign value to boolean appdelegate method? I want to set shouldAllowExtensionPointIdentifier in viewcontroller but i didn't find any solution. Thank you
//
// AppDelegate.swift
// TestKeyboard
//
// Created by Mol Monyneath on 11/1/17.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
public var Alow : Bool?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch
return true
}
func application(_ application: UIApplication, shouldAllowExtensionPointIdentifier extensionPointIdentifier: UIApplicationExtensionPointIdentifier) -> Bool {
print("\(extensionPointIdentifier.rawValue) allow = \(Alow)")
return Alow!
}
}
Here is Main view controller:
I couldn't block that app . please help
import UIKit
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet weak var normaltextView: UITextField!
#IBOutlet weak var txtView: UITextField!
var appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
normaltextView.delegate = self
txtView.delegate = self
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if textField.keyboardType == UIKeyboardType.numberPad{
// textField.inputView = nil
txtView.inputView = nil
appDelegate.Alow = false
txtView.reloadInputViews()
print("false")
}else{
print("should Press")
print("True")
// textField.inputView = nil
appDelegate.Alow = true
txtView.reloadInputViews()
normaltextView.reloadInputViews()
}
return true
}
}
thank