What describes an "Outlet" best in objective-c / Cocoa? - objective-c

Can someone explain in an humanly understandable way what an "Outlet" is?

It's an instance variable that shows up in Interface Builder, so that you can use IB to plug another object into the outlet.
When you load the nib, the nib-loading system will do the requisite magic to make sure the right object shows up in each outlet.
Edit: I'd intended to write a full blog post around this image (I changed my mind after finishing the image), but even alone, it should help clarify outlets for people. Here you go:
(source: boredzo.org)

From a code point-of-view and IBOutlet is only a hint for Interface Builder. It's actually a macro that compiles to, well, nothing at all. That is, the compiler completely removes when compiling.
But Interface Builder can scan your code for IBOutlet so when you right-click on an object in IB you can see all the outlets that you could connect to other objects.
alt text http://img27.imageshack.us/img27/5512/picture820090228.png
In this example, delegate is a member variable of UIApplication and it is an IBOutlet too.

I just think of it as a pointer to a UI control. Once I made that mental connection in my mind, it made sense.

I would say they are the bridge that connects your user interface objects to the code that uses them. Like the name suggests, they provide a spot to "plug in" your UI to your code.

The IBOutlet keyword is defined like this:
#ifndef IBOutlet
#define IBOutlet
#endif
IBOutlet does absolutely nothing as far as the compiler is concerned. Its sole
purpose is to act as a hint to tell Interface Builder that this is an instance variable that we’re
going to connect to an object in a nib. Any instance variable that you create and want to
connect to an object in a nib file must be preceded by the IBOutlet keyword.

IBOutlet is a symbol that indicates to Interface Builder that an object instance variable delcared as
IBOutlet id ivar_name;
should be presented as an outlet of an instance of the associated class. This allows you to graphically connect objects in Interface Builder such that, after the NIB is loaded (i.e. when the object is sent an -awakeFromNib message), the value of ivar_name will be a pointer to the object you selected as the outlet's value in Interface Builder.
From the Objective-C language standpoint, IBOutlet means nothing.

An outlet is an instance variable in your code (in X-code) that can be assigned a reference to a user interface object (in Interface Builder). You plug the user interface object into the instance variable. The assignment is specified in the NIB file created by Interface Builder.

Related

Why is my NSTextField not responding to setStringValue?

I have an object which is hooked up to interface builder (one of the little blue boxes down the left hand side (Xcode 4.5.2) and I have created bindings to an NSTextField as I am used to doing. I have also synthesised the text field in the main file (don't quite understand why but pretty sure this is necessary). However, when I try sending setStringValue:#"a string" to the text field, it doesn't work. Also, when I try and print the text field object to the command line it says null. From googling, I think some people have this problem when they use init instead of awakefromnib but this method in my programme is triggered when I press a button. The code is below. If any more information is needed, let me know. Thanks.
#import <Foundation/Foundation.h>
#import "CSSRuleSet.h"
#interface RuleSetViewUpdater : NSObject
#property (weak) IBOutlet NSTextField *top;
-(void)updateFields:(CSSRuleSet *)RuleSet;
#end
.
#import "RuleSetViewUpdater.h"
#implementation RuleSetViewUpdater
#synthesize top = _top;
-(void)updateFields:(CSSRuleSet *)RuleSet
{
[_top setStringValue:[RuleSet getValue:#"top"]];
NSLog(#"%#", _top);
}
#end
xib structure
Ok, so I realised what I was doing wrong. Basically, I had connected up the interface builder to the object exactly fine and it would of worked but because of the nature of my programme, I was initialising a new object to control the interface not realising that by doing that it would not have access to the interface. So basically instead I had to pass the original object. That probably does not make any sense but let me know if it needs explaining better.
First of all you need a connection from your sourcefile to the object in the XIB file. You have an outlet defined, but it's not sure that it's actually connected. Right-click on the object in the XIB file and make sure the outlet is connected.
Your NSLog statement ( NSLog(#"%#", _top); ) logs the NSTextField object itself. The fact that it logs "(null)", means that the outlet is not (yet) connected. When your XIB file gets loaded, the outlets are not immediately connected. awakeFromNib() gets called on all the objects in the XIB file when the file is loaded. After this, you should be able to access the objects by using the outlets.

Curiosities noticed while learning Objective-C and Xcode in general

While specifying an instance variable that provides a connection between the view controller and the View, we use the IBOutlet keyword prior to the View object type. This helps indicate that it is an instance variable connecting to the View.
However, is there a scenario where I would not require the IBOutlet keyword preceding my view Object type? For example: can we have a scenario where a:
UIButton *display ;
has some kind of use vs
IBOutlet UIButton *display ;
This question stemmed out of curiosity.
Another question that I have probably has to do with understanding the nuances of interfaces and C in general.
In the view controller or any controller as such, we tend to "import" the header files and not the implementation files. I am at odds with this concept and again it is just a curiosity?
The "IBOutlet" keyword doesn't change anything about your program, it just allows Interface Builder to recognize what connections are available. If you don't need to connect something in your interface (for example, if you just want an instance variable for private storage, or if you want to use an #property), then you don't have to use IBOutlet.
We import header files just so the compiler knows what classes and methods are available when using them from other places in the program. An implementation file doesn't need to be imported; it only needs to be compiled into the program and the things it contains will be available.
To the compiler, IBOUTLET is a null operator. It means nothing. It's only purpose is to tell Interface Builder that you intend to connect it to an interface object.
Header files define the interface, and that's all the other class implementations need.
Joe
IBOutlet and IBAction helped Interface Builder detect what outlet and actions you wish to connect to your UI controls, at compile time these IBOutlet and IBAction are ignored and have no use.
I believe you don't need these keywords anymore in Xcode 4.0+.
You can have a scenario where you don't need IBOutlet or IBAction, when you are building UI controls programmatically (in code).

How to programmatically access an NSTableView that was created in Interface Builder?

I am new to Objective-C and Cocoa programming (coming from a background of C/C++ development years ago on other platforms). I am writing an application to download remote data on a recurring basis (i.e. every X number of seconds), parse through it, sort/filter it into an NSArray, and display/update said data in an NSTableView. After reading a few books, a lot of Apple OS X Reference material, and experimenting I have managed to implement everything (the remote data download, parse/filter logic, in-memory storage, etc.) except actually updating the NSTableView with the data.
I am not sure if I am just missing something obvious or just how my application should be laid out following the MVC concept, or if Interface Builder's lack of actual code generation is just not what I am used to, but I cannot seem to determine how I can programmatically access/manipulate the NSTableView that was created in Interface Builder.
I tried (in Interface Builder) dragging a NSObject instance of my NSArray-based object in, where-then I can connect my NSTableView's Outlet/datasource, but this results in an another instance of my NSArray-based object (not connecting the NSTableView to my existing, programmatically-declared and instantiated object). Likewise, I thought to set my NSTableView's datasource programmatically, but I have not been able to determine how I can programmatically refer to the NSTableView object stored in the .xib/.nib file other than via a Tag (for which I have not been able to determine what object to call the viewWithTag: method from, after setting my NSTableView's Tag value in Interface Builder).
Any suggestions, advice, or guidance would be greatly appreciated. This feels like one of those things that will be very simple (and once I have it working in front of me, it will make a lot more sense), but I just cannot seem to get a starting point/example working.
You need to attach an instance variable in your table's controller class to the table in interface builder. Declare a table in your class like this:
IBOutlet NSTableView* myTable;
...
#property (nonatomic, retain) IBOutlet NSTableView* myTable;
And be sure to synthesize it.
In the connections tab of the info window in interface builder, connect your controller's new outlet to your table. Then when your view is loaded from the XIB, this outlet will be connected.
Hope that helps some.

How to refer to an object instance created/instantiated in interface builder?

When working in interface builder you can layout your interface with different types of objects but I'm unclear as to whether these are instances of objects or some sort of factory method or something like that. Basically if you use Interface builder to layout your objects, especially with subclasses of uiview, how do you refer to a specific instances/objects in your code?
When you place any objects such as UIButton via Interface Builder, these objects are instantiated when a xib file which you place the object is loaded.
You can refer to the object, if you hook it to a instance variable which is defined in a header file via Interface Builder.
But you need to define the instance variable to be displayed in Interface Builder like as follows.
#interface FooObject : NSObject {
UIButton *button;
}
#property (nonatomic, retain) IBOutlet UIButton * button;
You can draw connections between objects in the nib to give those objects references to each other, and you can also draw connections from the file's owner (which will be some pre-existing object from before the nib is loaded, such as a UIViewController). Generally, you'll need to structure your code so that everything that needs to access things in the nib either knows the owning object or is known by the owning object.
On the other hand, there shouldn't be that many outside objects that need to know about the specific elements in your nib or you might have a bit too much coupling.

IBOutlet and IBAction

What is the purpose of using IBOutlets and IBActions in Xcode and Interface Builder?
Does it make any difference if I don't use IBOutlets and IBActions?
Swift:
#IBOutlet weak var textField: UITextField!
#IBAction func buttonPressed(_ sender: Any) { /* ... */ }
Objective-C:
#property (nonatomic, weak) IBOutlet UITextField *textField;
- (IBAction)buttonPressed:(id)sender { /* ... */ }
IBAction and IBOutlet are macros defined to denote variables and methods that can be referred to in Interface Builder.
IBAction resolves to void and IBOutlet resolves to nothing, but they signify to Xcode and Interface builder that these variables and methods can be used in Interface builder to link UI elements to your code.
If you're not going to be using Interface Builder at all, then you don't need them in your code, but if you are going to use it, then you need to specify IBAction for methods that will be used in IB and IBOutlet for objects that will be used in IB.
The traditional way to flag a method so that it will appear in Interface Builder, and you can drag a connection to it, has been to make the method return type IBAction. However, if you make your method void, instead (IBAction is #define'd to be void), and provide an (id) argument, the method is still visible. This provides extra flexibility, al
All 3 of these are visible from Interface Builder:
-(void) someMethod1:(id) sender;
-(IBAction) someMethod2;
-(IBAction) someMethod3:(id) sender;
See Apple's Interface Builder User Guide for details, particularly the section entitled Xcode Integration.
You need to use IBOutlet and IBAction if you are using interface builder (hence the IB prefix) for your GUI components. IBOutlet is needed to associate properties in your application with components in IB, and IBAction is used to allow your methods to be associated with actions in IB.
For example, suppose you define a button and label in IB. To dynamically change the value of the label by pushing the button, you will define an action and property in your app similar to:
UILabel IBOutlet *myLabel;
- (IBAction)pushme:(id)sender;
Then in IB you would connect myLabel with the label and connect the pushme method with the button. You need IBAction and IBOutlet for these connections to exist in IB.
Interface Builder uses them to determine what members and messages can be 'wired' up to the interface controls you are using in your window/view.
IBOutlet and IBAction are purely there as markers that Interface Builder looks for when it parses your code at design time, they don't have any affect on the code generated by the compiler.
Ran into the diagram while looking at key-value coding, thought it might help someone. It helps with understanding of what IBOutlet is.
By looking at the flow, one could see that IBOutlets are only there to match the property name with a control name in the Nib file.
An Outlet is a link from code to UI. If you want to show or hide an UI element, if you want to get the text of a textfield or enable or disable an element (or a hundred other things) you have to define an outlet of that object in the sources and link that outlet through the “interface object” to the UI element. After that you can use the outlet just like any other variable in your coding.
IBAction – a special method triggered by user-interface objects. Interface Builder recognizes them.
#interface Controller
{
IBOutlet id textField; // links to TextField UI object
}
- (IBAction)doAction:(id)sender; // e.g. called when button pushed
For further information please refer Apple Docs
IBAction and IBOutlets are used to hook up your interface made in Interface Builder with your controller. If you wouldn't use Interface Builder and build your interface completely in code, you could make a program without using them. But in reality most of us use Interface Builder, once you want to get some interactivity going in your interface, you will have to use IBActions and IBoutlets.
One of the top comments on this Question specifically asks:
All the answers mention the same type of idea.. but nobody explains why Interface Builder seems to work just the same if you DO NOT include IBAction/IBOutlet in your source. Is there another reason for IBAction and IBOutlet or is it ok to leave them off?
This question is answered well by NSHipster:
IBAction
https://nshipster.com/ibaction-iboutlet-iboutletcollection/#ibaction
As early as 2004 (and perhaps earlier), IBAction was no longer necessary for a method to be noticed by Interface Builder. Any method with the signature -(void){name}:(id)sender would be visible in the outlets pane.
Nevertheless, many developers find it useful to still use the IBAction return type in method declarations to denote that a particular method is connected to by an action. Even projects not using Storyboards / XIBs may choose to employ IBAction to call out target / action methods.
IBOutlet:
https://nshipster.com/ibaction-iboutlet-iboutletcollection/#iboutlet
Unlike IBAction, IBOutlet is still required for hooking up properties in code with objects in a Storyboard or XIB.
An IBOutlet connection is usually established between a view or control and its managing view controller (this is often done in addition to any IBActions that a view controller might be targeted to perform by a responder). However, an IBOutlet can also be used to expose a top-level property, like another controller or a property that could then be accessed by a referencing view controller.
IBOutlet
It is a property.
When the nib(IB) file is loaded, it becomes part of encapsulated data which connects to an instance variable.
Each connection is unarchived and reestablished.
IBAction
Attribute indicates that the method is an action that you can connect to from your storyboard in Interface Builder.
# - Dynamic pattern
IB - Interface Builder
when you use Interface Builder, you can use Connections Inspector to set up the events with event handlers, the event handlers are supposed to be the functions that have the IBAction modifier. A view can be linked with the reference for the same type and with the IBOutlet modifier.
I didn't know you didn't need them anymore, they used to be to make it possible for interface builder to find them in your source, in swift I would image that IBAction is still needed, because it needed to change how your method can be called from interface builder though I imaging #objc would do the same thing. I personal intend to still keep using them because it documents what the method or interface is suppose to do.