How do you get an int++ to keep counting past 9? - objective-c

I'm relatively new to Objective-C and I'm trying to create a game.
I currently have a score counter as such:
-(void)score {
scorenumber++;
scorelabel.text = [NSString stringWithFormat:#"%i", scorenumber];
}
The problem I'm having is I can seem to get the score to keep counting past 9. every time it reaches 9 it then resets back to 0 instead of going onto 10 11 12 and so fourth.
How can I solve this? what I'm trying to accomplish is that everytime theres an intersect between coin and star it adds +1 to score and every time it passes through tunnel it adds +1 to score
heres the entire code.

Your problem is that the UILabel (or whatever else displays your number) isn't large enough to show more than one number. When it reaches 10, you only see the second digit, which is why you think it has been reset to 0.
Try making a longer scorelabel.

If your design allows you to let the label have different width, you can use sizeToFit to give it enough width to display its text
-(void)score {
scorenumber++;
scorelabel.text = [NSString stringWithFormat:#"%i", scorenumber];
[scorelabel sizeToFit]; // <------------
}

Related

Label only displays %i instead of number

I have a method which creates one ball each time I tap on the screen. Now, I have a label which shall show the score, for now I want to let it show how many balls there are / how many times the user tapped.
The label is called score and I use the following code in the method that is responsible for the tap-ball-creation.
scoreCount += 1;
_score.text = #"%i", scoreCount;
NSLog(#"ScoreCount = %i", scoreCount);
In the debugger it shows scoreCount increasing as it should, but the label only displays %i even though scoreCount is declared in the .h as int.
I already tried to use %f and %d instead but Xcode always tells me "Expression result unused". But why?
P.S.: I'm using chipmunk stuff...
Try changing the second line to
_score.text = [NSString stringWithFormat#"%i", scoreCount];

Objective C: calculator app - currentNumber = currentNumber * 10 + digit;

I am reading "Programming in Objective-C" 4th Ed. by Stephen G. Kochan. In the book, there is a sample code for creating a Calculator application for the iPhone. I understand the code, at least 90% of it. - There is a Fraction class that has methods to store fraction objects and that describe how to perform different basic fraction arithmetic operations
- In addition to that, there is a calculator class that runs the appropriate methods from the Fraction class depending on whether the user is trying to sum, divide etc.
The view controller has the following method for when the user presses a number in the interface:
-(IBAction)clickDigit:(UIButton *)sender {
int digit = sender.tag; //sender or the argument inthis case is the button
[self processDigit:digit];
}
As you see this method is now called:
-(void) processDigit:(int)digit {
currentNumber = currentNumber * 10 + digit;
[displayString appendString:
[NSString stringWithFormat:#"%i", digit]];
display.text = displayString;
}
My ONLY question (and probably the one with the most simple answer) is: Why is currentNumber always multiplied by 10? The value of currentNumber is always 0 by the time the compiler enters the method above (I verified this using the debugger in XCode) so i dont get why we even have to multiply it by 10. I did delete that multiplication and the results are incorrect, i just cannot figure out why yet.
Thank you
Maybe the best way to think about this is with an example.
Imagine the user has clicked the following digits in order: 1, 2. Then, assuming the code is working, the numeric value of currentNumber should be 12.
Now imagine the user next clicks on '3'. Now you want the value to be 123. You can get this by multiplying the previous value (12) by 10 and then adding the 3. If they then click on a '4', the value should become 1,234, which is achieved by 10 * 123 + 4. And so on.
Imagine your calculator has "123" on the screen and you want to turn this into "1234". If it was a string you can add "4" to the end, and it works fine. But it's an integer, and if you add 4 to the integer value you get 127. So what you do is take 123, multiply by 10 to give you 1230, then add the 4 to get 1234.
The debugger must be misleading you, as it sometimes does.
Consider that if taking the multiplication out makes the result wrong then the multiplication obviously does something!
Try the following for debugging only:
int lastCurrentNumber = currentNumber;
currentNumber = 10 * lastCurrentNumber + digit;
Now in the debugger check the values of lastCurrentNumber, currentNumber and digit as you step through these two statements.
The *10 is used to move digits through the various places in decimal numbers (tens place, hundreds place, etc.)
It's kind of a "hack" to avoid having to use an array. Other calculator apps "pop" and "push" digits onto an array, this allows for more powerful operations as well as manipulation of non-decimal numbers (binary, hex, etc.)
The free iOS development course on iTunes U includes a calculator app that uses an array. If you'd like to compare the difference, you can download the source code here:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
It also has a Fraction object but doesn't use the *10 method.

What is the best way to add and keep track of an indefinite amount of objects?

I have a button that, when tapped, adds a label inside a view. Anytime it is tapped after that, it adds another label that starts where the last one ended.
I tried this
if (self.currentLabel == nil)
startingPoint = 0;
else
startingPoint = currentLabel.frame.size.width + 5;
// Most recently created label becomes currentLabel
self.currentLabel = [[FormulaLabel alloc] initWithFrame:CGRectMake(startingPoint, 10, 100, 50)];
To keep track of all the labels, I tried adding them to an array
[arrayOfObjects addObject:self.currentLabel]
but I noticed that the array count wasn't changing.
Why doesn't the above code work, and is there a better way to keep track of an indefinite amount of labels?
NSArrays are immutable. You need to use an NSMutableArray.
If you are already using a NSMutableArray, are you getting any warnings?
As an additional note, "arrayOfObjects" is a poor name. Something like "labels," "usedLabels" or "labelHistory" would be far more descriptive.

Eternal scrolling UITableView

I'm trying to create a UITableView with dates, shouldn't be very exciting, I know. It starts around the current date, but the user should be able to scroll down (the future) and up (the past) as far as he/she wants. This results in a potentially infinite number of rows. So what's the way to go about creating this?
Returning NSIntegerMax as the number of rows already crashes the app, but even if it wouldn't, that still doesn't account for being able to scroll up. I could start half way of course, but eventually there's a maximum.
Any ideas how to do or fake this? Can I update/reload the table somehow without the user noticing, so I never run into a border?
SOLUTION:
I went with #ender's suggestion and made a table with a fixed amount of cells. But instead of reloading it when the user scrolls to near the edges of the fixed cells, I went with reloading the table when the scrolling grinds to a halt. To accomodate with a user scrolling great distances without stopping, I just increased the row count to 1000, putting the ROW_CENTER constant to 500. This is the method that takes care of updating the rows.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSArray *visible = [self.tableView indexPathsForVisibleRows];
NSIndexPath *upper = [visible objectAtIndex:0];
NSIndexPath *lower = [visible lastObject];
// adjust the table to compensate for the up- or downward scrolling
NSInteger upperDiff = ROW_CENTER - upper.row;
NSInteger lowerDiff = lower.row - ROW_CENTER;
// the greater difference marks the direction we need to compensate
NSInteger magnitude = (lowerDiff > upperDiff) ? lowerDiff : -upperDiff;
self.offset += magnitude;
CGFloat height = [self tableView:self.tableView heightForRowAtIndexPath:lower];
CGPoint current = self.tableView.contentOffset;
current.y -= magnitude * height;
[self.tableView setContentOffset:current animated:NO];
NSIndexPath *selection = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
if (selection)
{
// reselect a prior selected cell after the reload.
selection = [NSIndexPath indexPathForRow:selection.row - magnitude inSection:selection.section];
[self.tableView selectRowAtIndexPath:selection animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
The magic breaks when a user scrolls to the edge of the table without stopping, but with the table view bounces property disabled, this merely feels like a minor glitch, yet totally acceptable. As always, thanks StackOverflow!
You should establish a fixed number of cells and adjust your datasource when the user scrolls near the end of the tableview. For example, you have an array with 51 dates (today, 25 future and 25 past). When the app tries to render a cell near one of the borders, reconfigure your array and call reloadData
You might also have a look at the "Advanced Scroll View Techniques" talk of the WWDC 2011. They showed how you would create a UIScrollView which scrolls indefinitely. It starts at about 5 mins. in.
Two thoughts:
Do you really need a UITableView? You could use a UIScrollView, three screens high. If end of scrolling is reached, layout your content and adjust scrolling position. This gives the illusion of infinite scrolling. Creating some date labels and arranging them in layoutSubviews: should not be too much of an effort.
If you really want to stick to UITableView you could think about having two UITableViews. If scrolling in your first one reaches a critical point, spin off a thread and populate the second one. Then at some point, exchange the views and trigger the scrolling manually so that the user does not note the change. This is just some idea from the top of my head. I have not implemented something like this yet, but I implemented the infinite UIScrollView.
I answered this question in another post: https://stackoverflow.com/a/15305937/2030823
Include:
https://github.com/samvermette/SVPullToRefresh
SVPullToRefresh handles the logic when UITableView reaches the bottom. A spinner is shown automatically and a callback block is fired. You add in your business logic to the callback block.
#import "UIScrollView+SVInfiniteScrolling.h"
// ...
[tableView addInfiniteScrollingWithActionHandler:^{
// append data to data source, insert new cells at the end of table view
// call [tableView.infiniteScrollingView stopAnimating] when done
}];
This question has already been asked: implementing a cyclic UITableView
I'm copying that answer here to make it easier because the asker hasn't ticked my answer.
UITableView is same as UIScrollView in scrollViewDidScroll method.
So, its easy to emulate infinite scrolling.
double the array so that head and tail are joined together to emulate circular table
use my following code to make user switch between 1st part of doubled table and 2nd part of doubled table when they tend to reach the start or the end of the table.
:
/* To emulate infinite scrolling...
The table data was doubled to join the head and tail: (suppose table had 1,2,3,4)
1 2 3 4|1 2 3 4 (actual data doubled)
---------------
1 2 3 4 5 6 7 8 (visualizing joined table in eight parts)
When the user scrolls backwards to 1/8th of the joined table, user is actually at the 1/4th of actual data, so we scroll instantly (we take user) to the 5/8th of the joined table where the cells are exactly the same.
Similarly, when user scrolls to 6/8th of the table, we will scroll back to 2/8th where the cells are same. (I'm using 6/8th when 7/8th sound more logical because 6/8th is good for small tables.)
In simple words, when user reaches 1/4th of the first half of table, we scroll to 1/4th of the second half, when he reaches 2/4th of the second half of table, we scroll to the 2/4 of first half. This is done simply by subtracting OR adding half the length of the new/joined table.
Written and posted by Anup Kattel. Feel free to use this code. Please keep these comments if you don't mind.
*/
-(void)scrollViewDidScroll:(UIScrollView *)scrollView_
{
CGFloat currentOffsetX = scrollView_.contentOffset.x;
CGFloat currentOffSetY = scrollView_.contentOffset.y;
CGFloat contentHeight = scrollView_.contentSize.height;
if (currentOffSetY < (contentHeight / 8.0)) {
scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY + (contentHeight/2)));
}
if (currentOffSetY > ((contentHeight * 6)/ 8.0)) {
scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY - (contentHeight/2)));
}
}
P.S. - I've used this code on one of my apps called NT Time Table (Lite). If you want the preview, you can check out the app: https://itunes.apple.com/au/app/nt-time-table-lite/id528213278?mt=8
If your table can sometimes be too short, at the beginning of the above method you can add a if logic to exit when data count is say for example less than 9.

Add integers from 5 UITextFields to a UILabel in Cocoa Touch

I'm trying to sum the integers from five UITextFields and post them to a UILabel.
This is the code I have tried, but it doesn't work properly. The number that shows up in the label is not the sum of my textfields. I have also tried to post to a textfield instead of a label, with the same result. No errors or warnings when I build.
int val = [textfield1.text intValue]
val = val+[textfield2.text intValue];
val = val+[textfield3.text intValue];
val = val+[textfield4.text intValue];
val = val+[textfield5.text intValue];
NSString *labelStr = [[NSString alloc] initWithFormat:#"%i", val];
label.text = labelStr;
Something wrong with the code? Alternative code? Grateful for all answers!
The code looks more or less right to me, aside from the memory leak. You should review the memory management rules and fix your leak.
My guess is that the numbers you entered add up to a number that is outside the range of an int. Entering, say, 1000000000 (10**9) in each of the five fields would be one way to pull this off, on any machine where an int is 32 bits (including, currently, the iPhone-OS devices).
Depending on the purpose of your app, you may be able to simply cap the five input fields; if the highest value that makes any sense is less than one-fifth (for five fields, and that's assuming they all have the same cap) of the maximum int, overflow is impossible.
If a cap won't solve the problem completely, try a different type. If the values should never be negative, use an unsigned type. Otherwise, try long long, or either of the floating-point types, or use NSDecimalNumber objects.
Of course, I could be completely wrong, since you didn't say what numbers you entered or what the result was. If it was zero, make sure that you hooked up your outlets in IB; if you forgot to do that, they contain nil, which, when you ask it for text, will return nil, which, when you ask it for an intValue, will return 0, and 0 + 0 + 0 + 0 + 0 = 0.