I am new to mac dev, xcode and IB etc. I understand how to build simple applications and basic dragging & dropping in IB, but i don't know what and where does IB do with the objects.
the second questions is how to write a MVC without using IB?
When you connect two objects in IB with IBOutlet or IBAction it creates some special tags in XIB (which is XML).
When bundle (update: sorry, it's not a bundle, but UINib) reads NIB (which is compiled XIB) it looks for such tags and objects they are refer. After that:
For outlets it uses KVC (Key-Value Coding) to set corresponding property of receiving object.
For actions it calls addTarget:action:forControlEvents: on control object.
You can build iPhone app of any complexity without IB by creating and setting up objects in your code, but in most cases it's just not wise.
Further reading - Resource Programming Guide
As far as I know, the XIB files from IB are some kind of archives with your objects and their properties stored in them. When you send -initWithNibName, the objects are unarchived. So basically, you could - if you knew how - create your own XIB files and they should work. Note that loading a UIViewController without specifying a XIB file, an XIB file with the same name as your class is loaded. See the Wikipedia article.
To your second question: You can create any object you add using IB programmatically. Typically, these are UIView subclasses that you initialize using initWithFrame:. Then you set the properties you need. Finally, you add them to your view using addSubview.
IBActions are basically Target/Action Pairs. If you for instance add UIBarButtonItem, you use initWithBarButtonSystemItem:target:action:. Setting the action is equal to setting an IBAction connection in IB.
You should be able to create any User Interface you want programmatically, however it's usually a lot of work compared to when using IB.
Related
What happens when we connect the xib objects with class outlets? How to do such connection from code without wiring them in interface builder?
IBOutlets are just instance variables or properties that get set by the nib loading machinery when the nib is loaded at runtime. There's nothing particularly special about them. The trick in setting them up programmatically is finding the object(s) in the nib that you want to connect. If you load the nib using -[NSBundle loadNibNamed:owner:options:] you get an NSArray back containing all the top level objects in the nib (i.e. the objects at the top of the hierarchy in the Document Outline Inspector in IB). You can iterate through these and their subviews to find the objects you want to hook up IBOutlets. Take a look at the Loading Nib Files Programmatically section of the Resource Programming Guide.
I'm trying to keep things organized and create hierarchy of views for my app.
So for instance I want to create a custom view to display some text, another custom view to display progress and then use all those views in the main view created with View-Based Application template.
I know how to create it programmatically - you create UIView subclass, implement drawRect method, place an empty UIView in Interface Builder and chance it's Class to my custom class. My problem is that I want to create those custom view's in Interface Builder instead programmatically.
So far I've created UIViewController controller with XIB file and in viewDidLoad method of view controller from the template I create that custom view controller instance and add it's view as a subview of that empty UIView added in Interface Builder (the same you would change Class in programmatic approach).
It works, but it's more of a hack for me and it's hard for me to believe that there isn't a better method where I could add those custom views in interface builder without having to implement viewDidLoad method and create controllers and add their views inside of that method.
This was originally a comment in Ratinho's thread, but grew too large.
Although my own experience concurs with everything mentioned here and above, there are some things that might ease your pain, or at least make things feel a little less hack-ish.
Derive all of your custom UIView classes from a common class, say EmbeddableView. Wrap all of the initWithCoder logic in this base class, using the Class identity (or an overloadable method) to determine the NIB to initialize from. This is still a hack, but your at least formalizing the interface rules and hiding the machinery.
Additionally, you could further enhance your Interface Builder experience by using "micro controller" classes that pair with your custom views to handle their delegate/action methods and bridge the gap with the main UIViewController through it's own delegation protocol. All of this can be wired together using connectors within Interface Builder.
The underlying UIViewController only needs to implement enough functionality to satisfy the "micro controller" delegation pattern.
You already have the details for adding the custom views by changing the class name and handling the nib loading. The "micro controllers" (if used) can just be NSObject derived classes added to the NIB as suggested here.
Although I've done all of these steps in isolated cases, I've never taken it all the way to this sort of formal solution, but with some planning it should be fairly reliable and robust.
For this to work, you have to create a plug-in for Interface Builder that uses your custom control's class. As soon as you create and install your plug-in, you will be able to add by drag and drop, instances of your view onto another window or view in Interface Builder. To learn about creating IB Plugins, see the Interface Builder Plug-In Programming Guide and the chapter on creating your own IB Palette controls from Aaron Hillegass's book, Cocoa Programming for Mac OS X.
Here is the link to the original author of the accepted answer to a similar question.
Maybe i didnt understand u?
you have library in the Interface builder u can move every component u want and place it on your view. (u can add another view by adding UIView and change its class name in the 4th tab).
then u declare vars with IBOutlet and connect them from the 2nd tab of ur file's owners to their components...another question?
Unfortunately, you can't do what you want to do with UIKit. IB Plugins only work for OS X, and Apple explicitly doesn't allow them for use with iOS development. Something to do with them not being static libraries. Who knows, they may change this someday, but I wouldn't hold your breath.
There's some way to declare Strings and Variables in Obj-C for iPhone?
I mean, i want to display the data input on textfield in 01.xib on 02.xib label's.
How can i do that?
Thanks!
You'll need a class that communicates between the two, getting the relevant value from the textfield in your first XIB and setting it as the value of the label in your second. This is quite a basic sort of operation, so I guess that hints and keywords are the best way forward.
Your first XIB will have a class nominated as 'File's Owner'. That should match a class in your Xcode project. Things defined in Interface Builder access one another through outlets. So you at least need an outlet from the owner to the text field. You may also want it to be the text field's delegate, depending on what means you're using to decide to move from the one NIB to the other.
Much of the time, iPhone people set the File Owner of a NIB or XIB (the terms are interchangeable) to be a subclass of UIViewController. So probably you'll have an outlet to both the text field and the view controller that owns the second XIB. General program flow will be that, upon the relevant event, it reads the value of the text field, communicates it to the other XIB and then presents the other XIB.
Similarly, the second XIB's owner (another UIViewController, probably) will have an outlet to the label and will use that to set the value.
Interface Builder is for drawing out the interface and connecting objects to define who knows about who. Xcode is for writing actual code. If you stick to model-view-controller then Interface Builder helps you draw the view, then you code up the controller and model for yourself. UIViewController subclasses are, as the name suggests, meant to be in the controller layer. Objective-C is another language derived from C (which, unlike C++ or C# is a strict superset) with many of the same ideas about semantics.
It's difficult to elaborate on any of that without elaborating on all of it and writing about 20 pages.
Two view controllers are the owner of the two xib file. They should have property declaration for UITextField and UILabel.
(02.xib'x label).text = (01.xib's textfield).text;
This should be a pretty easy fix, but I haven't figured out from reading the Apple documentation or other SO questions how to do this simple switch from creating my Interface programmatically to using Interface Builder.
I am basing my code around this framework:
http://www.pushplay.net/blog_detail.php?id=27
The only difference is that, where each View is programmatically created (View01.m, View02.m) in ViewDidLoad, I instead want to import from a nib (while still using this framework) for each view (each view has a unique IB design).
Thanks for the help.
Think of IB as an Object Creator and not a code generator. That really helps. What IB does is actually create instances of objects as they are dragged on to the desktop/view/XIB window. It then allows you to start creating various connections (with a control drag on the mouse) from one object to another object. You then instantiate the entire XIB by unarchiving it from your bundle. This is highly automatic and reading up on UIViewController should move you along a bit. Look at:
initWithNibName:bundle:
You basically have two types of connections:
Outlet: This is how you teach one object about the existence of another object. For example, you might have a controller object that needs access to a button. You create an outlet (either in XCode Text Edit in the controller.h file/property area or in IB by adding an outlet) in your controller and then control-click-drag from the outlet to the button.
Actions: This is how you trigger an event on one object to call a method on another object. Actions will have a prototype of:
- (IBAction) someMethod:(id) sender;
I think the ":(id) sender" is optional if your method does not need a link to the object causing the event.
Within IB, you can arrange objects and set various attributes like size, color, position, target/actions, user interactions, Files Owner...
That brings me to files owner. Big concept here. It tends to be the Controller that loads the NIB (OK: I have a custom window controller I have used for over 15 years but Apple has a really good one UIViewController that does all sorts of goodness.) and acts as a proxy in IB. It is not actually instantiated in IB but it will be when you alloc and request it to load the NIB (XIB files are XML files that are turned into NIB files by the compile process)
As a newbie, IB and all the possible connections is bewildering to me. Most tutorials I've found are what I'd call the reincarnation of spaghetti code, in which the entanglement is all the connections created by dragging. Of course, I want to use IB for layout of views (sizing & placing visual elements), that's what IB is great for. But a controller is not a view, so it's less confusing if all my controllers are solely code and don't appear anywhere in IB. I suspect this will minimize the spaghetti. It also encourages the one-xib-per-view admonishment. To that end, and here's the question, where can I find example projects that adhere to this strategy?
I don't have a set of sample projects, but I will give you some information about how things work and when you should create controller's in a XIB file or in code.
If your controllers are created dynamically by way of a user's action, you typically won't instantiate them in a XIB file. Instead, you'll instantiate them in code like harms mentions above. Once you do that, you'll still need a mechanism to connect this controller that was created in code, to the user interface elements that you've created in IB.
The mechanism that IB provides for solving this is the File's Owner. Mastering the File's Owner is essential to "getting" Interface Builder.
The file's owner is not an object that is "in" the XIB file, it's an object that's represented in the XIB file. It's a placeholder for an object that will already exist when the XIB file is loaded. When NIB files are loaded at run time, they're loaded with the NSBundle method -[NSBundle loadNibNamed:ownwer:options:]. The owner parameter is used to resolve the file's owner placeholder object in the XIB/NIB file. When the file is loaded at runtime, all of the connections made against the file's owner will resolve against the object you passed in as the owner parameter to the NSBundle method. On the iPhone, you typically don't load NIB file yourself. Instead UIViewController does it for you. The default implementation of UIViewController's loadView method might look something like this:
- (void)loadView {
[[self nibBundle] loadNibNamed:[self nibName] owner:self options:nil];
}
So, by connecting the elements in your XIB file to the file's owner, you'll be connecting them to your view controller.
You will have some controllers that are statically in your application - they'll be alive forever. A navigation or tab controller along with their root items are typically alive for for the entire life of their application. When that's the case, I'd set those view controllers up in the MainWindow.xib file. Most of the other controllers would be created dynamically, and programatically in response the the user doing things.
Good question. The pattern I try to stick with is making the controller in code, adding IBOutlets and IBActions for the things in the XIB/NIB that interact with that code, and a thing in the controller's constructor which loads the XIB/NIB with "self" as the owner, and in IB I connect stuff to the "File's Owner" placeholder, whose identity I will have specified to be the my controller's class.