Calling an IBAction from another method - ios

I am new to Objective-C, Xcode and all of the good stuff. I am self teaching.
I am trying to call an IBAction from another method.
- (IBAction)strAdj:(UIStepper *)strStepper
{
// Converts stepper to integer
NSUInteger strvalue = strStepper.value;
// Changes the the text to the value of the stepper
strStat.text = [NSString stringWithFormat:#"%2d", (unsigned)strvalue];
_strMod.text = [NSString stringWithFormat:#"%2d", (unsigned)stepperAdj(strvalue)];
// Based on the value it change the strMod to a specific value
}
I am only posting a portion of the next code. It is a simple switch statement. I basically want to call the IBAction above in the Void below.
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (row) {
case 0:
break;
// Core races never change
// defines dwarf stats
case 1:
// sets all the increases
tempCon = 2;
tempWis = 2;
tempChr = -2;
// resets all other stats
tempStr = 0;
tempDex = 0;
tempInt = 0;
// I want to call the IBAction here...
break;
This IBAction will need to occur ultimately 15 times. The above switch statement occurs when the picker is changed. Where as the IBAction happens every time the stepper occurs.
I hope that I am not too far from what I want to do. Again I have only been working with this for the last several days and I have not been able to find what I am looking for or if I did then I wasn't sure what to do.

It kinda looks like you have a dropdown for the player to select a race and each attribute (str, con, wis, etc.) has a stepper to bump the respective values up or down.
I don't know enough to speculate, but I suspect there is a better approach overall. That said, I think a brute force solution to what you are trying to do is to make sure each of your steppers has a referencing outlet: stepperWis, stepperCon, stepperInt, etc. Then in your switch you can do something like so (for each attribute):
stepperWis.value = (whatever value you want);
[self strAdj:self.stepperWis];

You can call UIButton TouchUpInside event programatically like :
[YourButtonObject sendActionsForControlEvents: UIControlEventTouchUpInside];

Related

Data from DetailViewController not displaying

I'm making a chemistry calculator segment in an app I'm working on, and I cannot get the data and I cannot get the information to correctly populate the screen. There is a secondary issue, the alignment, and if someone can help me with that I'd greatly appreciate it, but it isn't the primary focus of this question - I'll make a dedicated topic for it.
So I'll go over what I want to do, and what I've tried. What I'm trying to do is make a chemistry calculator where depending on what equation is selected, a UIStepper max/min.Value is modified to include all possible derivations of that equation, as well as certain UILabels and UITextFields shown/hidden.
I have confirmed that I have data passed down from the MasterViewController as I've set the data to an NSString called _equation, and successfully used _equation to modify the title of the DetailViewController under self.title in viewDidLoad.
I have tried placing and initializing all UIStepper properties appropriately under a if/if else nest under viewDidLoad (which also quantizes the _equationName possible values to an integer (eqNum) so that it can be used in a switch statement). I have also tried placing the UITextField hidden properties under viewDidLoad, to no avail.
So without further ado, let's get to the code. I've truncated the code down to one equation so you can see what's going on here easier - note that this is nested under the IBAction for the Calculate button:
// Take _equationName quantization and use it in a switch case to determine the formula that IBAction will use:
if (dflt)
{
switch (eqNum)
{
case 1:
if ((stepper.value = 1))
{
// Change deriv_units appropriately:
deriv_units.text = #"Energy (Joules)";
// This is a Planck's constant calculation, we hide the second variable as the constant
// is stored:
value2.hidden = YES;
value2_type.hidden = YES;
// Now we set up the parameters of the first entry variable:
value1_type.text = #"Frequency (in Hz)";
double frequency = [value1.text doubleValue];
double Planck = 6.626069e-34;
double energy = Planck * frequency;
// Now we set up the return field to return results:
NSString* resultIntermediate = [NSString stringWithFormat:#"%f", energy];
result.text = resultIntermediate;
units.text = #"J";
}
and the subsequent code under viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
self.title = _equationName;
int eqNum;
if ((_equationName = #"Energy-Frequency Relation"))
{
eqNum = 1;
// Set stepper bounds for derivation:
[stepper setMinimumValue:1];
[stepper setMaximumValue:3];
self.stepper.stepValue = 1;
self.stepper.wraps = NO;
self.stepper.autorepeat = NO;
self.stepper.continuous = YES;
// This is primarily a two-variable equation, so hide UITextView and UILabel #3:
value3.hidden = YES;
value3_type.hidden = YES;
}
(Props to anyone who recognizes this - it's Planck's relation! :D)
Here is what the GUI is supposed to look like (as it appears in Storyboard):
Here is what it comes out looking like in the iOS Simulator:
Note the misalignment issue, which isn't the principle issue in play here.
Also note that right now, the switch statement for equation parameters is under an if tree that checks to see if dflt (a Boolean variable assigned to UISwitch) returns true for double-precision calculations. However, upon toggling the switch ON, the issue does not correct.
Here's an even more complete explanation:
value#.text is the number entered in one of the three UITextFields, from top to bottom.
value#_type is the text to be displayed in the corresponding UILabel.
deriv_units is the UILabel below the one marked "Derivation Units", and is used to display which derivation of the equation has been selected using the UIStepper.
At bottom: The rightmost UILabel is the result label, whereas the leftmost is the units label.
Many thanks to anyone who can help this beginning developer along the path of programming righteousness.
About your alignment issue: it looks as though you are creating the storyboard for 4" screen, while running it on a 3.5" screen. In the storyboard onnthe lower right there are some small buttons, one of thise allows you to change instantly between the display for either 4" or 3.5".
Have you made sure your controls are connected to your code?
- (void) viewDidAppear: (BOOL) animated{
[super viewDidAppear: animated];
// some rude NSAsserts, but let's be sure
NSAssert(value1_type != nil, #"Your control element is nil, it might not be hooked up");
// you should now see this text in the textfield
value1_type.text = #"Frequency (in Hz)";
NSAssert(result != nil, #"Your control element is nil, it might not be hooked up");
result.text = #"some test text";
NSAssert(units != nil, #"Your control element is nil, it might not be hooked up");
units.text = #"J";
}

Continuously Update Label Based on UISlider Value

I currently have a series of 5 UISliders that continuously update their respective labels to display what value the user is selecting in an hh:mm:ss format. I have the properties of each slider set to continuous and have their targets set to when the slider is changed (This example would be for just the first slider).
sliderOne.continuous=YES;
[sliderOne addTarget:self action:#selector(sliderOneChanged:) forControlEvents:UIControlEventTouchUpInside];
Each slider's individual label updates the time selected perfectly. Now however, I need to update another label underneath all of these sliders that continuously sums up the value of the sliders.
At the same time, I am also doing some conversions with the value of the slider using two segmented controllers -- a miles/kilometers segmented controller and various distances in another segmented controller. Each conversion results in a time in seconds that is then converted back into the hh:mm:ss format and displayed in the last label when the user selects which combo from the segment controller they want. I have all the math worked out for this, and the label will update correctly when changing segments, but not continuously.
How could I update a label to continuously show the sum of every UISlider as the user changes them?
For a continuous updating, use the UIControlEventValueChanged event along with the continuous property
sliderOne.continuous=YES;
[sliderOne addTarget:self action:#selector(sliderOneChanged:) forControlEvents:UIControlEventValueChanged];
Use KVO to get notified of changes in UISliders and update the UI accordingly. You want to wrap UI updates with dispatch_async to avoid locking the interface.
Using KVO-Notification-Manager it can be something like this (in viewDidLoad or similar):
id token1 = [slider1 addKVOBlockForKeyPath:#"value" options:NSKeyValueObservingOptionNew handler:^(NSString *keyPath, id object, NSDictionary *change) {
dispatch_async(dispatch_get_main_queue(), ^{
whateverSliderNeedsUpdate.value = /* your calculation result */;
});
}];
id token2 = [slider2 /* repeat for as many sliders as you want */];
...
It's important to remove the observers at some point.
- (void)dealloc {
[slider1 removeKVOBlockForToken:token1];
[slider2 ...];
}
If you feel adventurous you can try with ReactiveCocoa.
You could create a method that does all of your math and updates your UILabel with the result. For example:
- (void)updateSumLabel {
// this is obviously very simple
float num1 = [_sliderOne value];
float num2 = [_sliderTwo value];
float sum = num1 + num2;
[_sumLabel setText:[NSString stringWithFormat:#"#f",sum]];
}
The you can call updateSumLabel from any of your existing methods like sliderOneChanged. This is probably the most simple way todo this.

How do I use a UIButton to change a label multiple times?

I want to have one UIButton that will change the text of a label in a series. For example, I may have a label that says hello.
Then when i push a button, it will change to, What's up?.
But then a second tap of the same button will change the label to Nuttin' much!.
I know how to make the text of a label change once, but how do I change it many times with the same button? Preferably, anywhere around 20 to 30 separate texts.
Thank you in advance! :D
That's pretty open ended. Consider adding a property to your class which is an index into an array of strings. Each time you push the button increment the array (modulo size of array) and use the corresponding string to update the button. But there are a lot of other ways you could do this...
What happens when the app runs out of phrases? Start over? The typical approach would look like this.
#property (strong, nonatomic) NSArray *phrases;
#property (assign, nonatomic) NSInteger index;
- (IBAction)pressedButton:(id)sender {
// consider doing this initialization somewhere else, like in init
if (!self.phrases) {
self.index = 0;
self.phrases = #{ #"hello", #"nuttin' much" }; // and so on
}
self.label.text = self.phrases[self.index];
self.index = (self.index == self.phrases.count-1)? 0 : self.index+1;
}
In the viewDidLoad method, create an array with strings to hold the labels. Then create a variable to keep track of which object should be set as the current label. Set the initial text:
NSArray *labelNames = [[NSArray alloc] initWithObjects:#"hello",#"what's up?", #"nuttin much"];
int currentLabelIndex = 0;
[label setText:[labelNames objectAtIndex:currentLabelIndex]];
Then in the method that gets called when the button is tapped, update the text and the index.
- (IBAction) updateButton:(id)sender {
// this finds the remainder of the division between currentLabelIndex+1 and labelNames.count. If it is less than the count, its just the index. If its equal to the count we go back to the beginning of the array.
currentLabelIndex = (currentLabelIndex+1)%labelNames.count;
[label setText:[labelNames objectAtIndex:currentLabelIndex]];
}

iOS: Moving a uibutton by its tag outside of where it was generated

Is it possible? I have an array of buttons created in an void and I want to move one when a neighbouring one is called in the buttonTapped void. I have no trouble moving the button thats pressed because it is the sender, but I also need to move the one next to it and can't seem to get it to move. Each button in the array has a tag value so they're unique.
Thanks
Reasonable intuitive assumption: you generated the buttons so that they are ordered in the array...
- (void)moveButton:(UIButton *)sender // whatever
{
NSUInteger idx = [buttonArray indexOfObject:sender] + 1;
UIButton *nextButton = idx < buttonArray.count ? [buttonArray objectAtIndex:idx] : nil;
// do something with `nextButton`
}

How to use UITextFields?

I'm doing the following in my App right now:
NSInteger myReell1 = 6;
NSInteger myReell2 = 7;
NSInteger myImag1 = -5;
NSInteger myImag2 = 3
+ (WSData *)scientificData
{
float dataSet2D[2] = {0,myReell1 + myReell2};
float dataSet3D[2] = {0,myImag1 + myImag2};
return [WSData dataWithValues:[WSData arrayWithFloat:dataSet2D len:2]
valuesX:[WSData arrayWithFloat:dataSet3D len:2]];
}
This worked fine for me up to now.
Here is what I would like to change and what I would like to ask you for:
I would like to use 4 UITextFields to give the opportunity of personal input to the user, instead of the consistent Integers (myReell1, … ,myImag2) which I use right now.
How would you implement those UITextfields (maybe just 1 example?) into the code above to make the NSInteger part needless.
Please don't mind about the actual stuff inside of the scientific data. ;-)
Presuming this code is inside a view controller, you can:
Create your UITextField member variables in the class.
Subscribe the class to UITextFieldDelegate.
Wire your text fields up in Interface Builder (or instantiate them programatically and add them to the view).
Implement the didFinishEditing delegate method to handle the
actual input.
Say you make 4 textfield boxes, you can get the integer from going
myReell1 = [textFieldOne.text intValue];
and so on, there you have an integer you can use constantly, with no hardcoding
First put Textfield and then when user click some button just put bellow code in you button click metho...
NSInteger myReell1 = [textField1.text intValue];
NSInteger myReell2 = [textField2.text intValue];
NSInteger myImag1 = [textField3.text intValue];
NSInteger myImag2 = [textField4.text intValue];
:)

Resources