Why is the modifier .navigationBarTitle not applied to NavigationView? - swift

In SwiftUI, I understand that modifiers are used to modify a view. When modifying a view, the modifier returns the view wrapped in _ModifiedContent.
When embedding my view inside a NavigationView and assigning a navigation bar title like this: (as seen in Apple's official tutorials)
NavigationView {
Text("Hello, World!")
.navigationBarTitle(Text("My first SwiftUI App"))
}
...why is the modifier for the navigation bar title applied to Text, not to NavigationView?

Like Martin linked to, navigationBarTitle only works when contained in NavigationView. This is discussed briefly in the SwiftUI Essentials talk at ~52:30. The title ends up flowing up to the NavigationView, so that views that get pushed can also provide a title of their own (e.g. the view that gets pushed at ~54:00).
If the title was attached to the NavigationView directly, all possible titles would need to be determined up front and removed from the views the titles are associated with.
It's similar to UIViewController's navigationItem property, which is attached to each pushed view instead of the UINavigationController itself.

Because the .navigationBarTitle() is modifier on the View inside of NavigationView, It is not on the NavigationView. And the same is the case for .navigationBarItem().
Please refer to Building Lists and Navigation

Related

Swift UI - Using Navigation View and a Navigation Link - Creating view models before the Navigation Link is Activated

Inside a navigation view, I have a navigation link that shows the details of the item selected. Every detail view has its own view model. The problem is when I do it this way and check my memory graph I can see all my detail view models have been instantiated and stored in memory even before I make a selection from the list. I'm wondering if this is some sort of a sort UI bug when using the navigation View/Link or if I'm doing something wrong.
Check NavigationLazyView:
SwiftUI NavigationLink loads destination view immediately, without clicking
e.g.
NavigationLink("SomeLinkLabel", destination: NavigationLazyView(Text("SomeLink"))
edit: been using this for a while, I forgot this is not part of standard SwiftUI

How can I make a storyboard to the left of an initial view storyboard on Apple Watch using SwiftuI?

My Goal:
To make 3 views side by side, where each view takes up all of the Apple Watches viewable area. Something like Apple's workout app when it's on a current workout.
Using the stack overflow answer here I figured out how to use storyboards to make swipable views to the right of the Initial view, but how can I make a swipable view to the left of the initial storyboard view?
When I connect views with ctrl mouse from one view to another, the only segue option I get is next page, which makes a swipable view to the right.
Well, in SwiftUI 2.0 it looks like there is a very easy way to integrate this with a simple TabView and I'll show an example
struct threeViewsInOne{
#State private var selectedPage = 1
var body: some View {
TabView(selection: $selectedPage) {
ViewA.tag(0)
ViewB.tag(1)
ViewC.tag(2)
}
.tabViewStyle(PageTabViewStyle())
}
}

What's the difference between a View and a ViewController? [duplicate]

This question already has answers here:
What is the difference between a View and a View Controller? [closed]
(3 answers)
Closed 7 years ago.
Coming to Swift from Delphi, I thought the View represented an app's GUI and the storyboard was a visual representation of the View's underlying code. The ViewController was the one and only object the View interacted with. When a popular tutorial says
In the old days developers used to create a separate interface file
for the design of each view controller.
I'm thinking the "separate interface file" was the View file. But as I learn more, I'm getting confused. Beneath a screenshot of an empty Main.storyboard from a new application, the text says
The official storyboard terminology for a view controller is "scene,"
but you can use the terms interchangeably. The scene is what
represents a view controller in the storyboard ... Here you see a
single view controller containing an empty view.
So I'm seeing a "single view controller," not a view?? Confusion mounts when I note any views(?) displayed on a storyboard are called "View Controllers" in Swift.
So, what's the difference between a View and ViewController? How is a storyboard related? And what object "owns" something like a segue, which exists outside my (flawed) understanding of these concepts?
Take a look at this post - What is the difference between a View and a View Controller?
This described it pretty well for me.
If you don't want to go to the link, here is a great description of the difference between a view and a view controller by Alex Wayne:
A view is an object that is drawn to the screen. It may also contain
other views (subviews) that are inside it and move with it. Views can
get touch events and change their visual state in response. Views are
dumb, and do not know about the structure of your application, and are
simply told to display themselves in some state.
A view controller is not drawable to the screen directly, it manages a
group of view objects. View controllers usually have a single view
with many subviews. The view controller manages the state of these
views. A view controller is smart, and has knowledge of your
application's inner workings. It tells the dumb view objects what to
do and how to show themselves.
A view controller is the glue between your overall application and the
screen. It controls the views that it owns according to the logic of
your application.

How to create a segue performing a transition to the same view with another model object?

I am writing an iOS / CocoaTouch app and I am facing the following problem :
I have a detail view (think of an overview of one given object)
This detail view can present other elements
Any of these other elements can be viewed in this exact same detail view (I mean, another instance of this view / view controller using the viewed object model.
The only problem I have is that I am not able to create a segue from a view to the same view in the storyboard editor. Therefore, I cannot create the segue at all, cannot assign an identifier, and thus cannot trigger it from code.
Is there any way to implement this ?
This is as simple as a detail view pushing another, each of them having one dedicated instance of the view controller with their respective object model.
Thank you so much, I looked everywhere and cannot find any topic related to this.
Christophe.
Segues are between view controllers, not views (even though a view can act as a trigger). If you want to have a segue to a new view controller, create a new instance of it in the storyboard, assign its identity to the same class as your original detail, and define the segue.
If you're only trying to change which view is displayed inside a single view controller, then selectively setting views hidden and not-hidden can work...or adding/removing sub-views.

How to tell if view has appeared via popping or not?

Using a UINavigationViewController, how do I find out how a view has appeared?
The view has either appeared in a straightforward manner, as the first view in the UINavigationController stack. Or it has appeared because a second view has been popped and the first view has revealed itself again. How do you find out which of these happened?
The only reliable way to do this, as far as I'm aware, is to subclass UINavigationController and override the UINavigationBarDelegate methods:
– navigationBar:shouldPushItem:
– navigationBar:didPushItem:
– navigationBar:shouldPopItem:
– navigationBar:didPopItem:
Don't forget to call super, of course.
Simple approach is to add a property to your RootViewController to track whether or not it has pushed another view onto the navigationController.
-(BOOL)hasPushedSecondView;
Initialize to NO in your init method.
Before pushing secondViewControllers view onto the stack, update the property to YES.
In viewWillAppear, check the value and update your view accordingly. Depending on how you want the application to behave you may need to reset the hasPushedsecondview property back to NO.
you could take a look at the leftBarButtonItem or backBarButtonItem, based on how your application is written and determine how the view appeared. If it is on top, unless you have a custom leftBarButtonItem, there would be no object there.
You can determine this directly via a couple of methods on your UIViewController subclass.
From Apple's documentation:
Occasionally, it can be useful to know why a view is appearing or
disappearing. For example, you might want to know whether a view
appeared because it was just added to a container or whether it
appeared because some other content that obscured it was removed. This
particular example often appears when using navigation controllers;
your content controller’s view may appear because the view controller
was just pushed onto the navigation stack or it might appear because
controllers previously above it were popped from the stack.
The UIViewController class provides methods your view controller can
call to determine why the appearance change occurred.
isMovingFromParentViewController: view was hidden because view controller was removed from container
isMovingToParentViewController: view is shown because it's being added to a container
isBeingPresented: view is being shown because it was presented by another view controller
isBeingDismissed: view is being hidden because it was just dimissed