Instead of assigning the view controller as the UITableViewDelegate, I'm trying to reduce the code in the view controller by creating an extension for the UITableViewDelegate.
Why am I getting the error "Use of unresolved identifier companyDetailVC" for the line companyDetailsVC = CompanyDetailsViewController() when that is correct Swift 3 syntax?
Code
extension TableViewDelegate: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
companyDetailsVC = CompanyDetailsViewController()
self.present(companyDetailsVC, animated: true, completion: nil)
}
}
Edit: I'm trying to do this programmatically without storyboard. I created a UITableViewDelegate extension because I'm trying to reduce the code in the View Controller.
The code for presenting the Viewcontroller should be somewhat like this
and the extension should be like
extension YourClassNameHere: UITableViewDelegate {
//then your did select method comes here and in that put this code for presenting the viewcxontroller
let companyDetailsVC = CompanyDetailsViewController() //change this to your class name
self.present(companyDetailsVC, animated: true, completion: nil)
}
Replace your code with below code. You will need to provide your ViewController to create its extension and to use the property and method of it.
Make sure companyDetailsVC is declared in the controller. You don't need to use self until its called from block.
extension yourViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.companyDetailsVC = CompanyDetailsViewController()
self.present(companyDetailsVC, animated: true, completion: nil)
}
}
Related
Hello I actually use a tableview in my app. I have this lines of code which switch from a VC to a mother and it work fine everywhere :
let vue = MAINSTORYBOARD.instantiateViewController(withIdentifier: "accueil") as! Accueil
self.present(vue, animated: true, completion: nil)
In my tableView I use the function DidSelectRowAt ( this execute when I click on a row/cell) to do this (switch of VC)
But you've already understood when I click it work but with latency.
This latency can is sometimes 1-2s sometimes up to 12s it's random. That's weird.
I specify the function above work instantly with buttons and others.
this is the code (I write only important things) :
class Horaire: ViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vue = MAINSTORYBOARD.instantiateViewController(withIdentifier: "accueil") as! Accueil
self.present(vue, animated: true, completion: nil)
}
and the other class :
class Accueil: ViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad executed")
}
}
So when I click on a cell of my tableview it immediately print "viewDidLoad executed" but VC switch is done only after some random seconds.
Why does I have this latency and how to fix it ? it don't use segue
The first thing that came to my mind was to put the block in the main queue. I know didSelectRowAt is supposed to run in the UI thread, but I saw on the internet a couple complaints about this very same thing. Looks like a bug to me.
class Horaire: ViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
DispatchQueue.main.async{
let vue = MAINSTORYBOARD.instantiateViewController(withIdentifier: "accueil") as! Accueil
self.present(vue, animated: true, completion: nil)
}
}
}
You can see for some odd reason this seemed to work for these people:
https://github.com/HeroTransitions/Hero/issues/79
I'm trying to change the text that follows the < on the Navigation Controller. I successfully accomplished this in a UIViewController with a TableView that is its own DataSource and Delegate with code like this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var newVC = NewViewController()
self.title = "HomeVC"
navigationController?.showViewController(newVC, sender: indexPath)
}
When "HomeViewController" is presented, the back button on the Navigation Controller shows "< HomeVC" - the ViewController that we just came from.
Now, I'm trying to accomplish this with another UIViewController that has a TableView, but the DataSource and Delegate are in a separate file. Following the same logic as above, this is what I tried:
class CalendarTableDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var newVC = NewViewController()
self.navController?.title = "HomeVC" // ----> did not work
HomeViewController().title = "HomeVC" // ----> did not work
self.navController?.showViewController(newVC, sender: indexPath)
}
}
Ideas, anyone? Assuming that I want to keep the DataSource and Delegate in a separate file.
I am trying to create a custom keyboard extension that pushes to another UIViewController that has a list of text that can be inserted onto the selected text field. It subclasses a UIInputViewController. However, when I try to use the textDocumentProxy to input text on didSelectRowAtIndexPath() nothing seems to be happening.
Does the textDocumentProxy only apply to the default KeyboardViewController.swift file that was generated or am I able to to create another UIViewController that subclasses UIInputViewController to insert text? My last resort would be to use delegation or create a listener that will call a function in KeyboardViewController.swift, but I just wanted to see if anyone knew a better way.
Thanks in advance!
Code example is shown below:
import UIKit
class AnotherInputViewController: UIInputViewController, UITableViewDelegate, UITableViewDataSource {
...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
var proxy = textDocumentProxy as UITextDocumentProxy
if let input = arrayTextToInput[indexPath.row] as? String {
proxy.insertText(input)
}
}
}
Just in case any noobie runs into this again using the keyboard API extension...
I just injected the KeyboardViewController object into the view controller I was presenting as shown below:
//within KeyboardViewController.swift
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
let nextVC: NextViewController = NextViewController(keyboardVC: self.keyboardVC)
self.presentViewController(nextVC, animated: true, completion: nil)
}
and then just initialized the nextVC with the KeyboardViewController
//class NextViewController
var keyboardVC: KeyboardViewController
init(keyboardVC: KeyboardViewController) {
self.keyboardVC = keyboardVC
super.init(nibName: nil, bundle: nil);
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
From there you have access to keyboardVC and can use that object to call methods to insert text into whichever fields you wish. For example...
call keyboardVC.addText(input) from wherever you want
//class KeyboardViewController.swift
func addText(input: String) {
if let textDocumentProxy = self.textDocumentProxy as? UITextDocumentProxy {
textDocumentProxy.insertText(input)
}
}
Hope it helps !
I faced the same problem, and I fixed it by using Delegation.
where pass action of insert text to KeyboardViewController
First create delegate
protocol UITextDocumentProxyDelegate: AnyObject {
func insertText(_ text: String)
}
, then in AnotherInputViewController create variable delegate with type UITextDocumentProxyDelegate
weak var delegate: UITextDocumentProxyDelegate?
and replace your code to
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
if let input = arrayTextToInput[indexPath.row] as? String {
delegate?.insertText(input)
}
}
, and finally in KeyboardViewController conform UITextDocumentProxyDelegate protocol and implement insertText method
extension KeyboardViewController: UITextDocumentProxyDelegate {
func insertText(_ text: String) {
proxy.insertText(text)
}
}
I have a class and extension Swift file. After adding a delegate that I declared in another file to the class, Xcode shows this error
Declaration is only valid at file scope
at the extension line. I don't know what the problem is.
Can anyone help me to fix it?
class ListViewController: UIViewController, AddItemViewControllerDelegate {...}
extension ListViewController: UITableViewDataSource{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
performSegueWithIdentifier("ShowDetail", sender: indexPath)
}
}
The error is somewhere in your ... — that error means that your ListViewController class didn't get closed, so the extension is being interpreted as nested inside, like this:
class ListViewController {
...
extension ListViewController {
}
}
Find the missing closing brace and you should solve the problem.
The extension must be at the root level - don't embed them into a class or whatever.
Make sure that the extension is declared at the end of your main class and after the last curly braces "}"
class ListViewController: UIViewController, AddItemViewControllerDelegate {
//Make sure that everything is clean here!
}
extension ListViewController: UITableViewDataSource{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
performSegueWithIdentifier("ShowDetail", sender: indexPath)
}
}
Make sure your class and extension are seperated.
class ViewController: UIViewController {}
extension name: type {}
I had my extension calls at the bottom of my file and put them at the top and that fixed it for me. At the bottom, they were outside the class scope so I was a little stumped and just tried this.
The extension should be out of the Class.
class ListViewController: UIViewController, AddItemViewControllerDelegate {...}
// Code...
}
extension ListViewController: UITableViewDataSource{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
performSegueWithIdentifier("ShowDetail", sender: indexPath)
}
Usually, I change view like this:
var goBackToMainView:MainViewController = self.storyboard?.instantiateViewControllerWithIdentifier("navigation2") as MainViewController
self.presentViewController(goBackToMainView, animated: true, completion: nil)
But if I try to do this in my custom UITableViewCell when the user tap a button, it gives me errors like customTableViewCell does not have a member named 'storyboard' and 'presentViewController'
How can I change views in my TableViewCell ?
Have you tried adding as a subview?
Example:
var tableViewCell = UITableViewCell(frame: aFrame)
tableViewCell.addSubview(aView)
Why do it in the UITableViewCell subclass? You should be doing your view management in the ViewController.
In your view controller:
import UIKit
// Take note of UITableViewDelegate, you'll need it to be able to use
// tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
class MyTableViewController: UITableViewController, UITableViewDelegate {
// Assuming that you have a storyboard variable in AppDelegate
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
// .. more code here like viewDidLoad, etc.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var viewController = appDelegate.storyboard.instantiateViewControllerWithIdentifier("MainViewController") as MainViewController
// This will probably appear as a modal
self.presentViewController(viewController, animated: true, completion: nil)
}
}
Note: I just did a quick playground for the code above so you may need to unwrap optionals.
If you have your view controller embedded in a navigation controller, you might want to use Unwind Segues. More information about that here: What are Unwind segues for and how do you use them?
Cheers!