Data from DetailViewController not displaying - ios

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";
}

Related

Calling an IBAction from another method

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];

Adding label text together

Hi im relatively new to iOS and I'm just wondering how i would add two labels together.
- (IBAction)switch1
{
if (switch1.on) {
value1.text = #"3";
} else {
value1.text = #"0";
}
}
- (IBAction)switch2
{
if (switch2.on) {
value2.text = #"3";
} else {
value2.text = #"0";
}
}
As you can see i have used two switches which would show two different values if they were turned on or off.
Could someone help me understand how i would add two values together.
I.e if switch one was on and switch two was off the value would be three i want this value to be shown in another label.
So far i have come up with this but for some reason it doesn't work, i have a feeling it is the format specifier but I'm not sure.
int sum = [[value1 text] intValue] + [[value2 text] intValue];
value3.text = [NSString stringWithFormat:#"%d", sum];
Dont you have this:
int sum = [[value1 text] intValue] + [[value2 text] intValue];
value3.text = [NSString stringWithFormat:#"%d", sum];
in ViewDidLoad or something? Because you have to call this at the end of both IBActions. If you don't, your final value will never change.
Make sure you properly created an outlet connection in Interface Builder as described here:
Creating an Outlet Connection
In short words. Ctrl+Click & Drag from the UISwitch to File’s Owner and click the new switch1 or switch2 action. Create outlets for the text fields and switches and link them.
Set breakpoints in switch1 and switch2 methods and ensure there are being called.
Use po command in the console to check if the text fields and switches are configured correctly.
For example:
po _textField1
should print text field's description. It will print nil when the text field is not there - not linked to a control in interface builder.

iOS 7 frame.origin.y changes back to original value upon orientation change

BACKGROUND:
I am writing a trivia APP for iOS7 using xCode 5. As of right now there are two types of questions 1) Questions that require a text field input for the answer and 2) Multiple Choice Questions. After the user enters/selects an answer they click the "Check Answer" button which displays a UIView which has an evaluation label (Correct/Incorrect) and a Reason label(which explains why their answer is correct or incorrect). Upon reviewing the evaluation the user can click the Next question button to display the next question. I have to relocate the check answer button/Reason Box UIView/Next Question Button depending on the type of question that is displayed because the text field only takes up one line and the multiple choices are displayed in a tableview and thus takes up a lot more space. The multiple choice questions and possible answers are contained within one UIView object while the text questions and text field are contained in a separate UIView (I toggle the hidden property to be true/false depending on which question is displayed). I had to do this due to issues trying to get the original questions box to resize based on the height of the UITableView containing the multiple choice options. This all works fine however...
MY ISSUE:
As stated above, I can move the necessary labels/buttons as needed by doing the following...
I can move the check answer button by doing the following:
//Moves Check Answer back to original position for text field questions
-(void)moveCheckAnswerBack {
CGRect checkAnswerFrame = self.CheckAnswerButton.frame;
checkAnswerFrame.origin.y = 126;
self.CheckAnswerButton.frame = checkAnswerFrame;
}
//Moves Check answer button down for Multiple Choice Questions
-(void)moveCheckAnswerButton {
CGRect checkAnswerFrame = self.CheckAnswerButton.frame;
checkAnswerFrame.origin.y = 300;
self.CheckAnswerButton.frame = checkAnswerFrame;
}
I move the UIView (which contains the Evaluation label and reason Label) and the next question button by doing the following:
//MOVES REASONS UIView(containing evaluation label and reason label) and Next Button Back to original position for Text Questions
-(void)moveRBoxBack {
CGRect rBoxFrame = self.rBox.frame;
rBoxFrame.origin.y = 174;
self.rBox.frame = rBoxFrame;
self.rBox.hidden= false;
CGRect NBFrame = self.NextQuestionButton.frame;
NBFrame.origin.y = 313;
self.NextQuestionButton.frame = NBFrame;
}
//MOVES REASONS UIView(containing evaluation label and reason label) and Next Button Down for Multiple Choice Questions
-(void)moveRBox {
CGRect rBoxFrame = self.rBox.frame;
rBoxFrame.origin.y = 320;
self.rBox.frame = rBoxFrame;
self.rBox.hidden= false;
CGRect NBFrame = self.NextQuestionButton.frame;
NBFrame.origin.y = 463;
self.NextQuestionButton.frame = NBFrame;
}
Here's where the problem comes in... If I change the orientation of the device all of the above gets repositioned to its original position which causes it to overlap the multiple choice questions. (Note: this is not an issue for the text field questions due to the fact that the original positions are set up to work with the text field questions.)
I am attempting to solve this by placing a call to the appropriate methods within the willRotateToInterfaceOrientation as follows:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
[self reOrderToPortrait];
} else if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)){
[self reOrderToLandScape];
}
}
-(void) reOrderToPortrait {
NSString *qType = [_tempDictionary objectForKey:#"question_type"];
//CHANGE LABEL WIDTH TO CONTRACT TO FIT ON PORTRAIT
self.LabelWidth.constant = 240;
self.mcQLabelWidth.constant = 240;
// CHECK QUESTION TYPE 1 = TEXT 2 = MULTIPLE CHOICE
if ([qType intValue] == 1) {
[self moveCheckAnswerBack];
[self moveRBoxBack];
} else if ([qType intValue] == 2) {
[self moveCheckAnswerButton];
[self moveRBox];
}
}
-(void)reOrderToLandScape {
NSString *qType = [_tempDictionary objectForKey:#"question_type"];
// CHECK FOR RETINA DISPLAY
if ([[UIScreen mainScreen] scale] == 2.0) {
//CHECK QUESTION TYPE 1 = TEXT FIELD 2 = MULTIPLE CHOICE
if ([qType intValue] == 1) {
[self moveCheckAnswerBack];
[self moveRBoxBack];
} else if ([qType intValue] == 2) {
[self moveCheckAnswerButton];
[self moveRBox];
}
if([UIScreen mainScreen].bounds.size.height == 568){
// iPhone retina-4.0 inch and change Label width
self.mcQLabelWidth.constant = 488;
self.LabelWidth.constant = 488;
} else{
// iPhone retina-3.5 inch and change label width
self.mcQLabelWidth.constant = 380;
self.LabelWidth.constant = 380;
}
}
}
The positioning gets messed up whether I go from Landscape -> Portrait or from Portrait -> Landscape... It may also be worth noting that the elements remain in the proper location if I delete the willRotateToInerfaceOrientation method... however the content stops scaling to its proper width and remains at the default portrait width...
I am new to using Auto Layout so I am unsure if this is a constraint issue. Also it may be worth noting that all of this is contained within a UIScrollview.
Any help would be greatly appreciated... Thanks for your time in advance.

UIImageView center not updating properly

I'm practicing some iOS programming. I'm looking to move a UIImageView object to a given position on the screen. The storyboard contains
-Three textboxes to input X Y and Z components (xbox,ybox,zbox)
-Three labels to display said component values (XLabel,YLabel,ZLabel)
-UIImageView containing an image (ball)
-Go button (calls buttonPressed when pressed)
The following code successfully moves the image after inputing values into the textboxes n clicking "GO". However, when I uncomment the code to update the labels, the image does not move until I click "GO" twice in a row. The first time, the labels updates. The second time, the image updates. Why does it require two clicks when I have the label update code uncommented?
Thanks,
Rob
- (IBAction)buttonPressed {
[self graph: [xbox.text intValue] :[ybox.text intValue] :[zbox.text intValue]];
/*
XLabel.text = [NSString stringWithFormat:#"X:%#", xbox.text];
YLabel.text = [NSString stringWithFormat:#"Y:%#", ybox.text];
ZLabel.text = [NSString stringWithFormat:#"Z:%#", zbox.text];
*/
}
...
-(void)graph:(int)xpos : (int)ypos : (int)zpos{
ball.center = CGPointMake(xpos,ypos);
}
I'm going to provide this as an answer. Turn off auto-layout.

How do I hide controls and cause others to shift place in iOS?

I'm programming an app for iOS 7 in Xcode 5.
I have three text boxes at the top of my page, each right above the other. Let's call them topTextBox, middleTextBox, and bottomTextBox.
My intent is that depending on a particular condition, the topTextBox might not be visible (or present, really) when the view loads.
If topTextBox isn't present (or hidden, or whatever) I would like middleTextBox and bottomTextBox to be placed further up the page...as if topTextBox wasn't ever there in the first place (so middleTextBox is in the spot topTextBox used to be in, and bottomTextBox is in the spot middleTextBox was in).
I'm using storyboards with AutoLayout ON. I can't seem to figure out what to do with the constraints for each of the three textBoxes to make this work. Making middleTextBox and bottomTextBox sit higher on the page when topTextBox is hidden doesn't need to be dynamic--I make the decision to show or not show topTextBox in ViewDidLoad()--I just need to get them to show up in the right place depending on my conditions.
Questions:
a. Is making topTextBox.hidden = YES the right way to get topTextBox to not be shown? Or is there some way to make it not noticed by the view at all?
b. What do I do with these constraints on middleTextBox and bottomTextBox to move them up on the page in this condition?
c. Is there anything else I should know to get this to work that I'm not thinking of? Perhaps a better method?
Thanks.
Have you tried just hard coding the frame logic? This could be very effective. All you have to do is conditionally populate an array containing pointers to your text fields and then perform a little frame arithmetic on their y origins. For example, this could easily display all the fields:
NSArray *fields = #[topTextField, middleTextField, bottomTextField];
for (int i = 0 ; i < fields.count ; i ++) {
UITextField *field = fields[i];
[field setFrame:CGRectMake(20.0, 20.0 + (i * 50.0), 280.0, 34.0)];
}
Produces this:
Or at its most basic level, something like this could be used to check whether any of the text fields should/shouldn't be shown, and either hides them, or adjusts their frame accordingly.
BOOL shouldShowTop = YES;
BOOL shouldShowMiddle = NO;
BOOL shouldShowBottom = YES;
NSMutableArray *fields = [NSMutableArray new];
if (shouldShowTop) {
[fields addObject:topTextField];
}else{
[topTextField setHidden:YES];
}
if (shouldShowMiddle) {
[fields addObject:middleTextField];
}else{
[middleTextField setHidden:YES];
}
if (shouldShowBottom) {
[fields addObject:bottomTextField];
}else{
[bottomTextField setHidden:YES];
}
for (int i = 0 ; i < fields.count ; i ++) {
UITextField *field = fields[i];
[field setFrame:CGRectMake(20.0, 20.0 + (i * 50.0), 280.0, 34.0)];
}
Will produce this:
Setting the height constraint of topTextField to 0 will help you to achieve this.
provided all textfields are connected through vertical space constraint
Setting the height of topTextField so that it has zero height could also work for you.
CGRect frame = topTextField.frame;
frame.size.height =0;
topTextField.frame = frame;
This is a good choice should you want to animate its re-appearance later on.
As for constraints, constrain the top of the topTextField to the superview, and then the top of middleTextField and bottomTextField to the bottom of the textfield above.
Do not set a constraint for the height of topTextField, but do set width constraints. You'll need to set the height of topTextField in viewDidLoad:

Resources