Can ViewController be generic which contains IBOutlets etc? - ios

Can my viewcontroller be generic and still contain IBOutlet?
class AViewController<T> : SuperViewController, Decodable where T : Decodable {
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
var pop : T?
}
will this impleemntation works? it throws me an error. Type AViewController does not conform to decodable.Any ideas?

Simply remove the , Decodable. There is no reason to indicate that the view controller class itself conforms to Decodable.
Your error is gone with:
class AViewController<T> : SuperViewController where T : Decodable {
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
var pop : T?
}
This is completely independent of why you are also declaring that T must be Decodable. That's a completely separate question I'm not going to address.

View controllers that contain IBOutlets are view controllers that you will manipulate in Interface Builder. There are two problems that you face with this.
An Interface Builder view controller is created using the required init(coder:) initializer, which cannot instantiate generic objects, as it does not have any context in which it knows what T should be at run time.
When you create an instance of AViewController in code you will specify the concrete type
let aVC = AViewController<String>()
but you cannot do such a thing in the Identity Inspector in IB. This is not allowed:
What you can do is create a storyboard specific view controller that inherits from your generic view controller, but specifies the concrete type
class AStringViewController: AViewController<String> {
}
And use AStringViewController in IB in the identity inspector and hook up the outlets as required.
If you find that this isn't really what you want and your view controller needs to be more dynamic then you will have to create your view controller in code and you will not be able to use outlets.
Another alternative is to have a non-generic view controller with your outlets and use child view controllers that are created in code that have the generics you need.

Related

Why am I getting an NSInternalInconsistencyException exception on my UITableView?

UPDATE It turns out that my renaming of my project causes these issues to happen :. I followed all these steps (How do I completely rename an Xcode project (i.e. inclusive of folders)?). I removed all my Outlets and I'm still getting the error so I still don't know what exactly is causing this to happen. For now I'm just going to revert to my previously named project and go from there. If you have any other rec's I'd appreciate them!
I'm simply trying to run my app but I get an "NSInternalInconsistencyException" exception saying that my view controller didn't get a UITableView.
I checked that my IBOutlet from my UITableView is set correctly but I'm still receiving the error..
This is how I'm declaring my IBOutlet...
class EntryViewController: SwipeTableViewController, UITextFieldDelegate {
//MARK - IBOUTLETS
#IBOutlet weak var entryTableView: UITableView!
#IBOutlet weak var entryTextField: UITextField!
#IBOutlet weak var saveButton: UIButton!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
#IBOutlet weak var searchBar: UISearchBar!
This is the error I'm getting:
Screenshot
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: **'-[UITableViewController
loadView] instantiated view controller with identifier "showEntries"
from storyboard "Main", but didn't get a UITableView.'
libc++abi.dylib: terminating with uncaught exception of type
NSException
I imagine this would link my UITableView to my ViewController.
Also, I'm subclassing a view named SwipeTableViewController from my EntryViewController...
class SwipeTableViewController: UITableViewController, SwipeTableViewCellDelegate {
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 80
}
Wouldn't my EntryViewController be automatically subclassed to the UIViewController from there?
Looks like you have UITableView outlet declared in UITableViewController. Make sure your class is a subclass of UIVIewController instead of UITableViewController.
In your storyboard, look for the view controller with identifier "showEntries" , delete it, and drag the UIViewController element instead of UITableViewController element.
Then drop the UITableView into the UIViewController and connect it to the tableview outlet property in your view controller.
Do below steps.
1.Delete all outlets from storyboard.
2.Create a class of type UIViewController.
3.Drag and drop a new tableview to the storyboard.
4.Connect all the outlets with respective UI Elements.
Or you need to make your class as UITableViewController type.
Now It will not crash.

Cannot connect IBOutlet to a UIViewController (or subclass thereof)

I am currently trying to build a demo app in Xcode 8.2.1 using swift to learn how to use UIPageViewController. I added three outlets to my subclass of UIPageViewController which I intended to connect to the three views that the page view controller would control.
class MyPageViewController: UIPageViewController, UIPageViewControllerDataSource
{
#IBOutlet weak var redController : MyColorViewController!
#IBOutlet weak var greenController : MyColorViewController!
#IBOutlet weak var blueController : MyColorViewController!
//...
}
In my main storyboard, I created one instance of MyPageViewController and three instances of MyColorViewController.
But, for the life of me, I cannot figure out how to get the storyboard to connect the three outlets above to any of the color view controller instances.
I have tried both ctrl-dragging from the page view controller itself to each color view controller and from the page view controller's outlets in the inspector. Nothing works.
Suggestions?
You should do this by code. And not with IBOutlets.
First: set a storyboard ID to each of the UIViewControllers.
Second:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"blueViewController") as! UIViewController
And connect it to a property.
You do this for all three UIViewControllers.

Changing IBOutlet in UIViewController from UIWindow in Swift

I have a UIViewController with some IBOutlets. I also have a UIWindow that needs to access those IBOutlets in the first UIViewController. However, whenever I try to access it from my UIWindow, the variables are nil. Here's some of my code.
class ViewController: UIViewController {
#IBOutlet weak var playPauseLabel: UILabel!
#IBOutlet weak var playButton: UIButton!
#IBOutlet weak var pauseButton: UIButton!
func functionA() {
println(playPauseLabel)
println(playButton)
println(pauseButton)
}
}
class WindowClass: UIWindow {
func resetPlayPause() {
var vc = ViewController()
vc.functionA()
}
}
Now when I call func resetPlayPause() from WindowClass, all three IBOutlets are nil. I've read around on the other SO threads on this issue but haven't found any solutions. How can I access and modify those IBOutlets in ViewController from WindowClass?
The simple answer is that resetPlayPause() is constructing a new instance of ViewController each time it's called, and unless your ViewController has an initializer that loads itself from a storyboard or xib, none of your outlets will be connected. If your ViewController does have an initializer that does this, it won't connect its outlets until its view has been loaded. You can do this simply by calling vc.view in resetPlayPause() before you toggle the buttons.
The harder answer is that having your window access a view controller's ivars directly seems like a really bad idea. Either move your resetPlayPause() method somewhere other than in a window subclass, or have it call a method on ViewController that will toggle the buttons internally.
The answer is to use NSNotificationCenter. Works like a charm.

Accessing variables in other ViewControllers Swift

I have a user login to through a welcome screen in my app. Now I want that username to pass on to the other view controllers I have in the rest of the app, however i cannot figure out how. In old C i would have done an #import viewcontroller but that is not working.
I have one LoginVC where I set the username from a regular field
class LoginVC: UIViewController,UITextFieldDelegate {
#IBOutlet var txtUsername : UITextField!
now I want to show that txtUsername variable in my ActionVC as a regular var preferably in a function - however I have no idea how?
func accessOtherViewController(){
var userName = LoginVC(txtUsername)
}
var myCustomViewController: SomeViewController = SomeViewController(nibName: nil, bundle: nil)
var getThatValue = myTableView.someVariable
You can create a public var to access variables in other view controllers.
At the top of your viewcontroller class add public var name = "saucepan";
You should access this var in other view controllers if you only type the name of the var it will turn green (depending on your color scheme).

How to connect ViewController.swift to ViewController in Storyboard?

I made a new view controller in Storyboard and made a new .Swift file that inherits UIViewController. However, my viewDidLoad() is not being called.
What do I need to do to connect my view controller in my story board to my .swift code so viewDidLoad() is called?
I see there's this: How to connect storyboard to viewcontroller
However, in a default project, FirstViewController(storyboard) doesn't have FirstViewController in that box, it is empty, yet viewDidLoad() is still called. It doesn't make sense.
Choose your ViewController in the storyboard or scene list (mine is called Circuit).
Click on the Identity Inspector on the right
Select Custom Class > Class > Type name of your swift file.
DONE :)
You have your ViewControler created with some Objects in it (UILabel, UIButton, UIImage...)
1 - You need to link your ViewControler in your story board to your ViewController.swift , to do this follow the pictures
2 - In the class filed put the name of the ViewController class. With that you just linked your storyBoard view controller to your viewController.swift class
Class = ViewController.swift
3 - Now you need to cretae the variables you want to asign(UILabel, UIButton ... that you have in your storyboard): in this example:
class MovieDetailViewController: UIViewController, DetailView {
var presenter: MovieDetailPresenter!
var movie: Movie?
#IBOutlet weak var lblMovieYear: UILabel!
#IBOutlet weak var lblMovieTitle: UILabel!
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var lblMovieRating: UILabel!
#IBOutlet weak var lblMovieOverview: UILabel!
}
4 - To link the UILabel in the story board to your UILabel variable or your UIButton in your story board to your UIButton var, follow the next images
First select the view controller in the storyboard
Second select the parragraf icon in the right up corner ands clicked 'Assistant', it will open a screen of your ViewControler.swift
Now you just need to drag the variable to the corresponding object and you will be done.
Remember to do this with all variables, you will need to create a variable for each object you have in the storyboard
Connect storyboard and view controller
You should set ViewController in Class` field

Resources