I'm trying to figure out the delegate and the protocol and studying the tutorial. It has the following code:
class SelectTimeViewController: UIViewController, PopupDelegate{
...
let sb = UIStoryboard(name: "DatePopupViewController", bundle: nil)
let popup = sb.instantiateInitialViewController() as! DatePopupViewController
popup.delegate = self
…
}
What does this line in the code mean?
let popup = sb.instantiateInitialViewController() as! DatePopupViewController
I understand that here we are creating a popup constant and assigning something to it, which is then cast to the DatePopupViewController class.
But what does this mean more generally?
- Are we create an instance of the DatePopupViewController class?
- Are we assign any value from the DatePopupViewController class?
- Anything else?
CodePudding user response:
Your storyboard has one or more scenes. Each scene is managed by a view controller. Usually you'll create a custom UIViewController
subclass for each scene. In the storyboard editor, for each scene, you type in the name of that custom class.
One of the scenes in the storyboard can marked as the “initial scene”. UIStoryboard
has a method, instantiateInitialViewController
, that loads that scene from the storyboard.
But there are lots and lots of storyboards in the world, and they use lots and lots of different custom UIViewController
subclasses for their scenes. You might even have multiple storyboards in a single app, each with an initial scene that uses a different custom subclass.
There is no way, at compile-time, for UIStoryboard
to know what class the instantiateInitialViewController
is going to load. All it knows at compile-time is that it's going to load a UIViewController
, or a subclass of UIViewController
. So instantiateInitialViewController
is declared to return UIViewController
.
But when you're writing your code, you usually do know what specific subclass it's going to load, and often you want to do things that depend on the subclass. In the code you posted, you're setting a property named delegate
, which is a property specific to DatePopupViewController
—it is not a property of UIViewController
.
In order to access that delegate
property, you need to tell Swift what you know that Swift doesn't already know. You need to tell Swift that you're loading a DatePopupViewController
. You do that using syntax called a “cast”:
let popup = sb.instantiateInitialViewController() as! DatePopupViewController
↑ ↑ ↑ ↑ ↑ ↑
| | | This method returns a | The subclass you know
| | | UIViewController object. It | you're loading.
| | | might be (and usually is) a |
| | | subclass of UIViewController. The cast operator.
| | | The ! means the program
| | This variable references will crash if the
| | a UIStoryboard object, loaded object is not
| | which represents a an instance of
| | storyboard at runtime. DatePopupViewController.
| |
| This variable gets bound to the
| newly-loaded DatePopupViewController.
|
This says that the popup variable cannot
be changed to point at a different
instance of DatePopupViewController.
CodePudding user response:
I will explain you the code step by step...
class SelectTimeViewController: UIViewController, PopupDelegate{
Definition of the SelectTimeViewController
class, which is a UIViewController
and implements the PopupDelegate
protocol. SelectTimeViewController
can work as a delegate only because of this implemented protocol.
let sb = UIStoryboard(name: "DatePopupViewController", bundle: nil)
Creates a storyboard object from the file DatePopupViewController.storyboard
.
let popup = sb.instantiateInitialViewController() as! DatePopupViewController
Instantiates the initial ViewController
in this storyboard object. You can identify the initial ViewController
by the arrow in the storyboard file. Remember that each view in the storyboard has a ViewController
. So you create the view together with the ViewController
. In your case the ViewController
is the DatePopupViewController
.
You could omit as! DatePopupViewController
. In this case the popup
constant is only of type ViewController
and you can't access any attributes of DatePopupViewController
.
popup.delegate = self
Your instantiated DatePopupViewController
is now assigned to the popup
constant. So you can access DatePopupViewController
's attributes through the popup
constant. We have implemented the PopupDelegate
protocol in the first code line. Therefore we can set the current class (SelectTimeViewController
) as delegate of DatePopupViewController
.
Summary:
- Yes, assigned to
popup
- Yes,
delegate
ofDatePopupViewController
- See above
CodePudding user response:
About #1.
Usually, when we create an instance of a class, we use the following syntax:
constant (or variable) = ClassName (initializer)
For example:
var item = Item(name: "Car")
In this case, the syntax is different:
let popup = ... DatePopupViewController
That is, there is no class initializer here.
Why then do we call it creating of class instance?