I'm using xCode 6 to write a simple game in Swift. I have a variety of files in the project. How does xCode know where to begin when executing the code? It seems to me that it automatically starts with the file that, following various tutorials, I have called "GameViewController.swift." But how does it decide to use this file first? Does it scan the source files for a UIViewController object and start there?
For iOS, Swift looks for a class with the #UIApplicationMain attribute, and uses that as the Application's delegate.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
...
}
Using that attribute is equivalent to calling the UIApplicationMain function and passing the class’s name as the name of the delegate class. That in turn will handle loading your default Storyboard and load its initial view controller.
If no #UIApplicationMain is found, Swift looks for a file called main.swift and for a function called main inside of that and calls it.
if you are using storyboards, you have a setting called "Main Interface" on your target. This offers a dropdown list where you can select the storyboard file. i.e. Main.storyboard. This setting will be written to the Info.plist file that will be loaded at start time.
In this file a view controller is set as the initial view controller and will be loaded first.
To give you an idea of Apple architecture here's an example of a Cocoa app which applies to iOS Objective-C as well:
Every application starts at main but the developer entry point is usually AppDelegate. This applies to Swift as well, even if main has disappeared from the application lifecycle. Bear in mind, that main existed just to launch the app or few minor tweaks.
If you're using Storyboards, you'll be able to set the starting screen of your app from there, conversely if everything is done in code AppDelegate will be responsible of it at this point:
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Related
In my SwiftUI project I see AppDelegate file as well as a SceneDelegate file.
What are the differences between them?
For example between the methods in SceneDelegate
scene(_:willConnectTo:options:)
and in the AppDelegate
application(_:didFinishLaunchingWithOptions:)
The two files are meant to split the work by what is needed to run the app as a whole and what is needed for one "instance" that would support visibly running in the background. This would be something like configuring a database once, but displaying different sets of values by window.
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.
Courtesy of https://www.hackingwithswift.com/articles/193/whats-new-in-ios-13
AppDelegate is responsible for handling application-level events(like app launch), application lifecycle, and setup.
SceneDelegate is responsible for handling what is shown on the screen (Windows or Scenes) and managing the way your app is shown.
scene(_:willConnectTo:options:) is the first method called in UISceneSession life cycle. This method will create a new UIWindow, set the root view controller, and make this window the key window to be displayed.
application(_:didFinishLaunchingWithOptions:) is called when the application is launched and where the application set-up is done. Earlier iOS 13, we might have used this method to configure the UIWindow object and assign a ViewController instance to the UIWindow object to make it display on the screen. From iOS 13, if your application has scenes, then AppDelegate is no longer responsible for handling this and is moved to SceneDelegate.
From: https://medium.com/#kalyan.parise/understanding-scene-delegate-app-delegate-7503d48c5445
Multiplatform
In addition to the answer of Abandoned Cart, Since Xcode 11, You have a new option called Multiplatform for choosing as a starting template. That's where you will only see a file contains:
#main
struct MyMultiplatformApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
This is how the system knows where to start the code with #main (in Swift 5.3) and it contains WindowGroup that manages multiple windows of your app in all apple platforms. So you don't need the be worry about SceneDelegate and AppDelegate anymore.
If you need it to be like the old app delegate, for example when you want to use its methods, You should subscribe for corresponding notifications or use the UIAppDelegateAdapter wrapper as I described here
I'm new to Objective-C and iOS programming. I've read through a few of Apple's "Getting Started" docs and I've downloaded a few sample applications to try and get familiar with what is going on in the app. What I'm confused about is what exactly happens from the application's launch. I see in main.m that UIApplicationMain gets called and invokes the AppDelegate. From what I've read, now, if applicationDidFinishLaunching returns true, the app will enter the main event loop.
Is this all correct? If so, how do I tie my code to events? Where do I create instances of my classes when an event occurs?
Finally, from my understanding, Xcode now creates all template apps with storyboards. However, some applications I am looking at are a bit older and don't use storyboards, but I don't see .xib or .nib files anywhere in the directory, but the applications successfully build. Am I wrong in assuming that applications require these files?
An application does not require a .xib or .nib to run. Many programmers do not use any of the visual design tools that generate storyboards or .nib files. You can define your UI completely in code if you wish.
The call to UIApplicationMain in main.m creates a singleton UIApplication object, sets up an event loop, and sets up your UIApplicationDelegate which works in tandem with UIApplication so you can customize the behavior of your app at key points in its lifecycle. UIApplication manages the event loop for you. It receives events from the system and dispatches them to your code for handling.
In order to really understand event handling you need to understand the responder chain. If you look at the superclass of your app delegate you will see it is UIResponder. This is the interface that lets objects respond to and handle events. It is the superclass of UIApplication and UIView and handles most of the raw event handling for you. Events follow a defined path through your code. In the simplest case, touch events, UIApplication pops an event from the event loop and hands it off to UIWindow. UIWindow will perform a hit test to try and deliver it directly to the UIView under the finger. It gets more complicated and motion events take a different path but the point is that much of the raw event processing is handled for you by UIKit. All you really need to do is setup your UIWindow and its rootViewController and events will follow a specific delivery path through all your UIKit responders. You can read about the responder chain in detail here https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html.
When your app starts, the following delegate methods will get called in this order:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
- (void)applicationDidBecomeActive:(UIApplication *)application;
In addition, your initial view controller will get created and shown and the following methods will get called (assuming you are using storyboards or xib files):
-(void)viewDidLoad;
-(void) viewWillAppear:(BOOL)animated;
As for "tying your code to events", what type of events are you talking about? What are you trying to accomplish?
You no longer need to use xib files if you are using storyboards, however, you can if you want to.
I am developing app with finding audio frequency by using FFT. In my app, I am not able to call application delegate method in app delegate class as given in below, but I could able to call other custom methods in app delegate class. What mistake I have done?
Please help me!
(void)applicationDidFinishLaunching:(UIApplication *)application
It looks like your project files have got a bit mixed up. To be honest, it's probably easier to start with a new application template as a base and then add your changes into it. If that is not possible, have a look at the following
In your {project_name}.plist file under the Resources folder you should see a setting
Main nib file base name
This will tell you which nib file is loaded at the start (normally MainWindow). Open this file and have a look for 'Files Owner' 'UIApplication'. Right click on this and there should be a link to the delegate. If it isn't there, then that's your problem
Check to make sure your application delegate inherits from NSObject and NOT NSApplication as NSApplication is a singleton. Otherwise your application object will be its own delegate.
You should now be using application:didFinishLaunchingWithOptions:
I come from an iPhone OS development background. I'm now trying to write apps for OSX, but I don't understand where cocoa on OSX decides where the program gets control.
I can see the main function, but where does program control go from there? Say for example I want to programatically create a window with an NSView in it once the app has finished launching - how would I do that? There is no app delegate created that I can see, in iPhone OS I would wait for the -(void) applicationDidFinishLaunching:(UIApplication *)application
method to be called. I really don't want to use the Interface Builder or NIB files to setup my window/view. How would I go about this?
It's much the same as the iPhone. In your application controller class, override NSApplication's applicationDidFinishLaunching delegate method. If you used the standard Xcode project template your app controller is already instantiated in your Interface Builder MainMenu.xib and set to be the application's delegate; if not you'll need to drag it in there and set up those connections yourself.
Speaking more generally, an OS X app begins its life in the main method, where Cocoa will automatically set up your application's run loop and load the .xib file you specify in Info.plist. This xib is usually where your application controller is instantiated. By overriding one of the methods such as +initialize, -init, -applicationWillFinishLaunching or -applicationDidFinishLaunching (which all have subtly different behaviors) you can load additional controllers and nibs with objects that interact with the run loop at a future date, so you can continue to execute code after your launch method has finished.
As in the one defined with "Main nib file base name" in the app's Info.plist. Should I just use applicationDidFinishLaunching?
Yes, applicationDidFinishLaunching: gets called after the main nib has been loaded.
Also, according to the documentation (for iPhone OS 3.0):
It is recommended that you implement
application:didFinishLaunchingWithOptions:
instead of this method. See the class
description for the differences in
calling sequences between the two
methods.