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.
Related
So all my controller's are done programmatically to avoid segues and that sort of complicated stuff.
I have a viewcontroller (Call it ProfileViewController) that downloads data from the network.
So I have a method in ProfileViewController that instantiates a single storyboard file with a static tableview with cells that have textfields in them. Here is the method:
ProfileViewController:
func userSelectedUpdateProfile() {
// Obtain reference to the only storyboard file named EditProfileSB
let storyboard = UIStoryboard(name: "EditProfileSB", bundle: nil)
// Since the Tableview is embedded in a navigation controller (with ID set to "navigationID")
if let parentNavigationController = storyboard.instantiateViewController(withIdentifier: "navigationID") as? UINavigationController {
// Now find the embedded TableViewController and access it's properties to pass to.
if let childEditController = parentNavigationController.topViewController as? EditProfileTableViewController {
// ! Error here ! Found nil when doing this.
childEditController.nameTextfield.text = "Passed this to static cell"
}
present(parentNavigationController, animated: true, completion: nil)
}
}
So the code itself is self-explanatory to what I am trying to achieve here. The TableView is embedded in a Navigation (done on storyboard with "Editor > Embed In") so on the 2nd nested if let statement I am now checking to find that Edit controller and access its properties (nameTextfield).
I get a crash when I attempt to access the nameTextField.text property. This textfield is set using storyboard. Here is that EditProfileTableViewController:
class EditProfileTableViewController: UITableViewController {
#IBOutlet weak var nameTextfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
// Other methods ...
}
Here is the storyboard flow layout.
Am I missing something here? I keep getting a crash on childEditController.nameTextfield.text = "Passed this to static cell" on the method userSelectedUpdateProfile().
If your View Controller still not call viewDidLoad().
your textfield is not create.
#IBOutlet weak var nameTextfield: UITextField!
you can see it's attribute is weak here.
Try create a value and pass text to the value. Then in viewDidLoad(), you can set the value to your textField
I have two viewControllers in the storyboard, a ViewController (root) and a TableViewController, that are linked by a push segue.
The TableViewController acts as a setting page of the app and multiple UIControls such as UISegmentedControl and UISwitch are put in it. These UIControls are linked to the TableViewController via IBOutlets.
#IBOutlet weak var mySegmentedControl: UISegmentedControl!
#IBOutlet weak var mySwitch: UISwitch!
However, when I call these UIControls in the ViewController by:
let tableView: TableViewController = TableViewController.init(nibName: nil, bundle: nil)
if tableView.mySwitch.isOn {
//perform actions
}
Error pops up at the if-statment:
fatal error: unexpectedly found nil while unwrapping an Optional value
I thought it was because the TableViewController has not been loaded when the UIControls are being called, thus I have tried calling the viewDidLoad() of tableView first, but the error still remains.
What should I do? Appreciate any suggestions.
You do not directly call viewDidLoad, this is done by UIKit after the view is being loaded. And the view is loaded when the view needs to be displayed.
If you need to access the outlets before, you can force loading by
tableView.loadViewIfNeeded()
But remember:
Maybe it's better to do the outlet stuff inside viewDidLoad of the involved controller, and not from outside.
You should not name the controller variable tableView. That name suggest to be a view and not a controller. Better name it tableViewCtrl or so.
I'm having an issue with my current project.
At the beginning my main focus was to create a overlay button in a TableViewController but i saw that it was more simple to use a ViewController and set on it a tableView :
class MemoList : UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
#datasource is linked manually in the StoryBoard
...
}
}
When this View Controller is set as the initial controller, everything work fine but in my case, when the projet is rooted by a navigation controller, the tableview appears to be nil in the context of the 'Memolist' (when pushing on it).
Do you have any idea about this issue ? And how can I solve it ?
Thanks,
For me the problem was that I used
present(myViewController, animated: true, completion: nil)
After I tried to use segue and
performSegue(withIdentifier: "myIdentifier", sender: self)
it worked properly and tableView was no longer nil.
Why did I have this problem:
When you use present(), you initialise the View Controller from code and it doesn't watch on your Storyboard. When you use segues, it uses the Storyboard and of course see all you did in your Interface Builder
You also can:
UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerId")
This creates view controller from Storyboard, so that tableView is initialized now
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.
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