What is a StoryBoard ID and how can I use this? - xcode

I am new to IOS developing and recently started in Xcode 4.5. I saw for every viewController that i could set some identity variables including the storyboard ID. What is this, and how can I use it?
I started searching on stackoverflow and couldn't find any explanation for it.
I assumed it's not just some stupid label that I can set to remember my controller right? What does it do?

The storyboard ID is a String field that you can use to create a new ViewController based on that storyboard ViewController. An example use would be from any ViewController:
//Maybe make a button that when clicked calls this method
- (IBAction)buttonPressed:(id)sender
{
MyCustomViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
This will create a MyCustomViewController based on the storyboard ViewController you named "MyViewController" and present it above your current View Controller
And if you are in your app delegate you could use
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
Edit: Swift
#IBAction func buttonPressed(sender: AnyObject) {
let vc = storyboard?.instantiateViewControllerWithIdentifier("MyViewController") as MyCustomViewController
presentViewController(vc, animated: true, completion: nil)
}
Edit for Swift >= 3:
#IBAction func buttonPressed(sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
and
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)

To add to Eric's answer and update it for Xcode 8 and Swift 3:
A storyboard ID does exactly what the name implies: it identifies. Just that it identifies a view controller in a storyboard file. It is how the storyboard knows which view controller is which.
Now, don't be confused by the name. A storyboard ID doesn't identify a 'storyboard'. A storyboard, according to Apple's documentation, 'represents the view controllers for all or part of your app’s user interface.' So, when you have something like the picture below, you have a storyboard called Main.storyboard which has two view controllers, each of which could be given a storyboard ID (their ID in the storyboard).
You can use a view controller's storyboard ID to instantiate and return that view controller. You can then go ahead to manipulate and present it however you want. To use Eric's example, say you want to present a view controller with identifier 'MyViewController' when a button is pressed, you would do it this way:
#IBAction func buttonPressed(sender: Any) {
// Here is where we create an instance of our view controller. instantiateViewController(withIdentifier:) will create an instance of the view controller every time it is called. That means you could create another instance when another button is pressed, for example.
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
Please take note of changes in syntax.

Related

How to create modal slide-out window in Mac OS?

How can I create modal slide-out window/view "in-window" in Xcode like in these screenshot?
I've tried create new Window controller with "Authentication panel style" animation but then I'm receiving only Xcode crashes.
That kind of modal window is called a Sheet. It's very easy to get this behavior with a Storyboard segue, or programmatically with an NSViewController subclass. The example below is just a blank OS X Cocoa application as created by Xcode. (I chose Swift as the language, but it will work the same way with Objective-C.)
The only things I added to the storyboard was a second View Controller for the sheet view, and a label and pushbutton on each view.
Displaying The Sheet View With A Storyboard Segue
With the Sheet View controller selected and the Connections Inspector tab displayed, connect "Presenting Segues - sheet" to the "Display Sheet" button.
Connect "Received Actions - dismissController:" to the "Close Sheet" button.
That's it! There's no code needed to make this example work; just build and run.
Displaying The Sheet View Programmatically
Note that Xcode creates the default project with two custom class files. In the Storyboard, AppDelegate.swift is represented in the Application scene:
We don't need to use the AppDelegate for this example, but you could use it for interaction with the Main Menu, or other things.
The custom ViewController.swift custom class will be used to present the sheet. It is represented in the View Controller scene:
To instantiate the Sheet View Controller programmatically, it needs a Storyboard ID. Here, we'll give it the ID "SheetViewController". Note that it's still a plain NSViewController; we don't need to make it a custom class for this example, but your application might want to:
Displaying the ViewController.swift file in the assistant editor, Ctrl-drag a connection from the "Display Sheet" button into the custom class. This will create stub code for an #IBAction function we'll name "displaySheet":
In the ViewController.swift file, we'll implement the Sheet View Controller as a lazy var. It will get instantiated only once, the first time it's accessed. That will happen the first time the displaySheet function is called.
// ViewController.swift
import Cocoa
class ViewController: NSViewController {
lazy var sheetViewController: NSViewController = {
return self.storyboard!.instantiateControllerWithIdentifier("SheetViewController")
as! NSViewController
}()
#IBAction func displaySheet(sender: AnyObject) {
self.presentViewControllerAsSheet(sheetViewController)
}
}
Swift 4 version:
// ViewController.swift
import Cocoa
class ViewController: NSViewController {
lazy var sheetViewController: NSViewController = {
return self.storyboard!.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "SheetViewController"))
as! NSViewController
}()
#IBAction func displaySheet(sender: AnyObject) {
self.presentViewControllerAsSheet(sheetViewController)
}
}
As in the first example, the "Close Sheet" button is connected to the "dismissController:" action on the Sheet View Controller. Alternatively, you could call that function programmatically from your ViewController class:
self.dismissController(sheetViewController)
For more information, refer to the Apple "Sheets Programming Topics" document:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Sheets/Sheets.html
Objective-C version:
- (IBAction)displaySheet:(id)sender {
NSStoryboard *storyboard = [NSStoryboard storyboardWithName:#"Main" bundle: nil];
NSViewController * vc = [storyboard instantiateControllerWithIdentifier:#"SheetViewController"];
[self presentViewControllerAsSheet:vc];
}

Could not cast value of type UITabBarController to FirstViewController (xCode 6.4)

I'm trying to pass variables from a view controller to another one. First, there's a connection screen. When the infos are verified, then I pass the username and other data to the whole program (that has a tab bar controller).
Here is the code. I'm using Xcode 6.4. In the previous version, the page would open but the variables didn't pass. Now it just gives me the above error.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "lienConnecte") {
let nav = segue.destinationViewController as! UITabBarController // this line was just an attempt to find a solution
let vueFil = segue.destinationViewController as! FirstViewController
vueFil.utilisateur = utilisateur
}
}
Of course I know that in the storyboard, the segue points to the tab bar controller (because I need it afterwards), but I want the values to be passed to the FirstControllerView
Found the solution, for those who will see this post:
let tabBarController = segue.destinationViewController as! UITabBarController
let vueFil = tabBarController.viewControllers![0] as! FirstViewController
You cannot turn one thing into another, like some sort of magician, by saying as. You have to get a reference to the actual thing you're after. If there's a FirstViewController that is one of the child view controllers of the UITabBarController, then first get a reference to the UITabBarController (which you already know how to do), and then obtain its viewControllers property — those are its children, and you can, from there, get the one you want by its index number.
Your tab view controller is a container view controller that owns child view controllers. Presumably, FirstViewController is one of these child view controllers. Therefore, your tab view controller and your FirstViewController are different instances. You can access a tab bar's children with the viewControllers property:
let firstVC = tabVC.viewControllers?.first
// firstVC should be your FirstViewController

Presenting a navigation controller on a View Controller from storyboard

In my app i have a storyboard which has initial view controller as X and then i have a navigation controller which has couple of view controllers attached with it through segue but there is no connection between ViewController x and this navigation controller.
Now based on a button tap in View controller x i want to present this navigation controller.
I am doing this :
func showDashBoard()
{
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let next = storyBoard.instantiateViewControllerWithIdentifier("navigation") as! EBNavigationController
self.presentViewController(next, animated: true, completion: nil)
}
So the navigation view is getting presented with the root view controller but its not showing me animation and also i am getting a warning "Attempt to present on whose view is not in the window hierarchy!
"
Can some one please help me in figuring out what is the best way to do this.
Thanks,
The animation problem can be fixed using next.modalPresentationStyle and next.modalTransitionStyle. Lookup the enums for the possible values and give it the one you want.
You usually get the "Attempt to present on whose view is not in the window hierarchy!" errors when you are calling this function before the view is fully loaded. For instance if you call it in the viewDidLoad method. You should call it only after viewDidAppear is called.

Using Swift, I want to add information into a screen but after the first use I do not want to see it again

Ok so here is my question.
I want to have a screen pop up right after my LaunchScreen exits and i want to be able to add information into it, however once I add that information into it, I do not want to see that screen again.
I will be using storyboard, swift and CoreData and Xcode 6.3 if that helps.
Thanks in advanece
NSUserDefaults is a really quick way of storing (small amounts of) data.
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(true, forKey: "hasSeenStartup")
if(defaults.boolForKey("hasSeenStartup")){
println("Don't show")
}
First you will need to define a set of userDefaults, easiest is standardUserDefaults()
We can set a boolean value to a key (after we showed the popup screen) using setBool() this takes 2 parameters, the first is the boolean value, the second is a key for the value.
When the users launches the app, you will need to get the boolean value for the key. If the user already has seen the popup (it’s boolean value for hasSeenStartup will be set to true) you can skip the popup and show them the other viewController
EDIT:
Since your question seems to focus on showing the new view controller rather than saving the data. Here is some code on how to show a new view controller.
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc: NewViewControllerClass = storyboard.instantiateViewControllerWithIdentifier(“newViewController") as! NewViewControllerClass
self.presentViewController(vc, animated: true, completion: nil)
To use this code you will need to change the:
Storyboard name to the name of your storyboard (defaults to “Main”)
Set the class of the viewController by replacing NewViewControllerClass with the class of (obviously) your new viewController.
Change the newViewController with the Identifier
You can than use this code to present the new ViewController. Present this viewController if your Core Data has info saved about the user and thus if the user has seen the initial screen.
I would advice to retrieve the Core Data inside the ViewDidAppear method inside your FirstViewController.
override func viewDidAppear(animated: Bool) {
if (check to see if core data is not empty){
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc: NewViewControllerClass = storyboard.instantiateViewControllerWithIdentifier(“newViewController") as! NewViewControllerClass
self.presentViewController(vc, animated: true, completion: nil)
}
}

Split View Controller: How to connect Master View Controller to Detail View Controller?

(Xcode6-beta3, Swift, iOS8, iPad)
In an iPad split-view controller, how do I link the Master View Controller to the Detail View Controller?
In other words, when the user taps on an item on the left, how do I change the view on the right?
I know that in didSelectRowAtIndexPath, I need to call a method... but how do I call a method in the Detail View Controller from the Master View Controller?
Example
Imagine an app to display information on different types of cheeses. We begin by dragging a split-view controller onto the storyboard. A table of items in the master view on the left is set up to read as follows.
Swiss
Cheddar
Brie
On the right, there is simply a Web View inside of the detail view controller, named cheeseViewController. Therein, HTML documents about the selected cheese will be displayed.
An IBOutlet is wired from the web view into cheeseViewController, and a method named 'changeCheese' is set up in the Detail View Controller delegate to swap out the document.
How can I make a tap on "Cheddar" change the information in the detail view?
EDIT: Do I have to modify my AppDelegate.swift file? Using a Master-Detail template, I tried the following, with no luck:
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
// Override point for customization after application launch.
let splitViewController = self.window!.rootViewController as UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
splitViewController.delegate = navigationController.topViewController as Paragraph
return true
}
I hope I understood your problem correctly: You would like to show the detail information of a selected cheese in your Detailview.
When you create a new Master-Detail-View application in XCode 6 Beta 3, there will be a variable called "detailItem" in your DetailViewController.Swift file:
var detailItem: AnyObject? {
didSet{
self.configureView()
}
You set this detailItem in your MasterViewController.Swift file in the following function:
override func prepareForSegue(segue: UIStoryBoardSegue, sender: AnyObject?){
if segue.identifier == "yourSegueIdentifier" {
let indexPath = self.tableView.indexPathForSelectedRow()
let cheeese = yourCheeseArrayWithDetailInformation[indexPath.row]
(segue.destinationViewController as DetailViewController).detailItem = cheeese
}
}
(Assuming, that you have linked the views with a segue with the identifier: "yourSegueIdentifier" and an array of detailinfo called "yourCheeseArrayWithDetailInformation")
The above mentioned function "configureView" in the DetailView can now access your detailItem, which contains the contents of "cheeese"
I hope this helps you.
Why don't you just post a Notification from didSelectRowAtIndexPath in your Master and add an observer in your Detail View most likely inside your viewDidLoad. You also can handle the selector within the observer method with closure.
If you didn't create a master-detail app (so you have no detailItem), you might use this:
if let
mySplitViewController = splitViewController,
detailView = mySplitViewController.childViewControllers.last as? DetailViewController {
// do something with it
}

Resources