NSClassFromString in Swift 2.1 - ios

I guess I read most of the SO questions and Google answers on this, but still cannot get it working. Take this code example:
import UIKit
class Person: NSObject {
var name = "Pieter"
}
let PersonClass: AnyClass? = NSClassFromString("Person")
let person = PersonClass()
print(person.name)
Changing NSClassFromString("Person") into NSClassFromString("MyAppName.Person") does not make a difference. Adding as! NSObject.Type behind the PersonClass declaration neither. Adding #obcj(Person before the class declaration neither.
The real-life goal is to read class names from a database and load the appropriate storyboard / UIViewController accordingly. So I am looking for a way to pass the UIViewController class name as a String and instantiate the UIStoryboard with it.
How to do that?
Edit: here is what I currently try for the real-life scenario after your suggestions:
let storyboard = UIStoryboard(name: "MyStoryboard", bundle: nil)
let MyClassName = "MyApp.MyTableViewController"
let MyClass = NSClassFromString(MyClassName) as! UITableViewController.Type
let controller = storyboard.instantiateInitialViewController() as! MyClass
It gives an error saying "MyClass" is not a type. I cannot remove it or I will get an error that it cannot convert from AnyClass.

Try the code given below
let viewController = storyboard?.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
This code allow you to instantiate the storyboard view controller.
But you can not pass the View Controller class name.
You have to pass the storyboard identifier of the view controller.
Please review the below picture for it.

Related

Passing data to a specific ViewController

The picture is just an example...
So basically I want to pass data from RED to BLUE but i have to go through GREEN.. is there a way to just pass the data straight to BLUE without it having to go through GREEN?
What I'm doing now is the conventional method of passing the data to GREEN then having GREEN read it and pass it on to BLUE
But my app has a lot of ViewControllers and I wish to be able to pass it straight to the final page (BLUE page) is there a way? Sorry I'm new to the Swift
If you try to pass data from _Red to _Blue, without _Green - it about bad architecture, becouse if something changed in logic of app, and you need to changed flow of controllers - you will feel a lot of headache...
You can wrap your data in object and pass through or you can make DataController which will be manage your data, and your ViewController's will be get\set it by Datacontroller interface
Use a simple swift class e.g Sharedclass to set a variable and then get the value of the variable from the same Sharedclass. Example is given below
import Foundation
class SharedClass {
static let sharedInstance = SharedClass()
var phoneNumber = ""
}
To set the variable
SharedClass.sharedInstance.phoneNumber = "123456"
To get the variable
BLUEViewController.phoneNumber = SharedClass.sharedInstance.phoneNumber
You can push your navigationController directly to one of your viewControllers. Try this;
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let blueController = storyboard.instantiateViewController(withIdentifier: "BlueViewController") as? BluewViewController {
blueController.passedData = passedData
navigationController?.pushViewController(blueController, animated: true)
}
Or you can just present it too. Instead of pushing in navigation controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let blueController = storyboard.instantiateViewController(withIdentifier: "BlueViewController") as? BluewViewController {
blueController.passedData = passedData
present(blueController, animated: true, completion: nil)
}

How can I call a function of UIViewController from its reference on a different swift file?

I have got my current visibleViewController on a swift file:
let currentController = self.navigationController?.visibleViewController
and I have a function on the swift file associated to the actual UIViewController called chargeData.
What I am trying to do is to call that function from the first file but I am not able to do it. I tried doing:
currentController.chargeData()
but an error is shown:
Value of type 'UIViewController?' has no member 'chargeData'
I can guess from the error log that of course it is not recognizing the swift file in which the actual UIViewController is associated.
So what should I do to access to the function of my actual UIViewController from its reference?
Thanks in advance!
You have to typecast your currentController variable in order to call any method you created on your own.
let currentController = self.navigationController?.visibleViewController as? YourViewController //Here YourViewController is the name of the UIViewController subclass you created
Hope this helps.
You're not far away: you have access to the view controller, but Swift doesn't realize what type it is – it thinks it's a plain UIViewController? when really you know it isn't.
What you need is a typecast. If your class was called ViewController, you would write this:
if let currentController = self.navigationController?.visibleViewController as? ViewController {
currentController.chargeData()
}
If you don't want to cast your currentController from UIViewController to your specific type, then you can use Objective-C's performSelector:
let selector = Selector("chargeData")
if currentController?.respondsToSelector(selector) == true {
currentController!.performSelector(selector)
}
let currentController = self.navigationController?.visibleViewController
NavigationController's VisibleViewController method return UIViewController Type so your method is not find in UIViewController.
let currentController = self.navigationController?.visibleViewController as! YourVC.
Now you can call your method.
In Swift Type is not implicitly find.

How to pass data to embed ViewController?

I have a code, which must pass data with segue:
let navController : UINavigationController = segue.destinationViewController as! UINavigationController
let viewController : UIViewController = navController.viewControllers[0] as! CTableViewController
viewController.SelectedTypeOfVariable = "G"
But I have the following error:
UIViewController does not have a member named SelectedTypeOfVariable
This worked for me:
let viewController : CTableViewController = navController.viewControllers[0] as! CTableViewController
viewController.SelectedTypeOfVariable = "G"
I think the reason for this is because you are saying your "viewController" variable is of type UIViewController. If your "viewController" variable is of type UIViewController, then it indeed does not have a member named SelectedTypeOfVariable. Your subclass of UIViewController, "CTableViewController" does though and so you need to make sure your variable is of type "CTableViewController"
You can use like this
let viewController = navController.viewControllers[0] as! CTableViewController

How to use a variable in other class that is defined in AppDelegate

I have a variable var window: UIWindow? in AppDelegate.swift file inside class AppDelegate that I want to use in other class xyz.swift file inside class xyz as explained in here Get current view controller from the app delegate (modal is possible) but I am getting error at the first line any help will be appreciated. here is the code from xyz.swift
func CurrentView() -> UIView
{
let navigationController = window?.rootViewController as? UINavigationController // Use of Unresolved identifier 'window'
if let activeController = navigationController!.visibleViewController {
if activeController.isKindOfClass( MyViewController ) {
println("I have found my controller!")
}
}
}
Even if I use let navigationController = AppDelegate.window?.rootViewController as? UINavigationController error is 'AppDelegate.Type' does not have member named 'window'
You may have to do as follows:
var appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let navigationController = appDelegate.window?....
As #Dave Durbin has pointed out you are trying to use a variable defined in one class into another class without the reference of the defining class.
This line of code is in xyz.swift
let navigationController = window?.rootViewController as? UINavigationController // Use of Unresolved identifier 'window'
You don't provide any context for window so it's expected to be in this class or a global variable.
This is closer:
navigationController = AppDelegate.window?.rootViewController as? UINavigationController
and you seem to realise that you need to reference the window variable within your AppDelegate instance however the syntax you are using references a static variable and window is a member variable.
I suggest you read through the swift manual and gain a better understanding of variable scopes and check this:
How do I get a reference to the app delegate in Swift?

Loading a instance of a class dynamically in swift

I would like to init an instance of a class specified at runtime. I have the following set up.
//MyClass1 & MyClass2 inherit from UIViewController
let arr = MyClass1.self,MyClass2.self]
func didSelectRow(index:Int) {
var controllerRef = arr[index] //This returns a .Type
var controllerClass = controllerRef() //This returns “the class” MyClass1
//This is where I'm stuck. How do I initialize controller??
//Finally, push VC
self.navigationController?.pushViewController(controller, animated: true)
}
To initialize the VC with Objective C, I was able to do this as follows:
UIViewController *controller = [((UIViewController *)[controllerClass alloc]) initWithNibName:class1Nib bundle:nil];
With Swift, I’m expecting something like the syntax below, but it doesn’t work
//Doesn’t work
var controller = (controllerClass as UIViewController)(nibName: class1Nib, bundle:nil)
//Overriding the init method in MyClass1 and then calling the below doesn’t work
var controller = controllerClass(nibName: class1Nib, bundle:nil)
//The below works, but viewDidLoad() does not get called. It only loads the nib file
var controller = UIViewController(nibName: Class1Nib, bundle:nil)
Any help is appreciated. Thanks
Your question, with its repeated and meaningless "doesn't work" and "the below", is confused and confusing, so I will respond by assuming that what you want to do is instantiate and push a view controller given its class, and I will simply demonstrate in a few lines of code that this is possible.
Here is a function that returns a UIViewController subclass:
func provideVCClass() -> UIViewController.Type {
return ViewController.self
}
And here are lines from a button's action handler where we call that function and use the class to instantiate that view controller and push it onto the current navigation controller:
let vcclass = provideVCClass()
let vc = vcclass(nibName: "View", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)
I assure you that this does work: the correct view controller subclass is instantiated, its nib is loaded, and its view does appear in the interface.
So all I can say in answer to your question, which I don't fully understand, is Go Ye And Do Likewise.
EDIT Here's a little postscript. If your code actually says:
let arr = [MyClass1.self, MyClass2.self]
I would suggest you try saying
let arr : [UIViewController] = [MyClass1.self, MyClass2.self]
...just in case Swift is not inferring the correct type here.

Resources