Thank you for your answer, but I think @OOPer misunderstood my question. As far as I understand, the File Owner object is already an instance, not a type, when NIB is loaded. This is understandable because the entity that's going to substitute this File owner object is also an instance. But, at which point does this File Owner object get instantiated? Is it before NIB is loaded or after? NIB is lazy loaded, meaning it's only loaded when it is called by a certain instance, which means the order in which the File Owner object gets instantiated is either:
NIB gets called and lazy loaded
File Owner object gets instantiated
The caller object substitutes the instance of the File Owner object
or
File Owner object gets instantiated
NIB gets called and lazy loaded
The caller object substitutes the instance of the File Owner object
Also @OOPer mentioned that
It may change dynamically when loading the nib. in regards to what the "type" of the File Owner object is. I'm aware that it eventually gets substituted by an instance of another type, but what I'm actually curious about is that since the File Owner object is already an instance as a placeholder, what is it an instance of prior to being substituted by something else?
Post
Replies
Boosts
Views
Activity
@OOPer
It cannot be the reason. As you know, you can replace nil with an instance. Or you may be using the word instance in some other ways? The point is, the File Owner object IS actually an instance. Are you saying it's not? I'm just curious as to the order in which it gets instantiated and what the type of it is.
Matt Neuburg provides his own definition in his book "iOS 14 Programming Fundamentals with Swift":
So what is the nib owner object? It’s a proxy representing an instance that already exists outside the nib at the time that the nib is loaded. When the nib is loaded, the nib-loading mechanism doesn’t instantiate that object; the nib owner is already an instance. Instead, the nib-loading mechanism substitutes the real, already existing instance for the nib owner object, using the real instance to fulfill any connections that involve the nib owner.
Yes, but it seems like he's saying the nib-loading mechanism doesn’t instantiate that object because the nib owner is already an instance.
It sounds like it's all semantics at this point and the File's Owner is one and the same as the "self" that's calling the NIB. But, isn't Nuburg saying that File's Owner exists even before Bundle.main.loadNibNamed("SomeNIBFile", owner: self ) is executed?
Instead, the nib-loading mechanism substitutes the real, already existing instance for the nib owner object, using the real instance to fulfill any connections that involve the nib owner. When A substitutes for B, A and B are separate entities (ex. I'm substituting stevia for sugar). "The real, already existing instance" is A, which is what you're referring to as "self" in your example. B is the nib owner object which exists as an instance prior to "self" replacing it.
@OOPer
I've reached out to the author, but he never responded. Now that I revisit it though, I understand what you're saying and it makes sense to me. Thank you for the clarification.
So an example would be something like this:
override func awakeFromNib() {
super.awakeFromNib()
class SomeClass {
@objc func buttonPressed(_:Any) {}
}
self.addTarget(nil, action: #selector(SomeClass.buttonPressed), for: .valueChanged)
}
Do you want to know how the responder chain works? Or why such a mechanism like the responder chain exists in iOS? Sounds like that's what I'll have to do to understand this.
I was actually copying the template provided by the Apple documentation. - https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area Also, I've tried your example, but still didn't work.
@OOPer
I understand what you're saying and that was initially what I thought as well, but even when I tried to impose the additional insets to MyVC, the super view controller, instead to SecondVC, it still doesn't provide the spacing.
So instead of:
secondVC.additionalSafeAreaInsets = newSafeArea
I tried:
self.additionalSafeAreaInsets = newEdgeInsets
it made no difference.
I tried keeping the additionalSafeAreaInsets to SecondVC and adding a child view controller, AnotherVC, to SecondVC to see if it provides the insets, but didn't:
class SecondVC: UIViewController {
let anotherVC = AnotherVC()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .yellow
addChild(anotherVC)
self.view.addSubview(anotherVC.view)
anotherVC.didMove(toParent: self)
}
}
class AnotherVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .purple
}
}
As far as I understand, safe areas, unlike regular margins, are imposed by a view controller and propagated down the view hierarchy or the child view controller hierarchy. This is intentional so that if there is a top bar or a bottom tab bar, all the subviews and child VC's will also be safe from being covered by those bars. So it was my assumption that when we are adding the safe area, we are adding to the existing one from the parent view controller.
Apple's example from this documentation - https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area also shows that the additional insets are being added to the child view controller to achieve what I'm trying to achieve:
override func viewDidAppear(_ animated: Bool) {
var newSafeArea = UIEdgeInsets()
// Adjust the safe area to accommodate
// the width of the side view.
if let sideViewWidth = sideView?.bounds.size.width {
newSafeArea.right += sideViewWidth
}
// Adjust the safe area to accommodate
// the height of the bottom view.
if let bottomViewHeight = bottomView?.bounds.size.height {
newSafeArea.bottom += bottomViewHeight
}
// Adjust the safe area insets of the
// embedded child view controller.
let child = self.childViewControllers[0]
child.additionalSafeAreaInsets = newSafeArea
}
What is shown in the Apple documentation is in fact what I'm trying to do where there is one parent view controller and a child controller along with another view. The child view controller and the view are next to each other within the parent view controller set by additionalSafeAreaInsets.
I've also tried applying the constraints, but still doesn't work:
secondVC.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
secondVC.view.leadingAnchor.constraint(equalTo: self.leftView.safeAreaLayoutGuide.trailingAnchor),
secondVC.view.heightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.heightAnchor),
secondVC.view.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor)
])
or
secondVC.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
secondVC.view.leadingAnchor.constraint(equalTo: self.leftView.trailingAnchor),
secondVC.view.heightAnchor.constraint(equalTo: self.view.heightAnchor),
secondVC.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])
Maybe I'm not understanding Apple's example clearly. Could you explain why the example applies additionalSafeAreaInsets to the child view controller?
I understand where you're coming from, but that's not the point of this discussion. Also, I think view controller containment utilizes more than using a view controller as a dumb container.
Anyways, would you be able to try running the code in your Playground? I've formatted it so that it can work in Playground.
Thank you so much!
Inside Debug-iphoneos, I have a regular folder named MyApp.build, not sure if I'm supposed to see a package bundle. Inside of the folder are files like Base.lproj, DerivedSources, storyboards, but no executable files. And there is also no TCore framework.