Calling delegate function from AppDelegate not working - ios

I am trying to call delegate function in AppDelegate, but seems like it never get invoked.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,appdelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let navigationController = window?.rootViewController, let
viewController = navigationController.childViewControllers.first as? ViewController {
viewController.delegate = self
}
// Override point for customization after application launch.
return true
}
func callfromDelegte(indicator: UIActivityIndicatorView) {
indicator.stopAnimating()
}
ViewController-:
import UIKit
protocol appdelegate:class {
func callfromDelegte(indicator:UIActivityIndicatorView)
}
class ViewController: UIViewController {
#IBOutlet weak var indicator: UIActivityIndicatorView!
weak var delegate:appdelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
indicator.startAnimating()
indicator.hidesWhenStopped = true
}
#IBAction func rotateAction(_ sender: UIButton) {
if delegate != nil{
delegate?.callfromDelegte(indicator: indicator)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Delegate is always nil, it never goes inside function. What is that i don't
now about delegates yet? How does Google GIDSignInDelegate and its delegate functions get called inside AppDelegate from controller class? I know it might be very stupid question but I would still like to know.Thanks
Ok it worked as i have not embeded my controller with navigationController. So it was not going inside if let. It worked simply like this-:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// if let navigationController = window?.rootViewController, let
// viewController = navigationController.childViewControllers.first as? ViewController {
// viewController.delegate = self
// }
// Override point for customization after application launch.
let controller = window?.rootViewController as! ViewController
controller.delegate = self
return true
}

You cannot create the Viewcontroller object directly and set the delegate inside your app delegate. You need to access the Viewcontroller object first because it is the inside the rootViewController so you need to implement like this
if let navigationController = window?.rootViewController, let
viewController = navigationController.childViewControllers.first as? ViewController {
viewController.delegate = self
}

You can try to get AppDelegate instance from shared application. Hope it will help
This is Swift 3
#IBAction func rotateAction(_ sender: UIButton) {
let delegate = UIApplication.shared.delegate as? AppDelegate
delegate?.callfromDelegte(indicator: indicator)
}

Related

Framework ViewController View Not showing

I am trying to create a framework (Login VC) which contains a view controller. I have successfully imported the framework and presented the VC, but the view is not showing. I have a print function in the imported viewDidLoad and it is printing. What am I missing?
Framework VC:
public class LoginVC: UIViewController {
#IBOutlet weak var button: UIButton! {
didSet {
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
}
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func viewDidLoad() {
super.viewDidLoad()
print("View Loaded") // Firing
}
#objc func buttonPressed() {
print("hello")
}
}
Framework VC Xib:
This is view debugger when I present the framework VC
-- Update: This is how I am showing the VC ---
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let homeViewController = LoginVC()
homeViewController.view.backgroundColor = UIColor.white
window!.rootViewController = homeViewController
window!.makeKeyAndVisible()
return true
}
-- Update --
Since many comments relate to the app delegate, I first present a general ViewController which then will present my login framework VC.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let homeViewController = ViewController()
homeViewController.view.backgroundColor = UIColor.white
window!.rootViewController = homeViewController
window!.makeKeyAndVisible()
return true
}
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton! {
didSet {
button.addTarget(self, action: #selector(presentNext), for: .touchUpInside)
}
}
#objc func presentNext() {
let loginVC = LoginVC()
present(loginVC, animated: true, completion: nil)
}
}
Now, when I present the login framework, all I get is a black screen.
-- Update --
I can change the background color of the view in viewdidLoad, but the xib views are not shown. Why is this?..
Frameworks with xibs connected to viewController require explicit loading from the bundle.
Usually when we create a cocoaTouch UIViewController with xib, this is handled for us. However, when using frameworks, it is not handled.
To solve this, I add load the xib in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Frameworks require loading of the xib to connect xib to view controller
let bundle = Bundle(for: type(of: self))
bundle.loadNibNamed("viewControllerName", owner: self, options: nil)
}
You need to call your presentNext() after the ViewController has actually appeared -- not in viewDidLoad, and not even in viewWillAppear.
Like this:
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
presentNext()
}
#objc func presentNext() {
let loginVC = LoginVC()
present(loginVC, animated: true, completion: nil)
}
}
Here's the working test project:
https://github.com/drewster99/SO_LoginVC
Also, maybe double-check that your ViewController.xib has the IBOutlet actually attached for the button. It's actually got to be that. Everything else looks good.
Here's what I've got:
AppDelegate:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let homeViewController = ViewController()
homeViewController.view.backgroundColor = UIColor.white
window!.rootViewController = homeViewController
window!.makeKeyAndVisible()
return true
}
}
ViewController.swift:
import UIKit
import LoginFrameworkThing
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton! {
didSet {
button.addTarget(self, action: #selector(presentNext), for: .touchUpInside)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
#objc func presentNext() {
print("Presenting next...")
let loginVC = LoginVC()
present(loginVC, animated: true, completion: nil)
}
}
The button is connected in ViewController, and LoginVC (both .xib and .swift) exist in the framework.
I updated the sample project. Check the link.

Loading one instance of Google Admob throughout multiple ViewControllers

I am looking to load one instance of a Google Admob Banner View throughout multiple View Controllers (including, but not limited to a UITabBarController.)
My attempt is below. I'm using AppDelegate to set the adSize, adUnitID and testDevices. Then in each VC where I want a banner displayed, I set the rootViewController, frame, load request, and then addSubView.
This works, in the fact that the ads show up fine. However, the ads keep changing when I segue or dismiss VC! It appears that a new request is happening everytime VC's change. Which is precisely the result that must be avoided!
AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var adBannerViewFromAppDelegate = GADBannerView()
let loadRequest = GADRequest()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
adBannerViewFromAppDelegate.adSize = kGADAdSizeSmartBannerPortrait
adBannerViewFromAppDelegate.adUnitID = "12345"
loadRequest.testDevices = [kGADSimulatorID, myiPhone]
}
}
ViewController
(This has a button to SecondViewController via Push Segue)
import UIKit
import GoogleMobileAds
class ViewController: UIViewController {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addBannerToView()
}
func addBannerToView() {
appDelegate.adBannerViewFromAppDelegate.rootViewController = self
appDelegate.adBannerViewFromAppDelegate.load(appDelegate.loadRequest)
appDelegate.adBannerViewFromAppDelegate.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: appDelegate.adBannerViewFromAppDelegate.frame.height)
view.addSubview(appDelegate.adBannerViewFromAppDelegate)
}
}
SecondViewController
import UIKit
import GoogleMobileAds
class SecondViewController: UIViewController {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addBannerToView()
}
#IBAction func closeButtonPressed(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
func addBannerToView() {
appDelegate.adBannerViewFromAppDelegate.rootViewController = self
appDelegate.adBannerViewFromAppDelegate.load(appDelegate.loadRequest)
appDelegate.adBannerViewFromAppDelegate.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: appDelegate.adBannerViewFromAppDelegate.frame.height)
view.addSubview(appDelegate.adBannerViewFromAppDelegate)
}
}
How can I get one instance of the Banner created in the AppDelegate to display on multiple ViewControllers? Thanks.

Modal presentation of UITableViewController from UITabBarController

So as per title, I'm trying to present a UITableViewController from a UITabBarController. If you look at the video I've attached, on the third tab, it presents a view controller modally. Which is what I want to achieve.
https://vid.me/B0oy
I've been searching all day for a solution, and I yet I've tried them, but it doesn't work.
This is currently how I do it. I add this line of code in the view controller of my first tab.
self.tabBarController?.delegate = UIApplication.sharedApplication().delegate as? UITabBarControllerDelegate
And this is inside my AppDelegate.
class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegate {
var window: UIWindow?
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
if viewController is YourViewController {
if let newVC = tabBarController.storyboard?.instantiateViewControllerWithIdentifier("YourVCStoryboardIdentifier") {
tabBarController.presentViewController(newVC, animated: true, completion: nil)
return false
}
}
return true
}
func setStatusBarBackgroundColor(color: UIColor) {
guard let statusBar = UIApplication.sharedApplication().valueForKey("statusBarWindow")?.valueForKey("statusBar") as? UIView else {
return
}
statusBar.backgroundColor = color
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
setStatusBarBackgroundColor(UIColor.lightGrayColor())
return true
}

Swift: Setting rootViewController not working?

I'm trying to start a new Swift project. This is my first time trying to create the views programatically. However it doesn't even look like my controller is being loaded? All I see is the launch screen and then a black screen when I load it onto the simulator.
This is my AppDelegate:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSLog("zrrrzz") // <------------------------------ Prints properly
self.window?.rootViewController = self.rootViewController()
return true
}
private func rootViewController() -> UIViewController {
NSLog("zzz") // <---------------------------------- Does not print ????
return MapViewController.init()
}
}
MapViewController:
import UIKit
class MapViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var label = UILabel(frame: CGRectMake(0, 0, 200, 21))
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = "I am a test label"
self.view.backgroundColor = UIColor.whiteColor()
self.view.addSubview(label)
NSLog("heyyyy!!") //<------------------------------ Also doesn't print ??
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Am I missing a step? I don't see any warnings / errors when I start the simulator
In the line:
self.window?.rootViewController = self.rootViewController()
If the window property is nil, it will not execute your self.rootViewController() call. You can read more about calling methods with optional chaining in the documentation for details.
If you are trying to create your initial user interface in code, you will need to create a UIWindow instance and assign it to self.window. This is done for you automatically when using a Storyboard.
Disclaimer: I haven't written this code in a few versions of iOS, so this may not be exactly correct, but it will get you going in the right direction:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let applicationFrame = UIScreen.mainScreen().applicationFrame
let window = UIWindow(frame: applicationFrame)
window.rootViewController = self.rootViewController()
window.makeKeyAndVisible()
self.window = window
return true
}

Aassigning a value to a view controller from AppDelegate.swift

I try to assign a value to a view controller from AppDelegate.swift without success.
My controller is named DestinationsViewController, and its id in Main.storyboard is destinationsID. DestinationsController is embed in a Navigation Controller. The objet I want to change is named "label". This is the code:
if let destinationsViewController = storyBoard.instantiateViewControllerWithIdentifier("destinationsID") as? DestinationsViewController {
if let label = destinationsViewController.label{
label.text = "Super!"
}
else{
println("Not good 2")
}
}
else {
println("Not good 1")
}
Unfortunately, I get the message: "Not good 2". This is not good :-(
Thank you.
import UIKit
class DestinationsViewController: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Ok, here's how you can do it. However, if you change the structure of your storyboard then this may break.
First, in DestinationsViewController, you need to set a variable that will hold the text because we're setting the text before the view is rendered. Therefore, the label will not exist yet. When the view loads, it'll set the label.
class DestinationsViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var labelText = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label.text = labelText
}
Now, in the AppDelegate, we set the variable that will set the label when the view loads.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// assuming inital view is tabbar
let tabBarController = self.window?.rootViewController as UITabBarController
let tabBarRootViewControllers: Array = tabBarController.viewControllers!
// assuming first tab bar view is the NavigationController with the DestinationsViewController
let navView = tabBarRootViewControllers[0] as UINavigationController
let destinationsViewController = navView.viewControllers[0] as DestinationsViewController
destinationsViewController.labelText = "Super!"
return true
}
EDIT
After re-reading your last comment, I realized you want to set the label at some point after the app has already been running. You can just move the code in func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool to where you need it. Then you can also set the label directly, because the view has been loaded.
// assuming inital view is tabbar
let tabBarController = self.window?.rootViewController as UITabBarController
let tabBarRootViewControllers: Array = tabBarController.viewControllers!
// assuming first tab bar view is the NavigationController with the DestinationsViewController
let navView = tabBarRootViewControllers[0] as UINavigationController
let destinationsViewController = navView.viewControllers[0] as DestinationsViewController
if let label = destinationsViewController.label{
label.text = "Super DUper!"
}
else{
println("Not good 2")
}

Resources