What is the relationship between Storyboards and the Interface Builder? - ios

I just started learning XCode, objective-c, iOS, and all that. This is my first foray into app development. I'm not new to development, just iOS development and XCode.
So I'm going through a Udemy course that has me working with storyboards and I have some concern because every professional iOS developer I know uses something called Interface Builder which apparently removes the need for storyboards.
I've only just started, so I still have only a rough idea of what a storyboard even is....it seems to just be a graphical representation of a single page view. I don't know how it relates to this so-called Interface Builder and what their relationship is.
By going through this course learning with storyboards, am I being put on the wrong track? Or is this a useful beginning step before transitioning to the Interface Builder? Will using storyboards help me to work with that later? Am I wasting my time?

The Interface Builder refers to the part of Xcode that lets you view and edit Storyboards and .xib files (it automatically opens when you click on such a file).
A .xib (or 'nib') file is a representation of a single logical view in you application (on iOS, typically a UIViewController with a number of views, such as a UIScrollView and a UINavigationBar).
A storyboard is a collection of such views, and can be used to build transitions from views to other views, among other things.
I recommend reading Apple's Documentation on storyboards to get an idea of what they can do for you.

...
Interface Builder which apparently removes the need for storyboards.
...
Actually, storyboard is a concept within Interface Builder.
It's a visual representation of the entire app flow.
I think all you need is a quick-read through the Apple Interface Builder Doc.
In basic understanding, IB is a drag-drop area to visually create your views.
To quote:
You create your app’s user interface in Interface Builder. Select a
user interface file in the project navigator, and the file’s contents
open in Interface Builder in the editor area of the workspace window.
A user interface file has the filename extension .storyboard or .xib.
Logical Example: Instead of programmatically coding a UIButton and setting it's frame or constraints, you go to the Interface Builder, select a UIButton object and place it where you would want it to go. You will also specify what the object name and what method it responds to. (but this will need the object name and method name to be defined in the respective class's .m or .h file that the view is associated with)
Interface Builder can be either XIB/nib or Storyboard. Latter of which is the more recent (and recommended) method provided by Apple.
Using a storyboard, you have one single file, a .storyboard file that will represent the entire app flow.
An app can have multiple screens/views and so a storyboard will basically represent multiple UIViewControllers, each of which will be tied to a particular class.
For example, in this storyboard, you can visually see (assumptions from here on) that you have, say, 5 screens in the entire app:
Screen 1 begins with maybe a UINavigationController
Screen 2 is the root view of this UINavigationController, say, LoginVC (tied to LoginVC.m and LoginVC.h).
A button on LoginVC takes you to, say, SignUpVC (tied to SignUpVC.m and SignUpVC.h)
Another button on LoginVC takes you to, say, ProfileVC (tied to ProfileVC.m and ProfileVC.h)
Screen 3 is SignUpVC
A button takes you back to LoginVC
Screen 4 is ProfileVC
A button takes you to SettingsVC (tied to SettingsVC.m and SettingsVC.h)
A button logs you out and takes you back to LoginVC
Screen 5 is SettingsVC
Q.
By going through this course learning with storyboards, am I being put on the wrong track?
A.
No, absolutely not. You're going in the right direction.
However, i think knowing the former XIB/nib method is worth your time as well.
Plus, programmatically creating UIViews is highly recommended.
Q.
...is this a useful beginning step before transitioning to the Interface Builder?
A.
It's already getting you acquainted with the Interface Builder so there won't really be much "transitioning" required.
Q.
Will using storyboards help me to work with that later? Am I wasting my time?
A.
Yes, unless you work in a team under version control, in which case, XIB still looks good.
So what's XIB?
It's still within the Interface Builder scope...
Break a storyboard into it's individual views and you have multiple files (.xib files) that represent a UIView or UIViewController for a single class. (hence helps when you work in a team under version control)
So now... instead of having one .storyboard, you will have multiple .xib files that will be associated to all those classes that (you deem) needed a visual representation.
Links:
Storyboard
XIB

Storyboard :
Has a nice UI designer , WYSIWYG , drag, resize design editor, that generates code and sync with manual code changes.
SwiftUI:
Code is the single source of truth. No Designer. Lots of hard coding

Related

Wrapping my mind around Objects in iOS

I'm having trouble understanding the idea of objects. From what I've read, they're instances of a class. When learning swift, they're quite easy to understand. Simply create a class and create an instance of it, and from there, you can modify it's properties and call its methods:
class ExampleClass {
let ExampleProperty = "rabbit"
}
let exampleInstance = ExampleClass()
But I don't see how that translates when using iOS, since I haven't seen any objects being created explicitly yet:
var example = Wss()
So my questions are:
Are things like buttons, labels, and sliders objects?
-If so, where's the "code" behind them? Why do buttons, labels, etc. display even before they're connected through outlets and actions to the View Controller? Is there a hidden "var thisButton = ThisViewController()" embedded into each of those sliders and buttons?
If my assumptions are wrong, can someone explain to me how objects work?
"Is there a hidden "var thisButton = ThisViewController()" embedded into each of those sliders and buttons?"
No, and this is exactly where interface builder excels. Much of Xcode's modern Interface Builder comes from NeXTSTEP. When you drag out a new UI component like NSButton and place it on your story board, Xcode is instantiating a new object of the NSButton class for you. When you save your file, Xcode serializes all the objects of your story board into a .nib file. At the time when this was invented, it was quite revolutionary, all made possible because of the dynamism of Objective C. It made GUI programming much simpler and dynamic. Every object in your story board is aware of its class. For example, when you instantiate a new NSButton, you can open the inspector and see for yourself that its class is NSButton. When you add custom views to your application, they keep track of their class in the same way. Whenever a nib file is loaded, these views are instantiated from their classes. You might have noticed that you never override the initializer of your views. Instead, you override methods like awakeFromNib. This is because there's a lot of behind the scenes work being done for you, from the time the object is first instantiated, to the time. During this time IBOutlets and IBActions are bound for you.
Competitors tried to make similar interface building applications, but they ultimately resorted to doing code generation behind the scenes. In these systems, when you saved your interface file, the program would generate a source file that contains code that instructs how to instantiate these objects anew whenever the interface is loaded. However, it proved significantly more complex a task then just serializing the objects, so these systems were error prone, and significantly harder to debug (because you'd be trying to debug machine generated source files).
Answering your questions:
Yes. Your objects are just being created from a NIB, or Storyboard. So the NIB, or Storyboard, will create those visual (UI) elements for you, which you can then be accessed via the IBOutlets
Your assumptions, are not completely wrong as in, there is in fact something allocating those objects for you. The NIB, or Storyboard, just describe a way for those objects to be created. Also some other customisations, like frames, colors, etc.
More about how this ties up can be found here.
Building on Alexander's answer:
UIView objects have a method init(frame:) that lets you create a new UIView object with a specified frame.
Other UIView subclasses might have init methods that take additional parameters.
UIView objects also support an init method init(coder:) that knows how to create an object from a stream of stored data. This is known as "deserializing" the object, or converting it from a byte-stream back into a running object.
When you build an object in a Storyboard or XIB file in Interface Builder, the system serializes the object into a byte stream and saves it into your Storyboard/XIB.
Then when you invoke the storyboard scene/XIB, the system reads the data stream and uses it to recreate (deserialize) the objects that are described in the storyboard/XIB.
The effect is essentially the same as if you wrote a bunch of code that created and configured all your views, but instead of writing all that code you are able to build your interface in Interface Builder, which is faster and easier to create, and MUCH faster and easier to update and maintain than a bunch of custom code.
But I don't see how that translates when using iOS, since I haven't seen any objects being created explicitly yet
There's no difference between the objects in iOS and what you understand objects to be. Objects are instances of a class. What you need to understand is that your own code is not the only place where objects can be created, and your own code will often interact with objects created outside your code. Here's a simple example:
let defaults = NSUserDefaults.standardUserDefaults()
Here defaults gets a reference to a user defaults object that the system provides. You never need to instantiate NSUserDefaults yourself.
Are things like buttons, labels, and sliders objects?
Yes, those are instances of UIButton, UILabel, and UISlider, respectively.
If so, where's the "code" behind them?
It's in the UIKit framework. You don't get to see the source code for those classes, but you can still use them by linking the framework into your app.
Why do buttons, labels, etc. display even before they're connected through outlets and actions to the View Controller?
You're talking about storyboards here. When you set up a view in Xcode's storyboard editor, the data that's stored in the storyboard file is essentially an archive containing serialized objects. When a view controller is instantiated from a storyboard, the objects in the storyboard are recreated from that data and then connected to the view controller's outlets. You can start this process yourself by instantiating a new view controller like this:
let storyboard = UIStoryboard(name: "MyStoryboard", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "MyViewController")
You don't usually need to do that, though, because the segues in your storyboard provide for transitioning between scenes, including creating the view controller that's the destination of a given segue.

In swift, why do I HAVE to use IBaction or IBOutlet to communicate between code and UI?

I'm new to programming, and I'm trying to understand this concept in Swift IOS. What are the benefits of HAVING to use IBaction and IBoutlet to connect things like UIButtons and UILabels to my code?
Why don't they just let us set UI objects equal to a name like button1 or label1 so we can use those names to call and mutate them in my code?
You don't. IBAction and IBOutlet is how storyboard and xib files created with Interface Builder (IB) link to the implementation files when unarchiving the XML dictionaries of the nibs. However, creating views and controllers with layouts in code is entirely permitted and even a common pattern for project management in teams.
Personally, I do like using Interface Builder for the visual aspect of laying out my views, and it helps reduce the size of my controller files because it allows me to put my layout and color settings into Storyboards and xibs. But, some developers will argue this is actually a drawback, since it obfuscates some of the functionality of your controllers from the uninitiated. There are strong arguments for avoiding the use of Interface Builder when working in teams, but it really boils down to strategy and preference.
They're just tags Xcode uses to link the code and the storyboard / XIB. Functionally they do nothing. They help you as the developer to know what is / isn't / can / can't be connected between the visual representation of your UI and the code driving it.

loadview VS interface builder

Since I've seen many other IOS projects written in obj-C, I found that many of them do not use interface builder or storyboard file. It's hard to see what's going on. And I've known that loadview method should do the things similarly to drag and drop objects in IB. So what is the difference between loadview method and doing some dragging objects in interface builder?
Well, you don't have AutoLayout (unless you use hard code to constraints too) and Size Classes without interface builder.
Working with IB is much less coding and more clarity.
If you add a Label to IB then the IB is responsible to release that object. And it's added to the view of course so you don't have to.
I would never go without IB now and would recommend to do so for other devs.
I use Size Classes + AutoLayout and all my screens looks good on every device plus that iOS9 is coming out: I have multiple screens auto enabled because I used Size Classes. App works without maintenance for many years..
Simple difference between IB and loadView
IB:
All u can do is drag and drop things without having any code written.
loadView:
It is first viewCycle method which calls on loading any view of corresponding viewcotroller, You should do all your stuff programmatically here. like adding subviews to your view. and adding constraints etc.
Thanks

iOS: create a XIB from a UIView

I have lots of Views in old projects that I have layed out in code, using absolute positioning. That code is really hard to maintain. I'd like to port the code to using interface builder, but I'd have to layout every view again by hand.
Is it possible to programmatically create a XIB file from an existing UIView (which has been created programmatically)? I have searched the docs but can't find anything.
XIBs are essentially XML files, I guess that if you inspect a few you'd understand the format for different controls, but that would need a lot of manual reading, writing & testing to complete for all views. Probably a better plan would be to start slowly migrating to IB-made views.
Yes, it's possible; however, the thing is, you need to set all essential controls and properties of your xib. You won't be able to see its actual look and feel unless you have executed the project in your simulator or on an actual device (that means hard code everything).
You would use loadview in initializing your xib. Here's a bit of it:
- (void)loadview{
// set your view, screen size, and other properties of your xib
}

additional NIB for view controller in tabbed app

{Xcode 4.2, deployment target iOS4.3, not storyboard, using ARC}
I started with a tabbed application template & chose the universal platform, which nicely gives me view controller classes & NIB files for an iPhone (ClassName_iPhone.xib) & an iPad (ClassName_iPad.xib) for 2 tabs, with an if statement in the AppDelegate to determine which to run - exactly how I wanted it set up.
I wanted to add a 3rd & 4th tabs, so starting with the 3rd tab (doing 1 at a time) I created a new UIViewController subclass. As it doesn't give the option to create both NIBs at once, I selected "Targeted for iPad", & had intended to create the iPhone NIB manually. I added a "_iPad" suffix to the created NIB file, then I created a user interface view NIB file to which I added the "_iPhone" suffix. I then set up the code for the new view controller in the AppDelegate implementation file to include the 3rd view controller & tab, & I used the other view controller classes as a guide to set up the new class's code.
For the 3rd _iPhone NIB, I dragged a view object from the objects library onto the canvas, & set it up as per the other 2 _iPhone NIBs. But when I went to connect the outlets, there is no view outlet in the referencing outlets of the connections panel to connect with, which I thought there should be. At this point I suspected something was wrong.
I tried running it in the simulator, in iPad mode it works fine (all 3 tabs are clickable). But in iPhone mode clicking the 3rd tab crashes it with a "SIGABRT" on thread 1. It's obvious what I did didn't work. I don't see anything in the output window that gives me any clues.
Being a newbie to obj-c, so not being too sure of the problem, I would have thought that I either:
have used the wrong user interface template (view)
should have used a view controller object from the object library
(not a view)
or that I should have declared some outlets in my view controller
class files.
But if I should have done either of the latter 2, then my question would be why does the iPad NIB work then, when it clearly has a view object in the NIB & no outlets declared in the class files (same with the other 2 view controllers for both devices)?
Does the UITabView class somehow have outlets pre-declared within it for the first 2 tabs? But that still doesn't explain why the _iPad NIB works.
As usual, any help & advice much appreciated, & if there's a link to an explanation somewhere that I've missed, please show me, because I'm happy to do the research.
If what I've done wrong here is not determinable, then I guess ultimately what I'm asking is a clue to how best to create the second NIB file for iPhone to mesh with the class created with iPad NIB.
Sorry to answer my own question but with further searching I found this answer that was the solution, although not quite the whole story. So I thought to put what I did in an asnwer so others can refer to it.
As Piotr Czapla explains in the linked answer, for some reason Xcode doesn't populate the connectionRecords data, as you can see by my first red arrow. Having a look at the view controller that works (where second red arrow is), that's what the data should look like. So the answer is to cut the data & paste it into the NIB file, or type it. You can do this in Xcode by right-clicking the NIB file in the project navigatior & then Open As > Source Code, which is what you see in my screenshots.
The bit I want to add to Piotr Czapla's explanation though is the destination reference pointed to by the second red arrow might not be correct for the NIB file you're pasting into (mine wasn't) & Xcode might not let you go back into IB mode. If so, you need to get the correct reference from the IBUIView class within your NIB file, as pointed to by the third red arrow. Once I copied that reference to my destination reference ref=, as shown by the fourth red arrow, all was ok & the problem was solved. I could then go back into IB mode (right click, Open As > Interface Builder - iOS) & the view works in the simulator.

Resources