SwiftUI add view to NavigationView - swift

I'm currently working on rewriting a VoIP app from UIKit to SwiftUI. In the UIKit version, we have an active call screen with a button that when tapped, closes the active call screen and lets you interact with the app. Tapping this button also adds a view to the UINavigationController, basically covers most of the navigation view and when tapped, returns the user back to the active call screen.
I'm experimenting with different ideas in SwiftUI, but haven't hit on any solid ideas yet and wanted to see if the community had any ideas for accomplishing this.
Here's a sample of what the UIKit code:
class MainNavController: UINavigationController {
func showActiveCallBar() {
...
let activeCallBarView = ...
...
view.addSubview(activeCallBarView)
}
}
Here's a gif of what happens when we switch back and forth, sorry, couldn't show the whole app. You can see the whole upper portion of the Navigation View gets covered.
Thank you!

In SwiftUI, we would accomplish something like this with an #State variable, which would track wether we want to show the active call bar.
When your state variable changes, your SwiftUI view will be updated and the active call bar will be shown or hidden. It might look something like this.
struct PlayButton: View {
#State private var showActiveCallBar: Bool = false
var body: some View {
if (showActiveCallBar) {
ActiveCallBarView()
}
// ... Other Views
}
}
The SwiftUI documentation of State has more helpful information, and the SwiftUI docs generally are quite helpful in this regard. You could start with the SwiftUI tutorials https://developer.apple.com/tutorials/swiftui

Related

Swift: change size of SwiftUI view presented by a UIKit ViewController

I have a project which has been entirely built using UIKit. We are now trying to slowly introduce SwiftUI for any new UI views that we build into the app.
So y current dilemma is that we have a UIViewController which contains a view with a button that needs to present some kind of a pop-up view containing a list of notifications (which I plan to build using List in SwiftUI. For context, here is how the current view looks (built using UIKit). User would then tap on 'Show me...' and be taken to the new SwiftUI view.
So initially I just tried like this:
#objc func showNotifications() {
let controller = UIHostingController(rootView: NotificationContentView())
self.present(controller, animated: true, completion: nil)
}
This obviously presents a modal view which is great, but I want to be able to control the size of this view. The notification screen should be fairly narrow, not virtually full screen.
I wonder how I might go about implementing this.

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())
}
}

In watchOS, is it possible to display a view without a status bar button that leads to the root view?

I would like to have a similar navigation structure to the built-in Workout app in watchOS. I have a list of tennis rules formats, analogous to workout types in the Workout app. Tapping one starts a match in a new interface controller. In WatchKit, as far as I know, I can only push an interface controller or present one. Both approaches risk the user canceling the match earlier from the top left chevron or tapping the status bar in a presented modally.
The workout does not have that limitation during a workout session, instead, the user ends the workout from switching pages in its page-based navigation. Does SwiftUI with its fully programmatic way of watchOS app development allow for accomplishing this?
Below is the initial view of the Workout app
Selecting a workout switches to a screen where the top left title isn't tappable, which is what I'd like to accomplish (the initial view is completely hidden and does not show when you swipe between the three pages)
Maybe you need to modify your view with:
.navigationBarBackButtonHidden(true)
Did you try that?
I think you need to take a look at reloadRootPageControllers()
See https://developer.apple.com/documentation/watchkit/wkinterfacecontroller/2868441-reloadrootpagecontrollers
The basic idea appears to be that you are replacing the current interface controllers with the named ones listed in this method.
WKInterfaceController.reloadRootPageControllers(withNames: ["workout","nowPlaying"], contexts: [workoutToRecord], orientation: WKPageOrientation.horizontal, pageIndex: 0)
In my Interval Training app I call this method once a user has selected their workout. and this interface is then replaced with workout interface and now playing page.
You will note that there is no back button for them to accidentally return to the workout select screen.
Hope that helps.

Update text field values in multiple tabs with single button

I have 6 tabs in my application.
Each tab has a text field.
There is one button in the sixth tab, which when pressed, should reset the text fields in all the other 5 tabs to blank.
I am unable to figure out any direction in which I should look.
I am pretty new to Xcode, so please pardon my ignorance on this topic.
One thing I have tried so far is to set global variable.
When I press the button, I update the global variable to ""
But then I go to the other tabs, the value has not been updated.
My understanding is that I an not writing the code in the right place.
Currently, I have written this code in viewDidLoad function of each tab's viewController class:
override func viewDidLoad() {
super.viewDidLoad()
telephone.text = ViewLine.GlobalVariable.phone1
timerData.text = ViewLine.GlobalVariable.concept1
}
phone1 and concept1 are my global variables.
Would anyone be able to suggest where should I write this code? or is there a better way to do this?
Thanks
Write code in viewWillAppear
override func viewWillAppear() {
super.viewWillAppear()
telephone.text = ViewLine.GlobalVariable.phone1
timerData.text = ViewLine.GlobalVariable.concept1
}
I think that what you want is the first 5 view controllers to react to a tap on a button in the 6th view controller.
In that case - don't use global variables.
Use notifications:
When the button did tap, send a notification. The first 5 view controllers should subscribe to this notification channel. When each of the first 5 view controllers receive a notification they should change the text to "".
Here is a link on notifications:
https://www.raywenderlich.com/160653/design-patterns-ios-using-swift-part-22

Swift storyboards: split view controller not showing properly on MacOS

I am trying to implement a split view controller using storyboards & swift on MacOS:
For some reason only the right side shows up. Any ideas ?
It's actually a window size issue. As it is undefined it push the left side out of view. Just place the cursor on the left side and drag to show the left view.
Hope it helps.
UPDATE:
It's actually NOT a window size issue. It looks like that the split view controller push one side out of view by default. Conversely, I was able to view the two panes correctly using the split view component inserted into a view controller.
I'll be checking for information about this issue in the latest WWDC:
https://developer.apple.com/videos/wwdc/2014/?id=212
https://developer.apple.com/videos/wwdc/2014/?id=214
UPDATE 03/11/14:
After minute 07:00 of the first screencast I got what was going on. Take a look at the screenshot below:
Make the Split View Controller as wide as the main window.
Resize the Split View Items.
Click on the items with the right most Split View Item, add Missing Constraints from the Pin pop up menu.
It may take few tries before you get it right. I tested it three times and it did work.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/index.html#//apple_ref/doc/uid/20001093
NSSplitViewDelegate
class SplitViewController: NSSplitViewController{//,NSSplitViewDelegate
Swift storyboards: split view controller not showing properly
It was really problem for me as well. Now I got solved this problem in my code.
1.Create a class extended NSSplitViewController.
2.Set a class created in phase1 as Custom class on your SplitView which you created on StoryBord.
3.call MySplitView.adjustSubviews() inside viewDidLoad().
import Cocoa
class SplitViewController: NSSplitViewController{//,NSSplitViewDelegate
#IBOutlet weak var MySplitView: NSSplitView!
override func viewDidLoad() {
super.viewDidLoad()
MySplitView.adjustSubviews();
}
override func splitView(splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
return proposedMinimumPosition + 200
}
}