I have a ViewController which consist of UILabel and UIButton. OnClick UIButton a popOver present which show tableView. each cell of tableView represent different font option.
I want to change the font of UILabel based on user selected font from tableViewCell. how i can achieve this as my UILabel and tableView are in different viewController class.
Please help me.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var row = indexPath.row
// How to update label from here
}
Edit : I fond this answer but not able to understand as its return in objective c update ViewController label text from different view
You can use delegate. In your popover Swift file create such protocol:
protocol PopoverDelegate {
func didSelectFont(font: UIFont)
}
In your popover class create such implementation of newly created protocol:
class popoverviewcontroller : UITableViewController {
var delegate: PopoverDelegate?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var row = indexPath.row
// How to update label from here
delegate.didSelectFont(youFontHere)
}
}
Now in your main view controller, if you are presenting your popover programmatically, you should set your popover's delegate property to self. If your are presenting popover from storyboard, just handle segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
let destination = segue.destinationViewController as! popoverviewcontroller
destination.delegate = self
}
Now implement delegate method:
func didSelectFont(font: UIFont) {
//Update label's font
}
And of course don't forget to add delegate to your main view controller:
class mainViewController: UIViewController, PopoverDelegate { ...
Hope it helps!
Related
I'm trying to segue data from UIViewController to UITableViewController.
The data in UIViewController is coming from PFTableViewController and I want to pass that data to another TableViewController.
For passing to ViewController didSelect method is used but I have no idea how can I segue from viewController to TableViewController.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let destinationToFVC:ViewController = self.storyboard!.instantiateViewControllerWithIdentifier("FVCont") as! ViewController
if let indexPath = self.tableView.indexPathForSelectedRow {
let row1 = Int(indexPath.row)
destinationToFVC.currentObject = objects?[row1] as! PFObject!
}
navigationController?.pushViewController(destinationToFVC, animated: true)
}
I'm new to programming.
In your case you can launch the segue manually from your didSelectRowAtIndexPath, with the the method performSegueWithIdentifier.
You need to create a custom segue in your Storyboard from your UIViewController to your UITableViewController and set an Identifier for it, you can press Ctrl + Click from your UIViewController to the next to create the custom segue and then select the segue and in the Attributes Inspector set the Identifier for the segue just a this picture:
Then you can in your didSelectRowAtIndexPath launch the segue manually as in this code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// the identifier of the segue is the same you set in the Attributes Inspector
self.performSegueWithIdentifier("mySegueID", sender: self)
}
And of course you need to implement the method prepareForSegue to pass the data from your UIViewController to your UITableView like in this code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mySegueID") {
// in this line you need to set the name of the class of your `UITableViewController`
let viewController = segue.destinationViewController as UITableViewController
let indexPath = self.tableView.indexPathForSelectedRow()
destinationToFVC.currentObject = objects?[indexPath] as! PFObject!
}
}
EDIT:
If you want to perform your segue from an UIButton to the UITableViewController it's the same logic, just create the custom segue in your Storyboard and then call the prepareForSegue like in the following code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mySegueID") {
// in this line you need to set the name of the class of your `UITableViewController`
let viewController = segue.destinationViewController as UITableViewController
/ here you need to pass the data using the reference viewController
}
}
I hope this help you.
In my project, I have a few View Controllers and I use UINavigationController.
When I make a seque from UIViewController to UITableViewController I have "back" button added automatically, but when I make seque from UITableViewController to UIContentViewController tapped a cell, I don't have a "back" button in UIContentViewController.
Plan of my app is here
The segue in UITableViewController looks like that:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let CV = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
let tnumber = tableView.indexPathForSelectedRow?.item
CV.titleContent = daneOWpisach?[tnumber!]["title"]
CV.webContent = daneOWpisach?[tnumber!]["description"]
CV.category = category
self.presentViewController(CV, animated: true, completion: nil)
}
What should I do, if I would like to have a back button in UIContentViewController added automatically?
In your code you are presenting the view controller on cell selection..! Back button will show only if you perform push not on presenting the view.
In the above diagram what I have seen is you already make the segue from UITableViewController to UIContentViewController. select the segue and go to attribute inspector give the identifier for the segue.
On the cell selection perform the segue action with the identifier you specified
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("Your Segue name", sender: sender)
}
If you want to pass data to destination view controller, do it like below..
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "Your Segue name" {
let CV = segue.destinationViewController as! ContentViewController
let tnumber = tableView.indexPathForSelectedRow?.item
CV.titleContent = daneOWpisach?[tnumber!]["title"]
CV.webContent = daneOWpisach?[tnumber!]["description"]
CV.category = category
}
}
Hope this helps you
I have this:
MyTableViewController (inherits from UITableViewController)
It has a dynamic tableview with a few cells (foo, bar, qux)
MyViewController (inherits from UIViewController)
There are some "show" segues from this controller to other view controllers
It has a UIContainerView that embeds MyTableViewController
A picture speaks a thousand words:
When a certain cell is selected, I want to perform a segue of the parent view (MyViewController)
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (indexPath.section == 1 && indexPath.row == 1) {
self.WHAT.performSegueWithIdentifier("someShowSegue1", sender: self)
}
}
Is it possible? what should I use in «WHAT»?
In the prepareForSegue: for your embedded segue set the viewController in a new property in your tableViewController, let's name it parentController. And then you'll have just to call self.parentController.performSegueWithIdentifier().
EDIT: But first of all, maybe you can use the existing parentViewController if it contains the embedding view controller.
You may want to consider using delegation to solve this problem since the child tableView doesn't seem like it should be responsible for the segue. For example:
// MyViewController
class MyViewController: UIViewController, MyTableViewControllerDelegate {
func selectedMyTableViewControllerCell(cell: UITableViewCell) {
// ... check cell type or index or whatever
self.performSegueWithIdentifier("someValueFromCellType", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == myTableViewControllerIdentifier {
if let vc = segue.destinationViewController as MyTableViewController? {
vc.delegate = self
}
}
}
}
// MyTableViewController
protocol MyTableViewControllerDelegate: class {
func selectedMyTableViewControllerCell(cell: UITableViewCell)
}
class MyTableViewController: UITableViewController {
weak var delegate: MyTableViewControllerDelegate?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// ... get the cell
delegate?.selectedMyTableViewControllerCell(cell)
}
}
No need to create a property. Just this
self.parent?.performSegue(withIdentifier: "ID", sender: self)
SWIFT 4
Swift 4 no longer has parentViewController. You must use parent to access the parent object and is an optional so be sure to check for nil where necessary.
self.parent?.performSegue(withIdentifier: "IdentifierHere", sender: self)
Hook your segue up to the embedded table view controller's cell instead. You can use different segues per cell prototype. This saves you from checking index paths or even implementing didSelectRow at all.
Segue is defined from one view controller to another and is only invoke from the view controller in which it is defined. So you would need to store the reference of the parentViewController.
Like from MyViewController
if ([segueName isEqualToString: #"embedseg"]) {
MyTableViewController * tblViewController = (MyTableViewController *) [segue destinationViewController];
tblViewController.parentController=self; //Storing reference of parentViewController i.e MyViewController
}
Now you can simply invoke segues like
self.parentController.performSegueWithIdentifier("someShowSegue1", sender: self)
Hope this helps
override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath : NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier ("ChecklistItem") as UITableViewCell
let label = cell.viewWithTag(1000) as UILabel
if indexPath.row == 0 {
label.text = "jaswanth"
} else if indexPath.row == 1 {
label.text = "nikhil"
} else if indexPath.row == 2 {
label.text = "krishna"
}
return cell
}
I have UITableViewController, I have used above code to display the cells in the table and I had another UIViewController when user taps on jaswanth the text(labels text) in UIViewController have be changed and the same way when nikhil is tapped the text(labels text) in UIViewController have changed
I had only one UITableViewController and one UIViewController how can I do this?
You would want to be able to detect when these cells in the table are pressed. This can be done using the recommendation by Mike Welsh through implementing the method: func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
This allows you to be able to tell which cell is selected from the NSIndexPath.
From here on, it seems to me that you want to be able to change the text (on a button or field) that is controlled by another UIViewController. One way it can be done is to have a reference to this UIViewController and creating a method to update this text field.
If the UITableViewController is a child view controller, it can be as simple as calling
let parent = parentViewController!
Else if the Controllers are related by a Segue, it can also be done by overriding prepareForSegue of the original ViewController.
By using the segue.identifier to map to the segue you have made in StoryBoard/programmatically, you are able to set a delegate/pointer to the original UIViewController.
override func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?) {
if segue.identifier == "SomeStringID" {
self.tableViewController = segue.destinationViewController as? UITableViewController
self.tableViewController.delegate = self
}
}
With the reference to the other ViewController, you should be able to define your own method to change this text field quite easily
Hope this helps you!
I have created a TableView application following the "Beginning iPhone Development with Swift " book.The search Bar tableView is created with code and not within the storyboard.The book explains how to get search results and display the corresponding cells but I would like my app to perform a segue to a ViewController I have created in the storyBoard.How can I trigger a Segue with code ?
for more info , this is my file :
import UIKit
class SearchResultsController: UITableViewController , UISearchResultsUpdating{
let sectionsTableIdentifier = "section identifier"
var products = [product]()
var filteredProducts = [product]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UITableViewCell.self,
forCellReuseIdentifier: sectionsTableIdentifier)
}
// MARK: - Table view data source
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return filteredProducts.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(
sectionsTableIdentifier) as UITableViewCell
cell.textLabel!.text = filteredProducts[indexPath.row].name
return cell }
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailView"{
let index = self.tableView?.indexPathForSelectedRow()
var destinationViewController : infoViewController = segue.destinationViewController as infoViewController
destinationViewController.Title = filteredProducts[index!.row].title
destinationViewController.eam = filteredProducts[index!.row].energy
destinationViewController.fam = filteredProducts[index!.row].fat
destinationViewController.pam = filteredProducts[index!.row].protein
destinationViewController.cam = filteredProducts[index!.row].carbohydrates
destinationViewController.imgName = filteredProducts[index!.row].imgName
}
}
func updateSearchResultsForSearchController(
searchController: UISearchController) {
let searchString = searchController.searchBar.text
filteredProducts.removeAll()
for prod in products{
var name = prod.name.lowercaseString
if name.rangeOfString(searchString) != nil {
filteredProducts.append(prod)
}
}
tableView.reloadData()
}}
Because the controller is built in code, you need to use the SearchResultsController's tableView delegate method didSelectRowAtIndexPath to trigger the presentation of the next view controller.
Assuming that there is a table view controller underpinning the SearchResultsController, you could potentially use that as the delegate of the SearchResultsController. The main table view controller might already have the necessary code to segue when a cell is selected, in which case you need to check which tableView has been selected in order to correctly determine which product the cell represents.
To set the delegate, add the following line to the code (in your comment above) where you create the SearchResultsController:
resultsController.tableView?.delegate = self
Then amend the didSelectRowAtIndexPath method to test which tableView is triggering the method:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (tableView == self.tableView) {
// use the existing code to present the detail VC, based on the data in the main table view
...
} else {
// use new code to present the detail VC, based on data from the SearchResultsController
...
}
}
If the main table view controller is in a storyboard, you can use a segue to present the detail VC. In this case you would use self.performSegueWithIdentifier() in the above code. If not, you would either use self.navigationController?.pushViewController() (if you are embedded in a navigation controller) or self.presentViewController() (to present the detail VC modally).
Another option would be to set the SearchResultsController's delegate to be self (in viewDidLoad), and then to implement didSelectRowAtIndexPath in the SearchResultsController class. In this case, you don't need to test which tableView has triggered the method, but you will not be able to use a segue.