As having most of my experience in PHP, I have seen lots of new syntax rules. Most of them I have accepted and understood, but there is one that just makes no sense to me.
currentNumber = 0;
self.Label.text = [NSString stringWithFormat:#"%2.0f", result];
if ([sender tag] == 0) result = 0; {
currentOperation = (int)[sender tag];
}
As you can see, there is a bracket after result = 0;. At first I thought it was just a shortcut, just like [[something alloc]init], but when I rewrote the code like this:
currentNumber = 0;
self.Label.text = [NSString stringWithFormat:#"%2.0f", result];
if ([sender tag] == 0) result = 0;
else{
currentOperation = (int)[sender tag];
}
my app was not behaving as intended, even though the above has no syntax errors.
So my question is, what does this syntax mean? How does it translate to PHP if it even does?
This is not a single if statement, it is an if followed by a sequence of statements enclosed in curly braces. A better way of formatting this would be as follows:
if ([sender tag] == 0)
result = 0;
// ---- if statement ends here ----
{
currentOperation = (int)[sender tag];
}
result = 0 is the only part that is done conditionally; the rest, i.e.
currentOperation = (int)[sender tag];
is done unconditionally. In fact, the block that follows the conditional could be rewritten without curly braces; this would not change its behavior:
if ([sender tag] == 0)
result = 0;
currentOperation = (int)[sender tag];
why enclose currentOperation = (int)[sender tag]; within curly braces?
There is no point in doing that. The intention may have been to enclose both result = 0 and currentOperation = ... in the same block, but whoever wrote this code has made a typo.
if ([sender tag] == 0) result = 0; {
currentOperation = (int)[sender tag];
}
is equivalent to:
if ([sender tag] == 0) { result = 0; } {
currentOperation = (int)[sender tag];
}
which is equivalent to:
if ([sender tag] == 0) {
result = 0;
}
currentOperation = (int)[sender tag];
In other words, in your code only result = 0; is conditional - the rest is executed always.
Related
I want to show my long text in a UILabel. But, My design having small size of frame for that UILabel. So, i want to truncate my long text like this[see below]:
Ex:
UILabel Text: "I want to show my long text in a UILabel"
Recent Result: [Using lineBreakMode:]
I want to s........a UILabel
I want to s.....
I want to s
Expected Result: "I want to...."
[Note: I want truncation after the word which can fit within their label frame.]
I hope that you can sense about my expected result. Sorry for my English!.
I am not sure whether there is API for this. If you are not getting answers. You can use the below logic to achieve This is not optimum logic.
-(NSString *) textThatFits:(NSString *) originalText font:(UIFont *) font
{
NSArray *array = [originalText componentsSeparatedByString:#" "];
NSString *stringThatFits;
for (int i = 0 ; i < [array count]; i++)
{
NSString *tempString = [stringThatFits stringByAppendingFormat:#" %#", array[i]];
CGRect boundingRect = [tempString boundingRectWithSize:CGSizeMake(999, 999)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
if (boundingRect.size.width < self.yourLabel.width) {
return stringThatFits;
}
else
{
stringThatFits = tempString;
}
}
return stringThatFits;
}
According to the OP excepted result and the #Naveen logic, I develop the code which works but with some restriction.
Restriction:
Sometimes, extending that label width by adding 10.0 value.
don't give any spaces at begin and end of label text.
Design:
Controls: A UIButton, UITextField, UILabel
Type your text in the UITextField.
Do Action to display your excepted result in the UILabel.
Code:
-(IBAction)actionDisplayTextWithTruncate:(id)sender{
lblFinalResult.frame=CGRectMake(60, 345, 55, 21);
NSString *strGivenText, *strFuncResult, *stringThatFits;
int spaceCount;
//Custom Truncate Function
strGivenText=txtFldGivenText.text;
arrForGivenText_Words = [strGivenText componentsSeparatedByString:#" "];
stringThatFits=#"";
strFuncResult=#"";
for (int i = 0 ; i < [arrForGivenText_Words count]; i++)
{
/* must follow #" %#" - a space before %# */
NSString *tempString = [stringThatFits stringByAppendingFormat:#" %#", arrForGivenText_Words[i]];
CGRect boundingRect = [tempString boundingRectWithSize:CGSizeMake(999, 999) options:NSStringDrawingTruncatesLastVisibleLine attributes:#{NSFontAttributeName:lblFinalResult.font} context:nil];
if (boundingRect.size.width > lblFinalResult.frame.size.width) //Breakpoint1
{
if(i==0){
[lblFinalResult setText:#"..."];
return;
}
else{
for (int j = 0 ; j < i; j++)
{
strFuncResult = [strFuncResult stringByAppendingFormat:#"%# ",arrForGivenText_Words[j]];
NSLog(#"Present_a1: %#", strFuncResult);
}
strFuncResult = [strFuncResult substringToIndex:strFuncResult.length-(strFuncResult.length>0)];
lblFinalResult.frame= CGRectMake(lblFinalResult.frame.origin.x, lblFinalResult.frame.origin.y, lblFinalResult.frame.size.width+10, lblFinalResult.frame.size.height);
strFuncResult=[strFuncResult stringByAppendingString:#"..."];
[lblFinalResult setText:strFuncResult];
return;
}
}
else{
stringThatFits = tempString;
NSLog(#"Present_a2: %#", stringThatFits);
}
}
[lblFinalResult setText:stringThatFits];
}
I have this code written for a calculator application for an iPad but I just could not find a way for it to solve numbers in decimal. When I try to solve for example: 4.5 + 0.5, it will give me just 4 for an answer. I know that there is something missing with this.
Thanks for those incoming responses.
Cheers in advance!
- (IBAction)equalsPressed {
self.typingNumber = NO;
self.secondNumber = [self.calculatorDisplay.text intValue];
int result = 0;
if ([self.operation isEqualToString:#"+"]) {
result = self.firstNumber + self.secondNumber;
}
else if ([self.operation isEqualToString:#"-"]) {
result = self.firstNumber - self.secondNumber;
}
else if ([self.operation isEqualToString:#"*"]) {
result = self.firstNumber * self.secondNumber;
}
else if ([self.operation isEqualToString:#"/"]) {
result = self.firstNumber / self.secondNumber;
}
self.calculatorDisplay.text = [NSString stringWithFormat:#"%2.d", result];
self.displayLabel.text = self.calculatorDisplay.text;
}
- (IBAction) clearPressed: (id)sender {
self.calculatorDisplay.text = #"";
self.firstNumber = [self.calculatorDisplay.text intValue];
self.operation = [sender currentTitle];
}
- (IBAction)backspaceButton: (id)sender {
self.displayLabel.text = [self.displayLabel.text substringToIndex:self.displayLabel.text.length - 1];
}
- (IBAction)decimalPressed:(id)sender {
NSString *currentText = self.displayLabel.text;
if ([currentText rangeOfString:#"." options:NSBackwardsSearch].length == 0) {
self.displayLabel.text = [self.displayLabel.text stringByAppendingString:#"."];
}
}
You wrote:
int result = 0;
Change int to double.
Change all uses of intValue to doubleValue.
Change the format string from #"%2.d" to #"%2.f".
You've declared result to be an integer on this line:
int result = 0;
This is causing the values to be rounded, in some way. I'd also double check that other values that you use are of the right type too. If the input values are also ints you'd be calculating int(4.5) + int(0.5) which is 4 + 0 which is just 4.
If you change this to a float or double (depending on your needs) it should work better. Like so:
float result = 0;
I am creating a calculator app that has a backspace button just incase the user accidentally typed in a number. Is there a way to remove the last thing that was sent to the UILabel?
sure, I am adding my code to show what I am currently doing,
- (IBAction)digitPressed:(UIButton *)sender {
NSString *digit = sender.currentTitle;
if ([digit isEqualToString:#"."] && !_decimalPressed){
self.display.text = [self.display.text stringByAppendingString:digit];
self.historyDisplay.text = [self.display.text stringByAppendingString:digit];
self.decimalPressed = YES;
}
else if (!_isUserInTheMiddleOfEnteringANumber){
self.display.text = digit;
self.historyDisplay.text = digit;
self.isUserInTheMiddleOfEnteringANumber = YES;
}
else if (![digit isEqualToString:#"."]){
self.display.text = [self.display.text stringByAppendingString:digit];
self.historyDisplay.text = [self.display.text stringByAppendingString:digit];
}
}
This how I am trying to get delete the last element
- (IBAction)backSpace:(id)sender {
}
Just remove the last character from the string set inside your label. Example code:
int numChars = myLabel.text.length;
NSString* truncatedString = [myLabel.text substringToIndex:(numChars - 1)];
mLabel.text = truncatedString;
NSMutableString * stringToModify = [[NSMutableString alloc] initWithString: self.display.text];
if(stringToModify && ([stringToModify length] > 0))
{
[stringToModify deleteCharactersInRange: NSMakeRange([stringToModify length] - 1, 1)];
self.display.text = stringToModify;
[stringToModify release]; // if and only if NOT using ARC
}
- (IBAction)backPressed:(id)sender {
self.display.text=[self.display.text substringToIndex:[self.display.text length] -1];
if ([self.display.text isEqualToString:#""] || [self.display.text isEqualToString:#"-"]){
self.display.text = #"0";
self.userIsInTheMiddleOfEnteringANumber=NO;
}
}
Added in some common logic into the code. If you reach the last number and back space again, it will return the display text as 0. Since it's a calculator, assuming you have created the negative sign ( +/- ), if you are left with -, you will want to delete it and place it with 0 as well. Therefore if everything is relinquish back to 0, you will want to set your userIsInTheMiddleOfEnteringANumber to NO as well.
in the if statement below how could i make piece1's name be dynamic so that it checks for other pieces also which are piece1, piece2, ...piece5.
I would have to make it look like something like [#"piece%d",i] I'm just not sure what the correct way of writing this would be since i'm just starting with iOS.
for (int i = 0; i < 6; i++) {
if(CGRectContainsPoint([piece1 frame], location)){
piece1.center = location;
}
}
Something like this :
for (int i = 0; i < 6; i++) {
// Create a selector to get the piece
NSString *selectorName = [NSString stringWithFormat:#"piece%d", i];
SEL selector = NSSelectorFromString(selectorName);
UIView *peice = [self performSelector:selector];
// Now do your test
if(CGRectContainsPoint([piece frame], location)){
piece1.center = location;
}
}
The key bits are NSSelectorFromString to turn a string into a selector and performSelector: to get the object matching it.
First add tags to your imageView when initializing them
then change your code to this
for (int i = 0; i < 6; i++) {
UIImageView *piece = (UIImageView *)[self.view viewWithTag:i] ;
if(CGRectContainsPoint([piece frame], location)){
piece.center = location;
}
}
make sure your tag matches the value that will be in the loop i values.
Greetings,
I am new to objective c, and I have the following issue:
I have a NSString:
"There are seven words in this phrase"
I want to divide this into 3 smaller strings (and each smaller string can be no longer than 12 characters in length) but must contain whole words separated by a space, so that I end up with:
String1 = "There are" //(length is 9 including space)
String2 = "seven words"// (length is 11)
String3 = "in this" //(length is 7), with the word "phrase" ignored as this would exceed the maximum length of 12..
Currently I am splitting my original array into an array with:
NSArray *piecesOfOriginalString = [originalString componentsSeparatedByString:#" "];
Then I have multiple "if" statements to sort out situations where there are 3 words, but I want to make this more extensible for any array up to 39 (13 characters * 3 line) letters, with any characters >40 being ignored. Is there an easy way to divide a string based on words or "phrases" up to a certain length (in this case, 12)?
Something similar to this? (Dry-code warning)
NSArray *piecesOfOriginalString = [originalString componentsSeparatedByString:#" "];
NSMutableArray *phrases = [NSMutableArray array];
NSString *chunk = nil;
NSString *lastchunk = nil;
int i, count = [piecesOfOriginalString count];
for (i = 0; i < count; i++) {
lastchunk = [[chunk copy] autorelease];
if (chunk) {
chunk = [chunk stringByAppendingString:[NSString stringWithFormat:#" %#", [piecesOfOriginalString objectAtIndex:i]]];
} else {
chunk = [[[piecesOfOriginalString objectAtIndex:i] copy] autorelease];
}
if ([chunk length] > 12) {
[phrases addObject:lastchunk];
chunk = nil;
}
if ([phrases count] == 3) {
break;
}
}
well, you can keep splitting the string as you're already doing, or you could check out whether NSScanner suits your needs. In any case, you're going to have to do the math yourself.
Thanks McLemore, that is really helpful! I will try this immediately. My current solution is very similar, but less refined, as I hard coded the loops and use individual variable to hold the sub strings (called them TopRow, MidRow, and BottomRow), that and the memory management issue is overlooked... :
int maxLength = 12; // max chars per line (in each string)
int j=0; // for looping, j is the counter for managing the words in the "for" loop
TopRow = nil; //1st string
MidRow = nil; //2nd string
//BottomRow = nil; //third row string (not implemented yet)
BOOL Row01done = NO; // if YES, then stop trying to fill row 1
BOOL Row02done = NO; // if YES, then stop trying to fill row 2
largeArray = #"Larger string with multiple words";
tempArray = [largeArray componentsSeparatedByString:#" "];
for (j=0; j<[tempArray count]; j=j+1) {
if (TopRow == nil) {
TopRow = [tempArray objectAtIndex:j];
}
else {
if (Row01done == YES) {
if (MidRow == nil) {
MidRow = [tempArray objectAtIndex:j];
}
else {
if (Row02done == YES) {
//row 3 stuff goes here... unless I can rewrite as iterative loop...
//will need to uncommend BottomRow = nil; above..
}
else {
if ([MidRow length] + [[tempArray objectAtIndex:j] length] < maxLength) {
MidRow = [MidRow stringByAppendingString:#" "];
MidRow = [MidRow stringByAppendingString:[tempArray objectAtIndex:j]];
}
else {
Row02done = YES;
//j=j-1; // uncomment once BottowRow loop is implemented
}
}
}
}
else {
if (([TopRow length] + [[tempArray objectAtIndex:j] length]) < maxLength) {
TopRow = [TopRow stringByAppendingString:#" "];
TopRow = [TopRow stringByAppendingString:[tempArray objectAtIndex:j]];
}
else {
Row01done = YES;
j=j-1; //end of loop without adding the string to TopRow, subtract 1 from j and start over inside Mid Row
}
}
}
}