Method calls and returns - objective-c

Can anyone explain this to me please (I'm getting so confused)
i have a button i click the button to call a method (flowCalculaton)
i set a local float var assign a NSTextField to the var to get its contents then retune the value ,
ALl builds and runs fine but i get a value of 0 to the answerText (label)
but if i change float setVolume = 233 ; for example i get 233 shown in the label
- (IBAction)calculate:(id)sender {
AppControls *cal =[[AppControls alloc]init];
float callMethod = [cal flowCalculation] ;
[answerText setFloatValue: callMethod ];
[cal release];
}
- (float) flowCalculation {
float setVolume = [volumeText floatValue];
return setVolume ;
}
if i do this the same call in (flowCalculation) to volumeText gives me the NSTextField value.
- (IBAction)calculate:(id)sender {
//AppControls *cal =[[AppControls alloc]init];
//float callMethod = [cal flowCalculation] ;
[answerText setFloatValue: [volumeText floatValue] ];
// [cal release];
}
Why is it not assigning [volumeText floatValue] to the var within a method please ?
Help appreciated.

What is AppControls and why are you allocating a new instance to do the calculation?
What is volumeText in AppControls, and what would be its value in a newly allocated instance of AppControls?
I'm just guessing, but maybe you meant to do this:
- (IBAction)calculate:(id)sender
{
float callMethod = [self flowCalculation] ;
[answerText setFloatValue: callMethod ];
}
EDIT in reply to comments:
I'm guessing that AppControls is your view controller. So you have an instance of it being displayed to the user, and the user is editing the contents of the text fields in that particular instance of AppControls. When you call AppControls *cal =[[AppControls alloc]init];, you're creating a brand new, empty, instance of AppControls that the user can't even see. So when you try to get the values of the text fields in that new instance, they are empty, because that is not the instance that the user was editing.

Related

Calculator label string displaying

I'm new to Objective-C and trying to make a calculator. My problem is I can't add the new number when button is pressed to the string no matter what I use (I tried methods appendString/Format and stringByAppendingString/Format).
Inputting numbers. I do the same for every other numbers:
- (IBAction)btn9:(id)sender {
[self tabbedNumber:9];
}
Declare the variable:
#property NSString *labelString;
Getting the number function:
-(void)tabbedNumber:(int)num{
NSString *lblStr = [[NSString alloc]init];
lblStr = [lblStr stringByAppendingString:[#(num) stringValue]];
self.labelString = lblStr;
[self updateText];
}
Displaying on calculator with a label calLabel:
- (void)updateText{
self.calLabel.text = self.labelString;
Best Anwser by #pavelTerziyski:
You keep lblStr = [lblStr stringByAppendingString:[#(num) stringValue]] in the function but the creation of the variable must be in the view didLoad - (void)viewDidLoad { [super viewDidLoad]; self.lblStr = [NSString new]; }
How you get the (int)num - because i tried your code with this and it worked perfectly fine
- (IBAction)buttonAction:(UIButton *)sender {
NSString *lblStr = [[NSString alloc]init];
lblStr = [lblStr stringByAppendingString:sender.titleLabel.text];
self.labelString = lblStr;
[self updateText];
}
- (void)updateText{
self.numberLabel.text = self.labelString;
}
Try this method 👇
- (IBAction)tabbedNumber:(UIButton *)sender{
self.labelString.text = [self.labelString.text stringByAppendingString:sender.titleLabel.text];
}
With this you can add any button's title label text to your label string.
But you should connect number buttons to this method.
if you want to update label with another method try this 👇
- (IBAction)tabbedNumber:(UIButton *)sender{
[self updateText:sender.titleLabel.text];
}
- (void)updateText:(NSString *)tappedNumberString{
self.labelString.text = [self.labelString.text stringByAppendingString:tappedNumberString];
}
Don't forget to connect tabbedNumber method to number Buttons.
Appending something to a new created string is not very useful.
You need to append the integer (as text) to the property labelString which seems to hold the actual value of the label.
-(void)tabbedNumber:(int)num{
self.labelString = [self.labelString stringByAppendingFormat:#"%i", num];
[self updateText];
}

Get label.text from UILabel in an instance method iOS 7

I have a pickerview that displays an array of locations (2 components); below that are 2 UILabels (2 under each component).
When a user opens the app, the picker defaults to the first object in each array in the picker components and changes the label below to reflect that selection.
So it would look something like this:
|PickerComponent1|PickerComponent2|
| Label 1 | Label 2 |
It displays the labels correctly when [viewDidLoad] is called. The labels changed to the appropriate names.
I created an instance method - but I can't pass the text value of the labels to that method.
The log displays (null) and it's coming back as empty.
Any ideas on how I can pass that label text to the method appropriately?
*edit: if I put that code that assigned label1 and the NSLog line into the viewDidLoad method it prints out the label text appropriately. When I put it into the method it does not.
My viewDidLoad in my .m file:
- (void)viewDidLoad
{
//set self as delegate for tripPicker
_tripPicker.delegate = self;
//Set size of tripPicker & datePicker
_tripPicker.transform = CGAffineTransformMakeScale(0.60, 0.60);
_datePicker.transform = CGAffineTransformMakeScale(0.60, 0.60);
//Call method to get array of school names (reusable)
MetaMiles *model = [MetaMiles schoolNameList];
_schoolArray1 = (NSArray *)model;
_schoolArray2 = (NSArray *)model;
//Set date to current date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"MM/dd/yyyy"];
_dateLabel.text = [NSString stringWithFormat:#"Date of trip: %#",[dateFormatter stringFromDate:self.datePicker.date ]];
//Set selector method for datePicker so on the value change it updates the date
[self.datePicker addTarget:self action:#selector(updateLabelForDate:) forControlEvents:UIControlEventValueChanged];
[super viewDidLoad];
//Set labels to be appropriate schools
begSchoolLabel.text = [_schoolArray1 objectAtIndex:[_tripPicker selectedRowInComponent:0]];
endSchoolLabel.text = [_schoolArray2 objectAtIndex:[_tripPicker selectedRowInComponent:1]];
//Update the Mileage indicator to display miles between currently selected values
ML54AddMilesViewController *milesObject = [[ML54AddMilesViewController alloc]init];
NSArray *currentMiles = [milesObject getMileage];
NSLog(#"Current Miles first run: %#",currentMiles);
}
My getMileage method:
- (NSArray *)getMileage {
//Update the Mileage indicator to display miles between currently selected values
NSString *begSchool = begSchoolLabel.text;
NSLog(#"FIRE THIS OFF : %#",begSchool);
NSString *endSchool = endSchoolLabel.text;
NSPredicate *milesFilter = [NSPredicate predicateWithFormat:#"beg_school=%# AND end_school=%#", begSchool, endSchool];
NSArray *resultMiles = [MetaMiles MR_findAllWithPredicate:milesFilter];
if (!resultMiles || ![resultMiles count]) {
NSLog(#"Empty Array");
} else {
NSLog(#"Our array is: %#", [resultMiles objectAtIndex:0]);}
return resultMiles;
}
What I ended up doing was instead of using the label to get the text - I just had it nab whatever the picker had chosen. The label updates appropriately but for some reason I couldn't pass it between methods - this other way I was able to do that.

Programmatically change the state of a UIButton

I've got a pop-up view that loads when a user clicks on a TableView with Core Data elements. On the pop-up view I have a label that represents an int value.
The pop-up view has two butons, one for decreasing the value of the label by 1 and one for increasing it by one. So + and -
What I want to do is to disable the minus button if the label's value is 0. What I've tried is:
-(void)viewDidLayoutSubviews{
NSString *daString = currentVal.text;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:daString];
int number = [myNumber intValue];
if (number==0)
minus.enabled = NO;
else
minus.enabled = YES
}
The problem with my code is that the button stays disabled after I increase the label's value, and it's no longer equal to 0.
Any suggestions?
You should keep a reference to minus button e.g.
#property (strong, nonatomic) IBOutlet UIButton *minusButton;
Set it with a value of your minus button, or connect outlet in Interface Builder
in your action handler for plusButton, do something like that
-(IBAction)plusAction:(id)sender {
//Do your business logic
...
self.minusButton.enabled = YES;
}
//In your minusButton action handler
-(IBAction)minusAction:(id)sender {
//Do your business logic
...
NSString *daString = currentVal.text;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:daString];
int number = [myNumber intValue];
if (number==0)
self.minusButton.enabled = NO;
else
self.minusButton.enabled = YES
}
It seems like you have things the other way around. I would take a totally different approach:
Keep an instance variable (which we'll call 'count') in this viewController which holds the number. it can be an NSInteger. now add a target (self) to both buttons with a #selector(buttonPressed:). now this is how this selector should look like:
- (void)buttonPressed:(id)sender{
if (sender==plusButton)
self.count++;
if (sender==minusButton)
self.count--;
label.text = [NSString stringWithFormat:#"%d",self.count];
minusButton.enabled = (self.count>0);
}
I would just do this with a UIStepper, instead of the 2 buttons. You can set properties right in your storyboard/IB file that specify the max and min, increments, and a bunch of other useful things too. There are a couple video tutorials posted on YouTube that probably cover everything you'll need to know to use it.
Also, I have noticed one thing that...
If the button in disabled state and you are trying to change the title of normal state, it wont work.
I had to change the state to enabled and then I could manipulate title and set back to disabled.

NSNumberformatter quasi Scientific notations

I need the NSNumberFormatter to conditionally display very huge or very small numbers as Scientific notation. But if the number can be presented without, i need it to be only decimal.
6.62e-34 is Ok, but 4,2E1 is not.
Elsewhere in the system, I have solved this using the following method:
- (NSString *) formatNumber: (double) d {
BOOL sci=NO;
double dd = d;
if (dd<0.0) dd=(-d);
if ((dd>0.0) && (dd<1e-3)) sci=YES;
if (dd>1e+8) sci=YES;
if (sci) [nf setNumberStyle:NSNumberFormatterScientificStyle];
else [nf setNumberStyle:NSNumberFormatterDecimalStyle];
return [nf stringFromNumber:[NSNumber numberWithDouble:d]];
}
But at this particular place, the whole thing is set up in the interface builder, with bindings to an managed object modell and using an array controller object. In the first text cell of the colum in the tableview, I have dragged in the numberformatter. I dont know if its possible to define some custom methods to be called to do the formatting, instead of using this NumberFormatter. If I take it away, I got errors when I run it.
anyone have some idea ?
What you want to do is write a subclass of NSValueTransformer. You can then provide the name of that transformer class in IB, in the bindings inspector. Here is an example:
#implementation RDTransformer
- (id)init {
if (self = [super init]) {
self.formatter = [[NSNumberFormatter alloc] init];
[self.formatter setNumberStyle:NSNumberFormatterScientificStyle];
[self.formatter setMaximumFractionDigits:3];
}
return self;
}
+(Class)transformedValueClass {
return [NSString class];
}
+(BOOL)allowsReverseTransformation {
return NO;
}
-(id)transformedValue:(NSNumber *)value {
if ([value compare:#1000] == NSOrderedAscending) {
return value.stringValue;
}else{
return [self.formatter stringFromNumber:value];
}
}
In IB, the column (in a single column table) has its value bound to Array Controller.arrangedObjects with a value transformer of RDTransformer. I don't have any formatters connected to the table cells.

Custom Formatter Weird Behavior

I have a custom NSFormatter linked to 4 NSTextFields. When I change the values of my text fields manually, everything works fine. But when I change it through a combo box. I get an error looking like this:
-[__NSCFNumber length]: unrecognized selector sent to instance 0xc0c3
I've noticed that the application continuously sends this error and that the instance is always the same (0xc0c3). Also, when my NSTextFields aren't linked to my custom formatter, everything works well, even through the combo box.
Do you guys know what may be the source of the problem?
Thanks in advance!
Here's some code:
Combo box action:
- (void)subnetMaskByNumberOfSubnetBits:(id)sender{
// ------- Sets the subnet mask when the user selects the number of bits
NSNumberFormatter *stringToNumber = [[NSNumberFormatter alloc] init];//TURN A STRING INTO A NUMBER
NSNumber *selectedAmountOfBits = [[NSNumber alloc] init];//CONTAINS THE SELECTED NUMBER OF BITS
selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];
[self changeSubnetMaskUsingNumberOfMaskBits:selectedAmountOfBits];
//RELEASE
[stringToNumber release];
}
-(void)changeSubnetMaskUsingNumberOfMaskBits:(NSNumber *)numberOfMaskBitsSelected{
// --------- Change the subnet mask based on the number of bits
NSInteger numberOfFullOctets;
NSInteger valueOfLastOctet;
NSInteger octetCounter;
NSMutableDictionary *subnetMaskFields = [[NSMutableDictionary alloc] init];
//Contains keys to all the outlets
[subnetMaskFields setObject:subnetMaskOctet1 forKey:#"subnetMaskField1"];
[subnetMaskFields setObject:subnetMaskOctet2 forKey:#"subnetMaskField2"];
[subnetMaskFields setObject:subnetMaskOctet3 forKey:#"subnetMaskField3"];
[subnetMaskFields setObject:subnetMaskOctet4 forKey:#"subnetMaskField4"];
//NUMBER OF FULL OCTETS AND VALUE OF LAST OCTET
numberOfFullOctets = [numberOfMaskBitsSelected intValue]/8;
valueOfLastOctet = 256 - pow(2, 8 - ([numberOfMaskBitsSelected intValue] - (8 * ([numberOfMaskBitsSelected intValue]/8)))); //Big complicated formula
//-------Setting the fields------//
//SETTING THE FIELDS OF FULL OCTETS
for (octetCounter = 1; octetCounter <= numberOfFullOctets; octetCounter++) {
[[subnetMaskFields objectForKey:[NSString stringWithFormat:#"subnetMaskField%i", octetCounter]] setStringValue:#"255"];
}
//SETTING THE FIELD OF THE INCOMPLETE OCTET
[[subnetMaskFields objectForKey:[NSString stringWithFormat:#"subnetMaskField%i", octetCounter]] setIntegerValue:valueOfLastOctet];
//FILLING THE ZER0S
while (octetCounter < 4) {
octetCounter++;
[[subnetMaskFields objectForKey:[NSString stringWithFormat:#"subnetMaskField%i", octetCounter]] setStringValue:#"0"];
}
//RELEASE
[subnetMaskFields release];
}
The problem is this line of code:
[[subnetMaskFields objectForKey:[NSString stringWithFormat:#"subnetMaskField%i", octetCounter]] setIntegerValue:valueOfLastOctet];
From what I understand, since the NSFormatter needs to get the string value of my text field, I cannot set the text field as an integer. This line of code
[[subnetMaskFields objectForKey:[NSString stringWithFormat:#"subnetMaskField%i", octetCounter]] setStringValue:[NSString stringWithFormat:#"%ld", valueOfLastOctet]];
solves the problem.