Very basic outlet/action connection issue in xcode4 and assistant editor - objective-c

I have a brand new xcode 4 cocoa project ( not ios ) with a single window. For the view in that window I changed the class to "myView" and created myView.[hm] . I added a push button to the view of the main window. When I control-drag from the button to the source code for myView.m it doesn't popup with "create action?" as I would expect. It does, however, pop up when I try to control-drag to "AppDelegate.m". So I think I need to change an "owner" of something so the control-drags to myView.m work.
Any suggestions in how I might do that, or what I have conceptually wrong, would be greatly appreciated.
Thanks,
Charlie

You are doing two mistakes.
First : You have to do Ctrl+Drag to .h if you want it to make public, if you do it in .m it will become private. As you are unable to do in .m Please try it in .h.
Second: Change you Object's class to myView, by default it would be AppDelegate. And check what is your File's Owner class.

It depends on where you drag to. You can't insert an outlet (which is a property) or an action method declaration in an #implementation, or at the top level of the .m file. You must insert them within an #interface.
At the top of the .m file, just above the #implementation, start writing an #interface, and take the completion for a class extension. It should look like this:
#interface MyView ()
#end
Ctrl-drag to between those two non-empty lines, and insert your outlet or action declaration there.
So I think I need to change an "owner" of something so the control-drags to myView.m work.
I think what you read somewhere and are thinking of is changing the class of the File's Owner. You would only have to change it if it were not already the correct class, and even then, this would only be relevant if that object were on one end or the other of your ctrl-drag. Since you are dragging from one other object to the class of another, the File's Owner is not involved, so there is nothing about it that you can or should change to solve this problem.

The following approach doesn't make use of the assistant editor:
First declare an action
#interface myView : NSView
//...
- (IBAction)myAction:(id)sender;
//...
#end
in myView.h or alternatively in a class extension
#interface myView ()
//...
- (IBAction)myAction:(id)sender;
//...
#end
in myView.m.
In Interface builder, control drag from the button to the myView
and select myAction:.

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.

Accessing a label created in the storyboard on current ViewController

I want to do something pretty simple but have yet am having a hard time doing so. I want to access a label created on the currently displayed ViewController (with storyboarding) from that view controller's class. Thanks for any help.
You need to make an IBOutlet Property in your viewcontroller.h and connect it to the label.
After declaring the label property you can click and drag the o next to the property declaration (In Assistive Editor Mode) to the label to make the connection. Dont forget to synthesize it in the m.
#import "ViewController.h"
#implementation ViewController
#synthesize myLabel;
MobileOverlord is right, but you should really start using the Assistant Editor for wiring up things like this. It will do ALL the work for you:
Declaring your property as an IBOutlet
Synthesizing it for you in the implementation file
Setting it to nil in the viewDidUnload method (which you will forget 90% of the time if you do it yourself)
If you have never used the Assistant Editor, you should start it is super easy and helps you concentrate on more important stuff than manually wiring up your outlets AND actions.

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.

Events for custom UIView

What's the best way for registering events for my UIView subclass, so that I can connect them to IBAction-s in interface builder?
Currently I've just got a standard UIView dropped onto my main view and I've set the class to "RadioDial" (my custom class). This displays the view fine, but I have no idea how to get events out of it.
Thanks
Please clarify: do you mean that you would like Interface Builder to offer your view controllers to wire up custom events that your view subclass will be emitting (much like the Button controls allow you to wire up Touch Inside, etc)?
If you need this type of functionality, you will need to use a generalized 'delegate' property on your View combined with a protocol.
#protocol RadioDialDelegate
-(void)dialValueChanged:(id)sender
#end
#interface RadioDial
{
id<RadioDialDelegate> radioDelegate;
}
#property (nonatomic, assign) IBOutlet id<RadioDialDelegate> radioDelegate;
This will allow the controller to wire up to the view (assuming it implements RadioDialDelegate) and receive any events that come out of the view. Alternatively, you can use an untyped delegate and in your View code, use a late bound call:
if([radioDelegate respondsToSelector:#selector(dialValueChanged:)]) {
[radioDelegate dialValueChanged:self];
}
Create a method in your view controller (if nothing else, you should have a RootViewController in you project). Let's say your method is
-(void) buttonClicked { code code code }
In the controller's header file (for example RootViewController.h) you then put:
-(IBAction) buttonClicked;
And in IB you right-click your button/radio dial/whatever. You will see a list of events and you can drag FROM the connector of the event you want your controller to receive, to the object in IB that represents the controler (probably First Responder). This depends on how your IB structure is set up, but it should be straightforward.
Another alternative is to learn how to create UIViews programatically, and forget about IB for the time being. Opinions are divided about whether it's better to learn to use IB at the outset, or whether it's better to learn how to do everything in code and save IB for later. In any case, it's necessary to learn both ways of setting up an interface at some point.

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.