My app crashes when I press the "own" button. I don't know what's wrong with my code. I'm new to this, so if I totally screwed up, don't be to hard please :). EDIT: This is what Xcode says:
#1 0x000144fd in -[UIApplication sendAction:to:from:forEvent:] ()
The app crashes on the line:
if (thing.hidden == NO) {
This is the code that belongs to "own":
- (IBAction)own {
if (thing.hidden == NO) {
int rNumber = rand() % 4;
switch (rNumber) {
case 0:
result.text = #"A";
break;
case 1:
result.text = #"B";
break;
case 2:
result.text = #"C";
break;
case 3:
result.text = #"D";
break;
default:
break;
}
}
if (thing.hidden == YES) {
int rNumber = rand() % 3;
There may be several rason
IBAction is actually just a hint that tells interface builder where to find the methods in your objects so you can link controls to methods.
In iOS, actions can take zero, one or 2 parameters.
If one parameter, that parameter is the object sending the message:
-(IBAction) someAction: (id) sender;
If two parameters, it takes the form:
- (IBAction) someAction:(id) sender forEvent: (UIEvent*) event;
you can use -(void)own and connect to your button in nib file
Nothing seems wrong in your code, assuming that the objects thing and result are retained properly.
- (IBAction)own {
if (thing.hidden == NO) {
int rNumber = rand() % 4;
NSString *myText = #""; //
switch (rNumber) {
case 0:
myText = #"A";
break;
case 1:
myText = #"B";
break;
case 2:
myText = #"C";
break;
case 3:
myText = #"D";
break;
default:
break;
}
result.text = myText;
}
if (thing.hidden == YES) {
int rNumber = rand() % 3;
I just met this question. It's because of the memory management, I send the button related action to a released viewController. Hope this help.(BTW,I use the arc mode)
Related
I'm finding it hard to learn from documentation on how I can use the Kobold2D KKInput gestureSwipeDirection to detect swipes left/right/up/down and have them carry out if else statements. Can anyone help by providing me with a sample code. Thanks
KKInput* input = [KKInput sharedInput];
KKSwipeGestureDirection dir = input.gestureSwipeDirection;
switch (dir)
{
case KKSwipeGestureDirectionRight:
// direction-specific code here
break;
case KKSwipeGestureDirectionLeft:
// direction-specific code here
break;
case KKSwipeGestureDirectionUp:
// direction-specific code here
break;
case KKSwipeGestureDirectionDown:
// direction-specific code here
break;
}
I think you're making a mistake, you're placing the code in a single method, but you should use two hands, one to determine the KKInput, and one to check the status, plus you forgot gestureSwipeEnabled
try to do this:
-(id) init {
if ((self=[super init])) {
input = [KKInput sharedInput];
input.gestureSwipeEnabled = YES;
[self schedule:#selector(theTime:)];
}
return self;
}
-(void) theTime:(ccTime)time {
if (input.gestureSwipeRecognizedThisFrame) {
KKSwipeGestureDirection dir = input.gestureSwipeDirection;
switch (dir)
{
case KKSwipeGestureDirectionRight:
// direction-specific code here
break;
case KKSwipeGestureDirectionLeft:
// direction-specific code here
break;
case KKSwipeGestureDirectionUp:
break;
case KKSwipeGestureDirectionDown:
// direction-specific code here
break;
default:
break;
}
}
}
While doing tutorial work, it took me forever to implement a decimal point, and now i have one, that works in the formula, but the issue is it reverses the input - e.g.. enter 1.4, the calculator screen shows it as 4.1 - i know its something to do with my housekeeping of the variables.. planning to use BOOL's instead of a float..but..any takers?
The code:
- (IBAction) pressedDecimal: (id) sender
{
pressedDec = 1;
}
- (IBAction) pressedDigit: (id) sender
{
if (pressedDec == 1)
{currentNumber = .1 * currentNumber + (double)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%g",currentNumber];
}
else
{
currentNumber = currentNumber * 10 + (double)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%g",currentNumber];
pressedDec = 0;
}
}
- (IBAction) pressedOperation: (id) sender
{
if (currentOperation == 0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
}
}
currentNumber = 0;
calculatorScreen.text = [NSString stringWithFormat:#"%g",result];
if ([sender tag] == 0) result = 0;
currentOperation = [sender tag];
}
Consider more carefully what this extract from your code does:
currentNumber = .1 * currentNumber + (double)[sender tag];
(I'm not being very explicit because if I've understood the question right you're doing this in order to learn, and the more you have to think the better you'll learn :-).)
Lesson number 2 here: Stanford iTunes U tutorial covers building a simple calculator. Might be helpful. Either way it's a great tutorial series.
So, look at the following code below- my first question is, how can I make it so there is only 0, 1, or 2 decimal places or make it automatically have however many decimal places are there? the second question is, how would I add a decimal button to the calculator? it has +-/*, how would I add a decimal button? Tutorial I used is here http://www.youtube.com/watch?v=Ihw0cfNOrr4 and here is my code-
viewcontroller.h
#import <UIKit/UIKit.h>
#interface calcViewController : UIViewController {
float result;
IBOutlet UILabel *calculatorScreen;
int currentOperation;
float currentNumber;
}
-(IBAction)buttonDigitPressed:(id)sender;
-(IBAction)buttonOperationPressed:(id)sender;
-(IBAction)cancelInput;
-(IBAction)cancelOperation;
#end
in the .m
#import "calcViewController.h"
#implementation calcViewController
-(IBAction)buttonDigitPressed:(id)sender {
currentNumber = currentNumber *10 + (float)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%2f", currentNumber];
}
-(IBAction)buttonOperationPressed:(id)sender {
if (currentOperation ==0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
}
}
currentNumber = 0;
calculatorScreen.text = [NSString stringWithFormat:#"%2f", result];
if ([sender tag] ==0) result=0;
currentOperation = [sender tag];
}
-(IBAction)cancelInput {
currentNumber =0;
calculatorScreen.text = #"0";
}
-(IBAction)cancelOperation {
currentNumber = 0;
calculatorScreen.text = #"0";
currentOperation = 0;
}
you can use this on the output.
Float *number = 2.2f;
NSLog(#"%.2f",number);
Another thing you want to take note about the point is that you do not want to have multiple point in your calculation, e.g. 10.345.1123.5. Simply put, you want it to be a legal float number as well.
With that said, you can use a IBAction (remember to link it to your storyboard or xib file)
-(IBAction)decimalPressed:(UIButton *)sender
{
NSRange range = [self.display.text rangeOfString:#"."];
if (range.location ==NSNotFound){
self.display.text = [ self.display.text stringByAppendingString:#"."];
}
self.userIsInTheMiddleOfEnteringANumber = YES;
}
While it might be possible we are doing on the same project, it could also be entirely different (you starting from scratch by yourself) so i will go through some of the codes
you could replace UIButton with the default id, but it is better to static replace it to make clear clarification for yourself, or anyone else who view your code.
NSRange as the name implies, mark the range, and the range will be ur display text of calculation (e.g. 1235.3568), and the range of string it is targeting in this case is "." therefore, if NSNotfound (rangeOfString "." is not found in the text range) you will append the current display text with "." with the function stringByAppendingString:#".", there is no else, so no function will take place if "." is already found, which solve the problem of multiple point on the display.
userIsInTheMiddleOfEnteringANumber is a BOOL to solve the problem of having 0 in ur display (e.g. 06357), if you have a method to change it, then replace my method name with your own.
Regarding the display, as I'm using a different approach compared to yours, I'm unable to give any help or guide in that aspect.
This is my solution:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
float result;
IBOutlet UILabel *TextInput;
int currentOperation;
float currentNumber;
BOOL userInTheMiddleOfEnteringDecimal;
}
- (IBAction)buttonDigitPressed:(id)sender;
- (IBAction)buttonOperationPressed:(id)sender;
- (IBAction)cancelInput;
- (IBAction)cancelOperation;
- (IBAction)dotPressed;
#end
Viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)buttonDigitPressed:(id)sender {
if(!userInTheMiddleOfEnteringDecimal)
{
currentNumber = currentNumber*10 + (float)[sender tag];
TextInput.text = [NSString stringWithFormat:#"%d",(int)currentNumber];
}
else{
TextInput.text= [TextInput.text stringByAppendingString:[NSString stringWithFormat:#"%d",[sender tag]]];
currentNumber = [TextInput.text floatValue];
}
}
- (IBAction)buttonOperationPressed:(id)sender {
if (currentOperation == 0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
default:
break;
}
}
currentNumber = 0;
TextInput.text = [NSString stringWithFormat:#"%.2f",result];
if ([sender tag] == 0) result = 0;
currentOperation = [sender tag];
userInTheMiddleOfEnteringDecimal = NO;
}
-(IBAction)cancelInput{
currentNumber = (int)(currentNumber/10);
TextInput.text = [NSString stringWithFormat:#"%.2f",currentNumber];;
}
-(IBAction)cancelOperation{
currentNumber = 0;
TextInput.text = #"0";
userInTheMiddleOfEnteringDecimal = NO;
}
- (IBAction)dotPressed{
if(!userInTheMiddleOfEnteringDecimal){
userInTheMiddleOfEnteringDecimal = YES;
TextInput.text= [TextInput.text stringByAppendingString:#"."];
}
}
#end
Hope this helps.. This includes the decimal point in the button...
So I have an IBAction yesNo that I want to be ran on a shake event. Not all too sure why this is not working. Have followed all the documentation.
-(BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (event.subtype == UIEventSubtypeMotionShake)
{
[self yesNo];
}
}
And then the IBAction itself:
- (IBAction)yesNo
{
int rNumber = rand() % 26;
NSUserDefaults *def=[NSUserDefaults standardUserDefaults];
if ([[def objectForKey:#"activeVersion"] isEqualToString:#"0"])
{
switch (rNumber) {
case 0:
result.text = #"Never";
break;
case 1:
result.text = #"If you're lucky...";
break;
case 3:
result.text = #"Think twice";
break;
...
default:
break;
}
}
else if ([[def objectForKey:#"activeVersion"] isEqualToString:#"1"])
{
switch (rNumber) {
case 0:
result.text = #"Never1";
break;
case 1:
result.text = #"If you're lucky...1";
break;
...
case 25:
result.text = #"Very doubtful2";
break;
default:
break;
}
}
else if ([[def objectForKey:#"activeVersion"] isEqualToString:#"3"])
{
switch (rNumber) {
case 0:
result.text = #"Never3";
break;
...
case 25:
result.text = #"Very doubtful3";
break;
default:
break;
}
}
}
Basically what I have is a fortune ball type thing and when the iPhone is shaken I need that IBAction run.
Have you made that view the first responder? I.e. [yourView becomeFirstResponder]; (probably from some viewDidAppear: method).
You might want to check if it actually is the first responder when you shake your device.
When I was switching from defining everything graphically in IB to programmatically inline in Xcode, I forgot to make the view the first responder at all. Here's the code that ultimately fixed it:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self becomeFirstResponder];
NSLog(#"self is first responder %i",[self isFirstResponder]);
}
First thing I would question is whether this should be defined as an IBAction. If you only call it from code then you might want to consider using (void) instead (Simply a style choice).
Secondly, are you sure that the method is actually being called? Throw an NSLog in there to make sure.
Thirdly, are you sure that [def objectForKey:#"activeVersion"] returns a string? Is the value returned what you would expect? Throw an NSLog in there to make sure.
My guess is that one of the NSLogs will give you the answer to your question as the rest of your code seems fine.
-(void) setupMyLocation {
NSArray *viewControllerArray = [navigationUpdateFromDetail.navigationController viewControllers];
NSUInteger parentViewControllerIndex = [viewControllerArray count] - 2;
NSLog(#"Parent view controller: %#", [viewControllerArray objectAtIndex:parentViewControllerIndex]);
switch(parentViewControllerIndex){
case 0:
self.myLocation = navigationUpdateFromDetail.currentLocation;
break;
case 1:
YANAVAppDelegate *currentObject = (YANAVAppDelegate*)[[UIApplication sharedApplication]delegate];
// self.myLocation = currentObject.givenLocation;
break;
default: break;
}
}
I cannot seem to figure out why i keep getting an error "expecting expression before YANAVAppdelegate".
I cannot seem to put my finger on why this will not compile. any input is appreciated.. thanks in advance.
Don't define the variable (currentObject) inside the switch statement.
If you need to define a variable inside a case statement, you can do it using curly brackets (this technique also works in C++, by the way):
-(void) setupMyLocation {
NSArray *viewControllerArray = [navigationUpdateFromDetail.navigationController viewControllers];
NSUInteger parentViewControllerIndex = [viewControllerArray count] - 2;
NSLog(#"Parent view controller: %#", [viewControllerArray objectAtIndex:parentViewControllerIndex]);
switch(parentViewControllerIndex) {
case 0:
self.myLocation = navigationUpdateFromDetail.currentLocation;
break;
case 1:
{
YANAVAppDelegate *currentObject = (YANAVAppDelegate*)[[UIApplication sharedApplication]delegate];
// self.myLocation = currentObject.givenLocation;
break;
}
default:
break;
}
}
A C++ guru explained me once that this gives your variables a context stack for them to exist, which the switch / case statement does not provide automatically. Remember to delete / release objects if you create any in that context, otherwise it's an easy way to have a memory leak.
I personally always use curly brackets in my case statements, if you ask me ;) you never know if in the future you'll need them, it makes things easier to understand.