Curiosities noticed while learning Objective-C and Xcode in general - objective-c

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).

Related

Should I put IBActions in the header file or not?

Given that iOS SDK 6.1 is used in Xcode 4.6.3 , does it make a difference to declare the method signature of IBAction in a header file or not?
Without putting the method declaration in the header file, the app is still able to compile and run without problems. However, the method cannot be seen in a storyboard.
Are there any hidden issues of not declaring the method in the header file? Is there a memory consumption difference?
The entire point of an IBAction method is to be a public connection point in Interface Builder (using Storyboards or not).
The word IBAction itself is #defined as void. Its only purpose (and the same is true of IBOutlet) is to allow Xcode to scan your code and find these points where your controller needs to be wired up views via IB. You don't need the IBAction part of the declaration if you're programmatically connecting a control to that method.
There's no performance difference, but semantically, putting an IBAction in your implementation file doesn't really make sense. Having an IBAction means the controller is communicating to an outside object via that method, and that's exactly what header/public #interface declarations are for.
Only declare it in the .h file if you want to connect it in your storyboard/interfaz builder or you want to make it public for other classes to call it.
If you just want to make it private and only use it inside your class, there's no need of declaring it in the header file.
There's no memory or performance difference.
Even if you plan to hook it up to the interface builder, it still doesn't have be in the header file. I personally just place them straight into the implementation file.

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.

IBOutlet like constructs in the Objective-C runtime

My understanding of IBOutlets is that they act as a marker to ivars and properties in Objective-C classes. Is there anything in the Objective-C runtime that would allow one to query whether an ivar or property or a class has been marked with an IBOutlet at runtime? Or does XCode just do something clever with these at compile time?
If they are a runtime construct, is it possible to define ones own markers and use them in this way:
#private
MyMarker MyClass instance;
It is my understanding that Interface Builder simply reads the header files. IBOutlet and IBAction are trivial #defines:
#define IBOutlet
#define IBAction void
that do not affect the compile at all. Interface Builder reads your header files directly (it is notified by Xcode when the header files change, but it just reads and parses the header files itself.
When the nib files are dearchived, the values are set using the ivar or property through the normal interface, but nothing special is noted that the ivar/property is usable by Interface Builder.
So no, the existence of the IBOutlet/IBAction property is not stored and cannot be accessed, nor can you add your own properties.
You could look at attributes and see if there is anything useful that could be attached to the ivar with an attribute, but I'd be very surprised.
Yes, IBOutlet and IBAction are just thrown away by the parser at the precompilation stage, so there's nothing in the compiled output. And as noted above, they're just textually processed by Interface Builder so that it knows what subset of properties/methods to make available to the connections window.
However, that doesn't stop you doing the same thing yourself - you could just define some #define that are compiled away by the preprocessor, and using textual processing manipulate them. But none of these are available at runtime, which means that you can't really do what you propose.
It's technically possible to write a macro that would do some manipulation of a property/ivar and then add extra information to a different ivar; for example:
#define OUTLET(type,name) type name;BOOL property_##name;
#interface Foo : NSObject
{
OUTLET(NSString*,foo);
}
#end
would expand to
#interface Foo :NSObject
{
NSString* foo;
BOOL property_foo;
}
#end
and you could then use the existence of property_foo to do something with your code (which should be detectable at runtime as well as compile time).
I wouldn't recommend trying to do this generally though ... for a start, it will make your interface (and therefore memory objects) larger than they'd need to be. You'd be better off creating your own class (or struct typedef) to hold the additional information you want.

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.

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

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.