Open URL in different ViewController when tableView cell is pressed - ios

I am using SWRevealViewController for a slide-out menu in my app. The main View Controller contains a WKWebView to open URLs. When the slide-out button is pressed, a table view Controller appears.
I want to have the name of a website displayed in a Table View Cell in the Table View Controller in the slide-out menu and open that website in the WKWebView in the main View Controller when the cell is pressed.
This may seem like an easy question, but I can't seem to find anything about it online.
Thanks in advance for your help.

As far as I remember the implementation of SWRevealViewController, it uses the static table view.
If you are okay with the static table view that will have your links then you may just create a delegate method that will be called based on the cell that was chosen on the Table View Controller. This delegate will notify your ViewController and say which link to open.
Hope it's clear. Let me know if you need more details.

In SideMenuViewController (view controller in which you have table with links)
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let mainViewController = MainViewController()
mainViewController.link = linksArray[indexPath.row]
self.revealViewController().setFrontViewController(mainViewController, animated: true)
}
init new main view controller that have WKWebView
pass link as a property
set that view controller as new front view controller

Related

Editing Bar Buttons with PushSegue iOS

I want to have barButtonItems in the navigation bar of a view which I arrive at through a pushSegue.
I tried to achieve this by adding a navigation bar item to my storyboard, but when I launch the app, the barButton doesn't show in the build. See the screenshots here:
How the navigation bar looks on build
How I built it in Storyboards
Flow of the Storyboard
I segue to my MainTextView by clicking on a cell using this code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
if let destination = storyboard?.instantiateViewController(withIdentifier:"MainTextView") as? MainTextView {
destination.post = (posts[indexPath.row])
destination.delegate = self
navigationController?.pushViewController(destination, animated: true)
}
}
}
The back button doesn't even show up in the Storyboard. How could I change the default back button and add additional buttons to the navigation bar programmatically?
I assume this might be a Xcode 11/ios 13 related issue. Click on the segue and change it from push to present modally. From there change presentation context to fullscreen. You might be able to leave the it as push but when you click on your your viewcontroller/navigation controller go to the attributes inspector and look for a option called presentation, and set it to full screen.
Another option to try is to click on the view controllers, go to attributes inspector and under navigation controller - bar visibility tap (shows navigation bar)
Last thing I can think of is that when your segue to and from should be connected to the navigation controller.
Actually a few more possibilities...
1) check your debug view hierarchy when you launch the app. What I mean by this is
https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/ExaminingtheViewHierarchy.html
basically its a button you click and you'll be able to see how the views are stacked onto of each other. My best guess is that while you have a bar item button there, the nested button is not actually present/showing.
2) nest your tableviewcontroller in another navigation controller.

Tab Bar disappears on segue

What I want to achieve:
I have a "Login" ViewController which segues to a Tab Bar Controller.
My Tab Bar Controller goes to a Navigation Controller and then "Home" ViewController with a Table View. This view is my "Home/Welcome" page. I want there to be a Tab Bar at the bottom as well as a static table which I can edit with Prototype Cells. Each cell goes to a different ViewController.
Then, I want to be able to tap each Cell (I have "Info" setup for now) and it segue to the corresponding ViewController. For now, the "Info" cell should go to the second Navigation Controller and then "Information" ViewController.
From there, I want another static table which I can edit with Prototype Cells. Each cell will go to a seperate stack of ViewControllers.
My problem:
When I segue from the "Info" cell in the "Home" ViewController, the Information tab bar "pushes" up, and the Tab Bar disappears. I've experimented with other segue forms but none of them maintain the Tab Bar.
I want it so you can use either the Tab Bar to navigate to the Info ViewController or the cell on the Home/Welcome ViewController to navigate to the Info page.
I have no code at all at this point, I am just using these segues.
Does anyone have any idea how I can achieve what I want to achieve, and if so, provide as much sample code as I'm extremely new to Swift.
Any help is appreciated! Thanks :)
Don't add segue to open the "Information" ViewController which is part of UITabBarController.
You must have used didSelectRowAt for cell selection in tableview. Just add one line in it as it is :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true) {
self.tabBarController?.selectedIndex = 1
}
This will change the tab and open the "Information" ViewController.
If you want to load the "Information" ViewController with data relevant to cell selection you can go with Protocols or NotificationCentre which can pass data to "Information" ViewController from Homeviewcontroller on cell selection.

Pausing UIGestureRecognizer for parent view controller

I have added a pop up to my app and it lays over the main parent view controller. But when I swipe on the pop up the main view controller is recognizing the swipes. How can I prioritize the child view controller for actions or stop the gesture recognizer on the main view controller while the pop up is open?
Here's the code where I add the child view:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedItem = self.menuItems[indexPath.row]
let ratingVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "rating") as! RatingView
ratingVC.mainView = self
ratingVC.foodName = selectedItem
self.addChildViewController(ratingVC)
ratingVC.view.frame = self.view.frame
self.view.addSubview(ratingVC.view)
ratingVC.didMove(toParentViewController: self)
}
Thanks for adding the code! It looks like we should change how we are presenting the View Controller. First, I'll explain the simple reason this code doesn't work: When this method returns, the ratingVC variable is cleared, and since it is the only reference to your View Controller, that View Controller is cleared from memory. So your touches cannot be sent to it :-)
There are a couple better ways to present a view controller. Your code is doing what is called "View Controller Containment", and it may be overkill unless you know why you are doing it that way.
The first thing you could do is set the presented view controller as a strong property on this table view controller, and then use presentViewController:animated:completion: to present it. This is simple, and Apple's libraries handle putting it's view on screen.
The recommended way these days, though, to present a View Controller's scene after a table view cell is tapped goes like this:
Use Storyboards to setup both the table view (with prototype cells) and the destination scene.
Ctrl-Drag from the cell prototype to the destination scene.
In your table view controller's code, use prepareForSegue:sender: to give the destination View Controller it's required state.
As a side note, ratingVC.mainView = self in your code may imply another anti-pattern. The easy advice is: Make darn sure that mainView is marked as weak. The better advice is to use a loose-coupling design pattern like delegation, target/action, or callbacks.

How to add a view to UINavigationController that is visible above any child view

I'm creating an app which shows data in a UITableView. This data also contains location information, so I want to add a MapView to display this data. When a user taps a UITableViewCel, I need to segue to another UITableView to show the detailed data. I still want to show the MapView with the same data above this detailed data, and I still want the NavigationBar to update, i.e. the back buttons returns the user to the first UITableView.
In image form to make it easier to understand
I was thinking of making a subclass of a UINavigationController and putting the container underneath the MapView, but I don't really know where to go from there.
Have VC0 embedded in a navigation controller or subclass UINavigationController. Create an Info ViewController and push that on the navigation controller.
In your particular case you'll want to use the didSelectRowAt method from UITableViewDelegate.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// use indexPath.section and indexPath.row to use your data
let infoVC = yourInfoViewController()
infoVC.title = "Info Cell Name"
navigationController?.pushViewController(infoVC, animated: true)
}
Edit after first comment:
I'm not sure what the best way of doing this is but one way you can do it is:
Modify your table view based on what is being shown, ie: first set of data or cell detail data
Update the navigation bar's title and left bar buttons per set of data you're displaying
One of those buttons will only appear in the cell detail data set and it sets your switch back to displaying the first set of data

How to change button name when cell selected in UITableView in swift?

I have two UIButton and when you click on each you will go to table view controller and there you can select something.
My question is how to change the button title on selection of any cell.
I want to replace button title with selected cell's name.
There are two ways to pass data back to the previous viewController.
1) Using Delegates, check this
2) Using Notifications, check this
Bind button in your cell as #IBOutlet
When cell selected delegate method tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath. Here you can get your cell with [tableView cellForRowAtIndexPath:indexPath]
Change your button's title [cell.yourButton setTitle...]
If you were to make your navigation controller into you root view controller and put the view controller you wish to access the buttons from as its top view controller then you could do the following when a cell is tapped:
if let topVC = navigationController?.topViewController as? MyButtonViewController {
topVC.button1Name.setTitle("New Title", forState: .Normal)
}
Then you can hide the navigation bar on the top view controller with the following:
override func viewWillAppear(animated: Bool) {
navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(animated: Bool) {
navigationController?.setNavigationBarHidden(false, animated: animated)
}
Instead of using two navigation controllers you can use a single NavC and then make your view controller with the two buttons as the root view controller. Then when the buttons are pressed you load the appropriate table view controller. Also if your table view controller has the same data source then you can use a single table view controller itself.
Then depending on which button is pressed you push the appropriate table view controller but in the prepareForSegue keep track of which button was pressed so that you can change its title when a cell is selected in the table view controller.
To pass the selected cell details from the table view controller you can make use of a delegate which your view controller can implement and the table view controller will call and pass the selected cell details.
So in short do this.
Make your navC as the initial view controller.
Make your view controller with the two buttons as the root view controller of the navC
In the IBAction of the two buttons store which button was pressed so that you will know which buttons's title has to be changed.
When you load table view controller set the view controller as a custom delegate.
In the language list table view controller's didSelectRowWithIndexPath use the delegate to pass the selected cell info and pop the view controller.
In the delegate method of the view controller change the button title that you have stored in step 3 to the selected cell's text.
I have another solution which I have uploaded here. It does not contain any custom view controllers except the ViewController that has the two buttons. It makes use of segues and unwind segues.
http://www.filedropper.com/twobuttonnavc

Resources