iOS, use AppDelegate in InterfaceBuilder, two instances created - ios

In an iOS application I implemented some application logic in the AppDelegate.
Several view controllers etc. need to call the AppDelegate, so i placed the AppDelegate in Interface Builder and gave the ViewControllers an IBOutlet AppDelegate* and drew a link to it.
In the app I see now that there seem to be two instances of the AppDelegate created, one that is called and that gets all the notifications and one that is linked to the ViewControllers.
So i changed my app to use in the ViewControllers:
app_del = (AppDelegate*)[[UIApplication sharedApplication] delegate].
Then I'm calling this appDelegate. But this also is a different instance than the one that gets the notifications. Can anybody explain why?
Can anybody tell me what is going wrong? My suspicion from googling is that the iOS creates the AppDelegate instance and Interface Builder does not know about that one and creates another one? Is that correct?
Can anybody give me some hint on how to best create/plan instances in Interface Builder and in what order they are created in application at startup and in what notification I can rely that they are all created?
Thanks for any hints,
Torsten.

Your suspicion is correct. iOS creates an instance of your application delegate when launching your app, this instance is the one that is registered to receive all of the delegate events and so forth. See here.
Anything you add in to a xib or storyboard will be a new instance, and will not work.
To obtain a pointer to the application delegate, use this method:
[[UIApplication sharedApplication] delegate];
There is a school of thought that says you shouldn't overuse the application delegate as a conveniently available global data or method store, but that is outside the scope of this answer.

Related

Should my app be updated to Scene Delegate

Should my app be updated to Scene Delegate from App Delegate. My app supports ios 13.0 and up
first you have to understand what is difference
You could think of them as the global and private versions. One is shared and the other is limited to the individual owner. In a way, they are exactly what you would expect by the names.
Multi-window support is happening
Next time you create a new Xcode project you’ll see your AppDelegate has split in two: AppDelegate.swift and SceneDelegate.swift. This is a result of the new multi-window support that landed with iPadOS, and effectively splits the work of the app delegate in two.
From iOS 13 onwards, your app delegate should:
Set up any data that you need for the duration of the app.
Respond to any events that focus on the app, such as a file being shared with you.
Register for external services, such as push notifications.
Configure your initial scenes.
In contrast, scene delegates are there to handle one instance of your app’s user interface. So, if the user has created two windows showing your app, you have two scenes, both backed by the same app delegate.
Keep in mind that these scenes are designed to work independently from each other. So, your application no longer moves to the background, but instead individual scenes do – the user might move one to the background while keeping another open.
at last I will say that you can go with Scene Delegate
Courtesy of https://www.hackingwithswift.com/articles/193/whats-new-in-ios-13

Why does the applicationWillResignActive method not work?

In my GameScene.m I have a method called wentToBackGround. This method is called by applicationWillResignActive in AppDelegate:
GameScene *gameScene = [[GameScene alloc]init];
[gameScene wentToBackground];
In wentToBackGround I move my player sprite (just to test if it works) like so:
-(void)wentToBackground {
NSLog(#"BG");
self.player.position = CGPointMake(CGRectGetMidX(self.frame), 1000);
}
The NSLog works, however the players position remains the same. Is this due to the fact that SpriteKit automatically pauses everything once it enters the BG. How do I work around this. I eventually want there to be a pause menu that opens as soon as the user leaves the app. How do I do this properly?
I think it also might not work, because I made a new instance of the GameScene. How do I use the old instance? (the old instance was created in another scene, the TitleScene)
I think it also might not work, because I made a new instance of the GameScene
Correct, you got it! Well done. Keep in mind (and I think you are now grasping this) that a class is just a template. The objects in your app are instances, and you can make many instances of one class. So when you say
[[GameScene alloc]init]
you are making a new instance. That's legal but pointless; sending it the wentToBackground message does nothing of any use, because it isn't in your interface. The GameScene instance you want to talk to, the one in your interface, is elsewhere.
Getting a reference to a particular existing instance can be tricky. You sometimes have to arrange things in advance to make it possible. However, I think you can avoid the whole problem here. UIApplication has not only an app delegate method but also a notification for letting you know that you will resign active. So just have the GameScene register for that notification, and now you don't have to involve the app delegate at all.
Here's the documentation on that notification:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/#//apple_ref/c/data/UIApplicationWillResignActiveNotification
Any object can register for a notification, so this is a way to establish that your GameScene wants to be informed of deactivation.

Reloading UIViewController from scratch via AppDelegate applicationWillEnterForeground

What I'm looking for is a very straightforward solution to the following in my XCode project:
When applicationWillEnterForeground is called, I want my main (and only) viewcontroller to reload as if the app is launching from scratch, the reason being I want it to recalculate a number of things at that point which might have changed while the app was in the background, in response to temporal changes detected when the app is launched. I want this to happen rather than the view just to reappear in its last seen state
The viewcontroller is named TMViewController
I have found answers that tell me simply that I have to reload the viewcontroller in the applicationWillEnterForeground section of the AppDelegate, but not how to do this
I have found answers that explain how to reload various elements, labels, webviews, and data from the net. These are much more complex than I need, and I can't really see the needle for the haystack
All I need to happen is the applicationWillEnterForeground to reload the viewcontroller as if its viewDidLoad had been called (I understand that this in itself is not a good solution, not that I know how to do even that!)
I suppose in a nutshell I'm struggling to understand what needs to go in the h & m files of both the AppDelegate and the viewcontroller files to accomplish this
any help would be greatly appreciated
self.window.rootViewController = [[TMViewController alloc]intWithNibName:#"myNib" bundle:nil];

IOS: Is it possible preserve the State of UIViewController in Background

Am developing an IOS app. Where i need to make some images upload to server. Am using NSURLSession and uploadTaskWithRequest to do this. Every thing is working fine in normal way. My requirement user wants to store some post with more than 10 images in app using database SQLLite. And later show all the stored posts in UITableView with button for each UITableViewCell. When user tap on each button it should start uploading each POST to server. So I thought i should persist my UIViewController in AppDelegate so the process of uploading should not be killed when user go to another view controllers.
My Problem: When user close the app the process is in which UIViewController POST uploading is Stoping. So i would like to know how to keep my UIViewController live even in app go close or go into background.
Is there any better way to fulfill my requirement.
Here are some better ways!
Use a singleton. In my apps, I'll usually create a class called "DataHandler" that handles all of the NSURLSession/CoreData/etc stuff so all I have to do is
[DataHandler uploadImages:images];
and when I need the information back I'll call
self.tableData = [DataHandler lastUploadedImages];
This way I don't have to worry if my view controller is still alive.
Have the AppDelegate do the NSURLSession stuff. You already know the AppDelegate is persisted so why not just have that guy do it! Here is an example:
UIApplication *sharedApplication = [UIApplication sharedApplication];
AppDelegate *appDelegate = [sharedApplication delegate];
// this is the method you would add to your AppDelegate. Make sure to
// import your AppDelegate's header file so your ViewController can
// call the method.
[appDelegate uploadImages:images];

App delegate features in viewcontrller - Facebook

I have a sample code with a header and an implementation file and the two appDelegate files. I would like to add what the project does to my app. The first two files are a ViewController file, so I just need to drag it in, but the other two are AppDelegate, and I obviously can't have two app delegate. But in the case of this sample app the app delegate is used as a proper viewcontroller, because in the .m file of the UIViewController file, there is this code:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
Since the AppDelegate doesn't implement methods such as applicationWillBecomeActive:, how can I transform the file into a UIViewController file? What do I need to change in the code above to call the controller, instead of the Delegate (my AppDelegate will so remain untouched).
The code is on GitHub
This is what I have done (the code needs the Facebook API to be included). Go on the download tab and download Archive.zip and AppDelegate.zip: https://github.com/Alexmitico45/FacebookRequests/downloads
Basically the controller ContactFBSViewController is linked the a viewcontroller in the storyboard.
AppDelegate is the singleton that implement the protocol UIApplicationDelegate, because so you can't duplicate it, it must be unique.
You can create your own singletons to store the info available all over your app.
You can google "objective-c singleton" and get some good link to do it

Resources