How to programmatically change label in UIView created in a nib file? - cocoa-touch

I have trouble changing the text in a label programmatically.
When I run the following code, NSLog does display "Setting myLabel to = Hello World!", but the label on the screen is not changed.
UIViewOverlay *overlayWindow;
overlayWindow = [[[NSBundle mainBundle] loadNibNamed:#"UIViewOverlay" owner:self options:nil] objectAtIndex:0];
[self addSubview:overlayWindow];
[overlayWindow setMyLabel:#"Hello World!"];
My NIB file has a 300x300 window with some labels and buttons.
There is a label, which is connected to myLabel in the outlet. The UIView does display, just that the text cannot be changed programmatically.
UIViewOverlay.h
#import <UIKit/UIKit.h>
#interface UIViewOverlay : UIView {
IBOutlet UILabel *myLabel;
}
- (void)setMyLabel:(NSString *) label;
#end
UIViewOverlay.m
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)setMyLabel:(NSString *) label {
myLabel.text = label; // THIS LINE IS NOT WORKING! :-(
NSLog(#"Setting myLabel to = %#", label); // This line is working.
}
#end
Thanks in advance..

You are using an incorrect accessor name for your method to set the label string.
In cocoa, setFoo is the method by which an instance variable called foo is assigned. This isn't just a convention, many areas of functionality depend on it, for example the use of properties, key value coding etc.
In your code, your label is called myLabel. Your method to set the text of that label is called setMyLabel. Either this is causing your outlet to not be connected when the nib is loaded, as the runtime may be trying to use that method to assign the label to your instance variable in the first place, or all of the above has no effect and you have just not connected your outlet.

Make sure you have an object in your code for the label, like this example:
IBOutlet UILabel* aLabel;
And in interface builder (you may have already done this): Connect the aLabel (or whatever name you use) outlet to the actual label. This can be done by control clicking and dragging from the File’s Owner object, in the document window, to the label, in the view. A small, gray window will appear with at least two options, one will be the aLabel defined earlier, and the other will be the view (this is a default outlet required for viewcontrollers, it will have a dash to indicate it is already connected to something). Click on the aLabel option to select it. (I'll be honest, without my mac in front of me I copied most of this paragraph's instructions from this link.)
You have an object called aLabel that you can now treat like any other variable. If you want to change the text value, try this:
aLable.text = #"some text";
Maybe you did not make the connection. Can you try the following?
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)showMyLabel:(NSString *) label {
NSLog(#"My current label contents (myLabel) = %#", myLabel.text); // ** changed to myLabel.text
}
#end
If you aren't able to print the original value, then you aren't connected.
I hope that helps.

Related

Programmatically create NSPopupButton and add items to list

I've been able to programmatically create a NSPopupButton and add it to my window, and I can add items to the list from the same method, but I'd like to figure out how I can add items to it from another method.
Here's what I have so far that works:
// in my .h file:
#interface AVRecorderDocument : NSDocument
{
#private
NSPopUpButton *button;
}
#property (assign) IBOutlet NSWindow *mainWindow;
// in my .m file:
#implementation AVRecorderDocument
#synthesize mainWindow;
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
NSView *superview = [mainWindow contentView];
NSRect frame = NSMakeRect(10,10,149,22);
NSPopUpButton *button = [[NSPopUpButton alloc] initWithFrame:frame];
[superview addSubview:button];
[button release];
}
- (void)refreshDevices
{
// I'd like to add items to my popupbutton here:
// [button addItemWithTitle: #"Item 1"];
}
#end
Up in refreshDevices I don't get a compiler error, just nothing gets added to the popupbutton. The method refreshDevices is called from -(id)init. I've also tried putting the code that is inside the windowControllerDidLoadNib at the top of my init section, but it won't even create the popupbutton there.
There are a two problems with your code:
Inside windowControllerDidLoadNib:
You don't assign the newly created button to your ivar but only to a function local variable (with the same name as your ivar).
Why nothing happens inside refreshDevices
init is called before windowControllerDidLoadNib:, so your ivar is nil (and because of 1.). Sending messages to nil does nothing.
Solution:
Remove NSPopUpButton * from windowControllerDidLoadNib: so you assign the new button to your ivar and not to some function local variable.
Call refreshDevices at the end of windowControllerDidLoadNib: or at some point you know windowControllerDidLoadNib: has been called and your button is not nil.
Edit:
You should keep in mind that the moment you remove the button from the superview it is probably deallocated because you release it after creation.
The moment it is deallocated your button ivar points to an invalid/deallocated object which leads to undefined behaviour when used in this state.
I'd advise to release the button inside dealloc so you can be sure to have a valid object throughout the whole lifetime of your document object.
But nonetheless I don't know your exact use case which might require this design.

How I can get the value of my UITextField?

how I can get the value of my UITextField ? When I declare my UITextField in the Storyboard, I know but like this, I don't know.
(sorry for my English, I'm French)
Thank you in advance for your answer.
//Ajout d'un Text Field
CGRect rectTF = CGRectMake(10,70,100,20); // Définition d'un rectangle
UITextField *articleSaisi = [[UITextField alloc] initWithFrame:rectTF];
articleSaisi.borderStyle = UITextBorderStyleLine;
articleSaisi.placeholder = #"Article";
[self.view addSubview: articleSaisi];
I am not quite sure whether you want to access the value or you want to associate your UI element to your code:
Try this if you are saying that you want to access the text value.
atricleSaisi.text
Try to control drag the UI element to either your corresponding .h or .m file so that it can create IBOutlet for you if you are saying that you want to connect your UI element to your code.
Highly recommend you go check the documentation.
if you want to know when the user pressed return, as per your comment, then you should create a UITextViewDelegate for your text view and define its textFieldShouldReturn method:
Discussion
The text field calls this method whenever the user taps the return button. You can use this method to implement any custom behavior when the button is tapped.
Also, give a look at textFieldDidEndEditing, which is called whenever there is a focus change and you should define to correctly handle user input.
Old answer:
If I do not understand you incorrectly, you want to create a UITextField programmatically (i.e., not through a Storyboard).
In this case, you should put you initialisation code inside the viewDidLoad method of your view controller and make sure that you define a property for the text field instead of a local variable:
#interface MyViewController : UIViewController
....
#property (nonatomic, strong) UITextField* articleSaisi;
...
#end
- (void)viewDidLoad {
CGRect rectTF = CGRectMake(10,70,100,20); // Définition d'un rectangle
self.articleSaisi = [[UITextField alloc] initWithFrame:rectTF];
self.articleSaisi.borderStyle = UITextBorderStyleLine;
self.articleSaisi.placeholder = #"Article";
[self.view addSubview:self.articleSaisi];
}
If you do so, you can access the text field value from any other method in the view controller through its text property:
self.articleSaisi.text

Changes not reflected across view when using binding in cocoa

I am creating some sample applications to understand the concepts of view navigation, binding etc in cocoa.
Here is the scenario:
I have a window that has a tab view(2 tabs) in MainMenu.Xib.
I have a text field in the first tab and label in the second tab. I want both of them to reflect the same value and I want to do this using binding. Also, I don't want to use the views provided to me along with the tab view.
These are the steps I have done.
The view of each tab view item is set separately in the applicationDidFinishLaunching: method using the following code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
//initialize view controllers
view1=[[ViewTab1 alloc] initWithNibName:#"ViewTab1" bundle:nil];
view2=[[ViewTab2 alloc] initWithNibName:#"ViewTab2" bundle:nil];
//set views
[[[myTabView tabViewItems] objectAtIndex:0]setView:view1.view];
[[[myTabView tabViewItems] objectAtIndex:1]setView:view2.view];
}
myTabView is the outlet reference of the tab view from MainMenu.xib in AppDelegate.
ViewTab1 is the name of the first view controller (and the xib).
ViewTab2 is the name of the second view controller (and the xib).
ViewTab1 has one single text field (and an associated label). I have bound this to a variable(name) declared in AppDelegate.
ViewTab2 has a label. I have bound this also to the same variable in AppDelegate.
The variable, 'name' is initialized in the init method of AppDelegate.
AppDelegate.h
....
NSString *name;
....
#property(strong) ViewTab1 *view1;
#property(strong) ViewTab2 *view2;
#property (assign) IBOutlet NSTabView *myTabView;
#property (strong) NSString *name;
....
AppDelegate.m
....
#synthesize myTabView;
#synthesize view1,view2;
#synthesize name;
....
- (id)init {
self = [super init];
if (self) {
name=#"dummy";
}
return self;
....
Apart from this I haven't done any coding in my program.
In the ViewTab1.xib I got an object and made it an instance of AppDelegate and then connected the delegate reference of the Application object(NSApplication) to the same object. (I hope this is the right way of getting the AppDelegate object.)
I did the same in ViewTab2.xib
Then I bound the text field in ViewTab1 and label in ViewTab2 to this variable in AppDelegate.
When I run the program both the text field and label shows "dummy". But when I change the value in the text field, its not reflected in the label in the second tab( i.e. ViewTab2).
Please tell me what I'm doing wrong.
How to establish binding to the same App delegate object from any loaded Nib?
Yes, I know this frustrated situation as described in question... after many weeks and hundreds pages of documentation for KVO - Notifications - Bindings I think there is one very simple solution for that.
As we can find in some information sources the nib-loading process produce new instances of members... and we need to use binding connection to the old one.
Note that bindings made in InterfaceBuilder are redirect to these new instances automatically after loading nib
Why not redirect the pointer of App delegate to the old instance?
In method where you loads your nib you can test which object is app delegate before and just after nib load.
If the new one isn’t the same as the previous one you can redirect it as you want.
This simple example works for me in Xcode3 under 10.5.8 with target to OSX10.5 / i386:
// ***** SOMEWHERE IN DEFAULT APP-DELEGATE.m IMPLEMENTATION
- (IBAction) createOtherWindowFromNib: (id)sender
{
// ensure that app delegate is set as you want...
[NSApp setDelegate:self];
NSLog(#"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE BEFORE NIB LOAD: %# ", [[NSApp delegate] description]);
// we can bind members of the nib to this controller over proxy object named "File’s Owner"
NSWindowController *otherWinCapo = [[NSWindowController alloc] initWithWindowNibName: #"OtherTestWindow"];
NSLog(#"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE AFTER NIB LOAD: %# ", [[NSApp delegate] description]);
// make some test for delegates before/after here if you need ...
// usually your bindings made inside "OtherTestWindow.xib" by IB doesn’t works in this moment
// ... and some redirection if needed
[NSApp setDelegate:self];
// afer that the bind made in IB inside "OtherTestWindow.xib"
// referred to (proxy object) "Application.delegate.myBOOL" (Bind to:Application, Model Key Path:delegate.myBOOL)
// react to changes of myBOOL placed in default app delegate object as expected
// simultaneously in every open instance of "OtherTestWindow.xib"
[otherWinCapo showWindow: otherWinCapo.window]; // we need populate the window instance on screen to see it
}
I think the problem is that the objects in your xibs that you set to the app delegate class create 2 different instances of the app delegate, so changing the value of the text field changes the value of name in one instance but not in the other. That's what you're doing wrong, unfortunately, I can't think of a solution at this time.
Have you turned on 'Continuously Updates Value' in the NSTextField controls?
See this example.

Getting value of a button label from a different ViewController

This seems to be quite trivial but somehow I can't get it to work. I have 2 Popover Controllers with a tableView as contents, and I have a UIViewController with some buttons.
I'm setting one of the button's title from the PopoverController's didSelectRoxAtIndexPath function. This works nicely. Now I would like to pass this button title to the second PopoverController but can't seem to get this to work; the string returns a NULL. Currently I'm using:
h file:
NSString *myString;
#property(nonatomic,retain)NSString *myString;
m file:
#synthesize myString;
in viewDidLoad:
MyAppViewController *appV = [[MyAppViewController alloc]initWithNibName:#"MyAppViewController" bundle:nil];
self.myString = appV.buttonOne.currenTitle;
Try setting setting this property before displaying the second UIPopoverController.

Append text with UITextField text

I am running Objective-C/Cocoa in Shell in Windows, not on Mac OS X.
I want to append a string with an existing string in a text field when I click a button. I've created a button in a window, but I don't know how to append a string when I click that button.
How can I append a string to a text field when that button is clicked?
This is a pretty empty question and will probably get deleted quickly. However, to attempt to answer it in some way:
If you want to display something when you click a button then you'll need a UIButton (already added you have said) and let's say a UILabel. You can find a UILabel in the same window you discovered the button. Add it to the view, somewhere just below the button.
You then want to find the .h file that corresponds to the .xib file (if you set something up by default in XCode it will have been created for you). Let's call it MyViewController.h although it will have a different name in your app.
In that .h file, you want to create an IBAction (so that you can detect the button click in code) and an IBOutlet (so you can update the text on the label).
The code should end up looking something like this:
//
// MyViewController.h
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UILabel *label;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
- (IBAction)buttonClick;
#end
Then, go back to the .xib file where you created your button. Select "File's Owner", open up the "Identity inspector" under the "Tools" menu and make sure the class is set to the same name as the class whose .h file we were just editing.
Now we need to connect the button and the label. Click on the button and bring up the "connections inspector" from the "Tools" menu again. Click in the circle next to "touch up inside" and drag it to the "File's owner". Select the "buttonClick" method that pops up in a window for you. Now select the File's owner. Click in the circle next to the word "label" and drag it to the label on your iPhone screen. This has now connected up the label and the button to the code you wrote before.
Finally, save the .xib file and open up the MyViewController.m file (or whatever it is called in your app). Add the following to it:
//
// MyViewController.m
#import "MyViewController.h" // Swap this name for the name of your .h file
#implementation MyViewController
#synthesize label;
-(IBAction)buttonClick {
label.text = #"Hello World!"
}
- (void)dealloc {
[label release];
[super dealloc];
}
#end
Spend some time looking at various tutorials etc and you'll quickly get up to speed.
You didn't specify whether you're using UILabel (Cocoa Touch) or NSTextField (Cocoa). For the latter, get the field's stringValue, send that object a stringByAppendingString: message with the string you want to append, and pass the result to the field's setStringValue: method.
Short answer: create an IBAction method in a controller class and set the IBAction as the target of your button.
Long answer: Get a book and learn the details of Cocoa. Cocoa is difficult to get started with, but once you've made the initial investment you'll be able to quickly create apps. I'd recommend Cocoa Programming for Mac OS X by Aaron Hillegass. It's desktop orientated rather than iPhone, but that shouldn't put you off.
There are also loads of great web resource to learn Cocoa. Cocoa Dev Central and the Apple developer site are great places to start.
import <UIKit/UiKit.h>
#interface MyViewController : UIViewController {
    UIButton *btnToAppend;
UITextField *textfield;
}
- (IBAction)buttonClick:(id)sender;
#end
import "MyViewController.h"
#implementation MyViewController
-(void)init{
btnToAppend = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btbToAppend.frame = CGRectMake(10, 10, 100, 30);
[btnToAppend setText:#"Append Text" forState:UIControlStateNormal];
[btnToAppend addTarget:self action:#select(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubView:btnToAppend];
textfield = [[UITextField alloc] initWithFrame:CGRectMake(10, 200, 300, 50)];
textfield.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubView:textfield];
}
-(IBAction)buttonClick:(id)sender {
NSString *string = [textfield.text stringByAppendingString:#"Welcome "];
    textfield.text = string;
}
- (void)dealloc {
    [super dealloc];
}
#end
Output will be like :
Welcome Welcome Welcome ...