Assume there's code for an iPhone project that is:
IBOutlet UITextField* numberDisplay;
#property (strong,nonatomic) IBOutlet UITextField *numberDisplay;
in implementation file and
#synthesize numberDisplay;
in implementation file. Also in implementation is
-(IBAction)numberClicked:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
int val = buttonPressed.tag;
if ( [numberDisplay.text compare:#"0"] == 0 ) {
numberDisplay.text =[NSString stringWithFormat:#"%d", val ];
}
else {
numberDisplay.text = [NSString
stringWithFormat:#"%#%d", numberDisplay.text, val ];
}
}
When I run the app there is no display shown in the UITextfield, even though the connections were made with IB and is proven to be made by viewing the inspector. Even as a test if I add the lines
numberDisplay.text = #"a";
NSLog(#"the value is %#",numberDisplay.text);
NSLog(#"the value is %#",numberDisplay);
I get " the value is (null) in both cases.
Clean and rebuild your project, then double-check that the IB connections have been made to the relevant fields. If that still doesn't work, you'll want to try running the debugger and checking whether the UITextField is ever set or released.
Drop the IBOutlet from the ivar, in fact drop the ivar, the modern runtime will synthesize it for you.
Drop the ivar, and change to this:
#property (strong,nonatomic) IBOutlet UITextField *numberDisplay;
And this:
#synthesize numberDisplay = _numberDisplay;
This line will automatically create an ivar named _numberDisplay.
-(IBAction)numberClicked:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
int val = buttonPressed.tag;
if ( [_numberDisplay.text compare:#"0"] == 0 ) {
_numberDisplay.text =[NSString stringWithFormat:#"%d", val ];
}
else {
_numberDisplay.text = [NSString stringWithFormat:#"%#%d", _numberDisplay.text, val ];
}
}
Note from your own class you can use either self.numberDisplay or _numberDisplay to reference the text field.
There's a good chance you will have to reconnect in IB when you are done. Remember to disconnect any connections rendered invalid.
Related
For example, I have, in my ViewController.h:
#property (weak, nonatomic) IBOutlet UIButton *buttonA;
....
#property (weak, nonatomic) IBOutlet UIButton *buttonZ;
in my ViewController.m, I have:
for (unichar ch = 'A'; ch <= 'Z'; ch++) {
NSMutableString *nameOfButton = [[NSMutableString alloc] initWithString:#"button"];
[nameOfButton appendString:[NSString stringWithCharacters:&ch length:1]];
//Code equivalent to change "self.(nameOfButton).text = #"";"
}
I'm trying to iterate through all of the buttons, and change their text property. Basically, I'm unsure of how to make the above for loop do the equivalent of:
self.buttonA.text = #"";
self.buttonB.text = #"";
...
self.buttonZ.text = #"";
because I'm using a NSString 'nameOfButton' instead of the actual property name.
You can make an IBOutlet collection instead of multiple UIButton IBOutlets and loop over the buttons in your outlet collection.
When you make the connection between the view and code you choose outlet collection in the dialog that pops open. (under connection)
Example: call your IBOutlet collection button list and loop over it:
for (UIButton *button in self.buttonList) {
[button setTitle:#"text" forState:UIControlStateNormal];
}
PS: Remember to always use set title for state, .text doesn't work on buttons
This will work for you
for (unichar ch = 'A'; ch <= 'Z'; ch++) {
NSMutableString *nameOfButton = [[NSMutableString alloc] initWithString:#"button"];
[nameOfButton appendString:[NSString stringWithCharacters:&ch length:1]];
//Code equivalent to change "self.(nameOfButton).text = #"";"
NSLog(#"%#",nameOfButton);
UIButton *btn = (UIButton *)[self valueForKey:nameOfButton];
[btn setTitle:nameOfButton forState:UIControlStateNormal];
}
The code makes all your buttons in this series to change there title to there outlet name.The code with that log is self explanatory
You can use KVC (key value coding) to pull out properties using strings e.g.
UIButton *btn = (UIButton *)[self valueForKey#"buttonA"];
You could use KVC (Key-Value Coding) inside your loop:
[self setValue:#"" forKeyPath:[NSString stringWithFormat:#"%#.text", nameOfButton]];
You can iterate through all the buttons in self.view if they are added to the viewcontroller's view with the following
for (UIButton *button in self.view.subviews) {
// your code here
}
It's me again, I've been struggling with this for the past hour and a half and can't seem to find a good way of implementing this. I'm basically trying to display results on a label on clicking of a button. (Just starting out with xcode so I'm not sure if that's the right term for that action). Anyway, here's my code and the method on my controller: I have
#interface Match : NSObject{
}
#property NSInteger *Id;
#property NSString *fighter1, *fighter2;
- (id) initWithWCFId:(NSInteger)matchId bracketId:(NSInteger)bracketId;
#end
#implementation Match
- (id) initWithWCFId:(NSInteger)matchId bracketId:(NSInteger)bracketId{
self = [self init];
if(self){
self.Id = &(matchId);
self.fighter1 = #"Person 1";
self.fighter2 = #"Person 2";
}
return self;
}
#end
--- controller ---
#interface ViewController : UIViewController{
/*IBOutlet UITextField *txtFieldBracketId;
IBOutlet UITextField *txtFieldMatchId;*/
}
#property (weak, nonatomic) IBOutlet UITextField *txtFieldBracketId;
#property (weak, nonatomic) IBOutlet UITextField *txtFieldMatchId;
- (IBAction)btnSubmit:(id)sender;
#end
--- implementation
- (IBAction)btnSubmit:(id)sender {
#autoreleasepool {
Match *match = [[Match alloc]initWithWCFId:[_txtFieldMatchId.text integerValue] bracketId:[_txtFieldBracketId.text integerValue]];
self.lblMatchId.text = [[NSString alloc] initWithString:[NSNumber numberWithInt:match.Id]];
self.lblFighter1.text = [[NSString alloc] initWithString:match.fighter1];
self.lblFighter2.text = [[NSString alloc] initWithString:match.fighter2];
}
}
I basically have two text boxes.
Now when I click the button it'll get the value for those text boxes and then displays the data it got based off of those inputs. It'll then display the three following data:
Id, Fighter1 and Fighter2.
So what's happening is, when I click the button, the whole thing stops and gives me this error:
NSInvalidArgumentException', reason: '-[__NSCFNumber length]:
unrecognized selector sent to instance 0x74656e0'
* First throw call stack: (0x1c90012 0x10cde7e 0x1d1b4bd 0x1c7fbbc 0x1c7f94e 0xae4841 0x2891 0x10e1705 0x18920 0x188b8 0xd9671 0xd9bcf
0xd8d38 0x4833f 0x48552 0x263aa 0x17cf8 0x1bebdf9 0x1bebad0 0x1c05bf5
0x1c05962 0x1c36bb6 0x1c35f44 0x1c35e1b 0x1bea7e3 0x1bea668 0x1565c
0x23dd 0x2305) libc++abi.dylib: terminate called throwing an exception
Now I'm not sure if 1. The way I designed my class is correct, using "NSInteger" for the property id. or
2. Assigning the Id integer to string (edit box) is wrong.
Two things:
The property should not be pointer type, so it should be #property NSInteger Id; and in init it should be just self.Id = matchId;
Make it to string by using [NSString stringWithFormat:#"%d", match.Id]
In addition to the issues with your Id property, the crash is coming from this:
self.lblMatchId.text = [[NSString alloc] initWithString:[NSNumber numberWithInt:match.Id]];
You are trying to pass an NSNumber object as the argument to the initWithString: method. But this method expects an NSString value, not an NSNumber.
Update the three lines to:
self.lblMatchId.text = [[NSString alloc] initWithFormat:#"%d", match.Id];
self.lblFighter1.text = match.fighter1;
self.lblFighter2.text = match.fighter2;
I'm assuming match.fighter1 and match.fighter2 are NSString properties.
I am a beginner of iOS and I am writing some practice code in which I am trying to pass a string from one tab to another in a UITabViewController and using a label to display it in the next tab. Now the code where I am passing the message is:
-(IBAction)sendMessage:(id)sender
{
MessageRecepientViewController * contoller = [self.tabBarController.viewControllers objectAtIndex:1];
[contoller passString:_textField.text];
self.tabBarController.selectedIndex = 1;
}
And I am receiving the text here (in the second view controller) as:
-(void) passString:(NSString *) str
{
_string = str;
}
And in viewDidAppear, i am doing this:
- (void) viewDidAppear:(BOOL)animated
{
self.textLabel.text = [NSString stringWithString:_string];
NSLog(#"did appear called, str = %# and label text = %#", _string, self.textLabel.text);
}
and the log is showing that the value of the string is the passed text as it should be, but the value of textLabel.text is always null.
I have tried everything I could think of from checking that the UILabel is attached to the textLabel outlet to writing the code in viewWillAppear and viewDidLoad but nothing have worked so far. The string is showing the correct value but the label is not updating. What is wrong here?
Ok found the error:
It was a minor typo: I had declared IBOutlet as:
IBOutlet UILabel * textlabel;
and property as:
#property (nonatomic, strong) UILabel * textLabel;
and had attached the outlet to textlabel and had been updating textLabel. Fixed this and things are fine!
I'm making an app that calculates certain things.
I need it to be able to take the input from the first textfields, for example 4+4 and save the result in a variable.
In the second text fields there could be 8+8 for example, and the result of that will also be saved into a variable (possibly the same).
Third row of textfields could yield more numbers etc, etc..
In the end there will be a button "Calculate" for example. And that will take the results from first, second, third etc textfields and calculate all of those together and output the end result.
The calculations are of course more advanced than this, but I just need the basic/simple idea of how to do this.
There is no need for saving the data to a file just now, it should just be in the app while the other textfields are being filled.
For 0x8badf00d:
Header.
#interface UnitConverterViewController : UIViewController {
NSMutableArray *calculationsArray;
UITextField *m1Text;
UITextField *m2Text;
}
#property (nonatomic, retain) IBOutlet UITextField *m1Text;
#property (nonatomic, retain) IBOutlet UITextField *m2Text;
#property (nonatomic, retain) IBOutlet NSMutableArray *calculationsArray;
#end
Implementation:
#implementation UnitConverterViewController
#synthesize m1Text, m2Text, calculationsArray;
#synthesize resultTotal = _resultTotal;
-(id)init {
if(self = [super init]){
calculationsArray = [[NSMutableArray alloc] init];
}
}
- (void)compute{
NSString* sumString = [NSString stringWithFormat:#"%d",[m1Text.text intValue]+[m2Text.text intValue]];
[calculationsArray addObject:sumString];
}
-(IBAction)calculate{
int total=0;
for(NSString* sumStr in calculationsArray){
total = total+[sumStr intValue];
}
NSLog(#"Total: %d", total);
[calculationsArray release], calculationsArray = nil;
}
I must be doing something wrong, and I know I need a way to output this, a label and such. But for now I need to know if what I've done so far is correct, and what the best way of outputting it would be.
You should declare the variables to store the results in your header file, these are than accessible from anywhere in your .m file, the same goes for your text fields.
For example:
Calculator.h
#interface Calculator: SuperclassName{
UITextField *_fldOne;
UITextField *_fldTwo;
UITextField *_fldThree;
UITextField *_fldFour;
int resultOne;
int resultTwo;
int _resultTotal;
}
#property(nonatomic, readonly) int resultTotal;
- (void) calculate;
#end
Calculator.m
#implementation Calculator
#synthesize resultTotal = _resultTotal;
- (void) calculate{
resultOne = [_fldOne.text intValue] * [_fldTwo.text intValue];
resultTwo = [_fldThree.text intValue] / [_fldFour.text intValue];
totalResult = resultOne + resultTwo;
}
#end
In this example resultOne and Two, and all the textfields are available throughout your class to work with, the totalResult is set as a readonly property and synthesized to create a getter automaticaly (which returns the value stored in _totalResult because of synchronizing like totalResult = _totalResult) as so it is available to read from outside the class.
As long as it all happens on one screen it should be more than enough, but of course you could make an NSDictionary or NSArray but that seems unnecessary here.
Hope this helps
Save the result to array. Lets say you have NSMutableArray* calculationsArray;//iVar
//initialize calculationsArray in init method
-(id)init
{
if(self = [super init])
{
calculationsArray = [[NSMutableArray alloc] init];
}
}
- (void)compute
{
NSString* sumString = [NSString stringWithFormat:#"%d",[textField1.text intValue]+[textField2.text intValue]);
[calculationsArray addObject:sumString];
}
- (IBAction)calculate
{
int total=0;
for(NSString* sumStr in calculationsArray)
{
total = total+[sumStr intValue];
}
NSLog(#"Total: %d",total);
[calculationsArray release],calculationsArray = nil;
}
I already googled for "CFString isNaturallyRTL" with 0 results.
these are my classes:
//in .H
#interface myViewController : UIViewController {
UITextField *from;
UITextField *to;
NSString *fromText;
NSString *toText;
}
#property (nonatomic, retain) NSString* fromText;
#property (nonatomic, retain) NSString* toText;
#property (nonatomic, retain) UITextField *from;
#property (nonatomic, retain) UITextField *to;
//in .m
#synthesize from, to;
#synthesize fromText, toText;
viewDidLoad(...) {
fromText = #"Roma";
toText = #"Lecce";
}
- (void) drawRoute {
if ( ([[from text] length] > 2) && ([[to text] length] > 2) )
{
fromText = from.text;
toText = to.text;
[...]
}
}
Now, i have a view that open on button touch tha contains two text boxes and a button. Like this.
- (void) drawRouteTextboxes {
from = [[UITextField alloc] initWithFrame: [...] ];
from.text = fromText;
from.delegate = self;
[ctr.view addSubview:from];
[from release];
to = [[UITextField alloc] initWithFrame: [...] ];
[...]
[searchButton addTarget:self action:#selector(drawRoute) forControlEvents: UIControlEventTouchUpInside];
}
It's all correct, compile and run.
First time that i click drawRouteTextboxes, it opens my view with default text setted ("Roma" and "lecce").
Second time, i open the view, edit textfield and call drawRoute. It's ok.
The third time that i call drawRouteTextboxes it return me this runtime error:
*** -[CFString _isNaturallyRTL]: message sent to deallocated instance 0x3a8d140
I don't know where is the problem...
Someone know a solution?
It's the first time that i see this error!
thanks,
Alberto.
It's all correct, compile and run.
If it was all correct, it would run without error. ;)
This looks suspect:
fromText = from.text;
toText = to.text;
If from.text and to.text are returning either autoreleased objects or objects that are later released, then the above doesn't retain the strings and could easily lead to an over-release problem as you are seeing.
Use self.fromText = from.text; instead.
Note that NSString* properties should almost always be copy and not retain.