Navigation bar for UIWebView - ios

I am new on iOS. Trying to implement a navigation bar for my UIWebView.
My TableView calls the webview when user clicks on any row. I load different local HTML files based on the index user clicked on. My webview is loading correctly but the problem is, I want to keep a navigation bar and < back button there, so that user can click it to come back to the tableview.
Here is the my ProductTableViewController:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ProductTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ProductTableViewCell
let product = products[indexPath.row]
cell.name.text = product.name
cell.generic.text = product.generic
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let resultController = storyboard!.instantiateViewControllerWithIdentifier("webView") as? WebViewController {
presentViewController(resultController, animated: true, completion: nil)
}
//print(indexPath.row)
clickedOn = indexPath.row
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let svc = segue.destinationViewController as! WebViewController;
//if clickedOn == 3{
svc.fileName = "Ace-VetBolus"
//}
}
And my WebViewController:
override func viewDidLoad() {
//print("got: "+self.fileName)
let url = NSBundle.mainBundle().URLForResource(self.fileName, withExtension:"html")
let request = NSURLRequest(URL: url!)
web1.loadRequest(request)
}
Please help me to write Swift code for this.

If you are presenting the WebViewController on ProductTableViewController, and want to have Bar Buttons on Navigation bar, I would suggest you to embed WebViewController in UINavigationController in IB.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let navc = segue.destinationViewController as! UINavigationController;
let svc = navc.topViewController as! WebViewController;
//if clickedOn == 3{
svc.fileName = "Ace-VetBolus"
//}
}
Will be the minor change in prepareForSegue method.
The back button on bar has to be added manually.

replace your didSelectRowAtIndexPath with following one, it works for me.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let resultController = storyboard!.instantiateViewControllerWithIdentifier("webView") as? WebViewController {
let navController : UINavigationController = UINavigationController (rootViewController: resultController)
self.navigationController?.presentViewController(navController, animated: true, completion: nil)
}
//print(indexPath.row)
clickedOn = indexPath.row
}

Related

navigationItem.title from UITableViewCell

Navigation Bar title is not appearing according to the Selected Cell.
I have the Navigation View Controller inside a Container View.
The Container View is in ViewController.
ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "embedseg" {
guard let splitViewController = segue.destination as? UISplitViewController,
let leftNavController = splitViewController.viewControllers.first as? UINavigationController,
let masterViewController = leftNavController.topViewController as? MasterViewController,
//let detailViewController = splitViewController.viewControllers.last as? DetailViewController
let rightNavController = splitViewController.viewControllers.last as? UINavigationController,
let detailViewController = rightNavController.topViewController as? DetailViewController
else { fatalError() }
let firstMonster = masterViewController.monsters.first
detailViewController.monster = firstMonster
masterViewController.delegate = detailViewController
detailViewController.navigationItem.leftItemsSupplementBackButton = true
detailViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
//detailViewController.navigationItem.title = "Hello" <-- tested this, it worked.
//detailViewController.navigationItem.title = cell.textLabel?.text <-- this didn't work.
//detailViewController.navigationItem.title = monster.name <-- and this didn't work.
}
}
MasterViewController:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let monster = monsters[indexPath.row]
cell.textLabel?.text = monster.name
return cell
}
When you select the cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! YourCellClassName
self.performSegue(withIdentifier: "embedseg", sender:cell.textLabel?.text)
}
in prepareforSegue
let cellText = sender as! String
detailViewController.navigationItem.title = cellText
This happens because monster and cell are defined inside
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
but not inside
override func prepare(for segue: UIStoryboardSegue, sender: Any?){}
If you have set your segues using the storyboard you can do something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if let cell = sender as? UITableViewCell {
detailViewController.navigationItem.title = cell.textLabel?.text
}
}
or something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if let cell = sender as? UITableViewCell {
let indexPath = tableView.indexPath(for: cell)
detailViewController.navigationItem.title = monsters[indexPath.row].name
}
}
In the first case you cast "sender" as the cell so you can access it's values, in the second case you cast "sender" as the cell, you find what is it's indexPath and then you use the indexPath to find the correct "monster" using you array monsters

TableViewCell to ViewController - Swift

I tried many ways but still can't go to another ViewController. This is my storyboard.
and This is my code.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? HistoryMainTableViewCell {
listItems.sort() { $0.seq > $1.seq }
let history = listItems[indexPath.row]
cell.setValue(history: history)
return cell
} else {
return HistoryMainTableViewCell()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "vcProductHistory" {
if let productHistoryPage = segue.destination as? HistoryProductViewController {
if let IndexPath = tableViewHistory.indexPathForSelectedRow {
let historyArray = listItems[IndexPath.row]
productHistoryPage.history = historyArray
}
}
}
}
Try this code:(Untested Code)
Note: Below code will trigger prepare segue. When, tableViewCell selected.Let me know the code works...
func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
// let indexPath = myTableView!.indexPathForSelectedRow
// let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
//sendSelectedData = (currentCell.textLabel?.text)! as String as NSString
performSegue(withIdentifier: "vcProductHistory", sender: self)
}
Based on your answer to my initial comment: dragging the line from initial vc to destination vc tells your vc about the segue, preparing for segue tells your vc what do when the segue is triggered, but you still need to let your vc know when it should perform the segue. try this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? HistoryMainTableViewCell else { return HistoryMainTableViewCell() }
let history = listItems[indexPath.row]
cell.setValue(history: history)
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "vcProductHistory" {
guard let productHistoryPage = segue.destination as? HistoryProductViewController, let indexPath = sender as? IndexPath else { return }
let historyArray = listItems[indexPath.row]
productHistoryPage.history = historyArray
}
}
func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
performSegue(withIdentifier: "vcProductHistory", sender: indexPath)
}
I think this is a little bit neater using the guard syntax. Also, it uses sender as the indexPath, not using tableView.indexPathForSelectedRow.
Also, I noticed you have this in your cellForRowAtIndexPath:
listItems.sort() { $0.seq > $1.seq }
Your sorting your data source in cellForRowAtIndexPath. You can't do that there because that function gets called for each row individually. You need to do the sorting before that is called, somewhere like viewWillAppear. Also, to sort an array in place you need to remove the () after sort. try this.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
listItems.sort { $0.0.seq > $0.1.seq }
tableView.reloadData()
}
I think you should connect to UINavigationController , not to HistoryProductionViewController
Because your MainViewController's segue connected to Navigation Controller
I guess in func prepareForSegue segue.identifier == "vcProductHistory" it works but, if let productHistoryPage = segue.destination as? HistoryProductViewController not works
because your destination ViewController's class is NavigationController
you should call
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "vcProductHistory" {
if let naviVC = segue.destination as? UINavigationController {
if let productHistoryPage = naviVC.topViewController as? HistoryProductViewController {
if let IndexPath = tableViewHistory.indexPathForSelectedRow {
let historyArray = listItems[IndexPath.row]
productHistoryPage.history = historyArray
}
}
}
}
}
Your solution - as you described it - should work.
The most work here can be done directly in the Storyboard.
Select the prototype cell in the TableView, drag the Segue to the NavigationController and select presentModally.
This should work without further magic.
When selecting the TableViewCell the NavigationController should be presented. There is also no code needed at this point (except for the population of the TableView).
If not - you maybe misconfigured your TableView by setting the selection to No Selection:
or you set User Interaction Enabled to false somewhere.

Swift - Expand tableview without Storyboard segue

I am trying to create a similar tableview like the one below:
https://github.com/justinmfischer/SwiftyExpandingCells
I already have a complete tableview with contents, including a filtering system. The current problem is that I want to implement the same functionality to expand cells and show detailed information, without using storyboard.
The sample code (link) uses a storyboard segue, but I want to get rid of that so that it can basically do the same thing through code. I removed the label for the background. Just want to get the title and a new controller first by clicking a tableview cell.
DetailViewController
class DetailVC: UIViewController {
var brand: Brand?
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
func setup() {
self.view.frame.origin.y = UIApplication.sharedApplication().statusBarFrame.size.height
if let brand = self.brand {
self.title = brand.name
}
}
}
This part needs to change
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedCellFrame = tableView.convertRect(tableView.cellForRowAtIndexPath(indexPath)!.frame, toView: tableView.superview)
self.selectedBrand = BrandManager.sharedInstance.brands[indexPath.row]
self.performSegueWithIdentifier(.DetailVC , sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segueIdentifierForSegue(segue) {
case .DetailVC:
let vc = segue.destinationViewController as! DetailVC
vc.brand = self.selectedBrand
self.navigationController?.delegate = self
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedCellFrame = tableView.convertRect(tableView.cellForRowAtIndexPath(indexPath)!.frame, toView: tableView.superview)
self.selectedBrand = BrandManager.sharedInstance.brands[indexPath.row]
let vc = storyboard?.instantiateViewControllerWithIdentifier("DetailVc") as! DetailVC
vc.brand = self.selectedBrand
self.navigationController?.pushViewController(vc, animated: true)
}//// add the storyboardID for the detailsVc as "DetailVc"

Reciever has no segue with identifier swift 2

I am trying to pass value from Realm via segue to another viewcontroller. The problem is it is crashing with error : Reciever has no segue with identifier. I tried other way, prepareforsegue but it is not working as well as this one.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let lektire = datasource[indexPath.row]
let destinationVC = DetaljiViewController()
destinationVC.programVar = lektire.ime
destinationVC.performSegueWithIdentifier("oLektiri", sender: self)
}
However, my segue is definitely there, and its identifier is properly set (see screen shot below).
What is going on, and how can I fix this problem?
I believe this is what you are looking for you have to call performSegueWithIdentifier from the view controller you are currently inside of and either make the sender the indexPath or you can make it your datasource item.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("oLektiri", sender: indexPath)
// Another WAY
self.performSegueWithIdentifier("oLektiri", sender: datasource[indexPath.row])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "oLektiri") {
let indexPath = sender as! NSIndexPath
let toViewController = segue.destinationViewController as? NextViewController
let lektire = datasource[indexPath.row]
toViewController?.selectedObject = lektire
}
// Another WAY
if(segue.identifier == "oLektiri") {
let lektire = sender as? lektireTYPE
let toViewController = segue.destinationViewController as? NextViewController
toViewController?.selectedObject = lektire
}
}
// An example of what the next view controller should look like
class NextViewController: UIViewController {
var selectedObject: ObjectType?
}

How to Segue from Custom TableViewCell to Another ViewController (Swift)

I am attempting to navigate from a TableViewCell to a detail VC indicating details about the current business that is on the cell. Here are the stub tableiewMethods:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("YelpTableBusinessCell", forIndexPath: indexPath) as! YelpTableBusinessCell
var business:Business = Business(dictionary: businessArray[indexPath.row] as! NSDictionary)
cell.business = business
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
businessToUseTVC = Business(dictionary: businessArray[indexPath.row] as! NSDictionary)
performSegueWithIdentifier("businessToDetailVC", sender: view);
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let cell = sender as? YelpTableBusinessCell {
if segue.identifier == "businessToDetailVC" {
if let ivc = segue.destinationViewController as? AttractionsDetailViewController {
ivc.businessToUse = self.businessToUseTVC
}
}
}
}
I set two breakpoints, one at the prepareForSegue method and one at the didSelectRowAtIndexPath method
I initialize businessToUseVTC variable in didSelectRowAtIndexPath, but when I run the app, when I am at the AttractionsDetailVC, which contains this bit of code,
func loadYelpInfo() {
businessName.text = businessToUse.name
let thumbImageViewData = NSData(contentsOfURL: businessToUse.imageURL!)
thumbImage.image = UIImage(data: thumbImageViewData!)
let reviewImageData = NSData(contentsOfURL: businessToUse.ratingImageURL!)
reviewImage.image = UIImage(data: reviewImageData!)
categories.text = businessToUse.categories
reviews.text = "\(businessToUse.reviewCount!) Reviews"
distanceLabel.text = businessToUse.distance
}
the code breaks, saying that businessToUse, set inside DetailsVC, is nil.
Any help would be greatly appreciated.
First, make sure you ctrl drag from the VIEWCONTROLLER, not the individual cell.
Second, the sender is not of type YelpTablseBusinessCell, i believe this is your problem.

Resources