Is it possible to do negative loc in the NSMakeRange? - ios

Is it possible to do negative loc in the NSMakeRange?
NSString *string = #"abc";
NSString *myString = [string substringWithRange:NSMakeRange(-1, 1)];

No.
location and length are unsigned integers :
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;
and also, NSMakeRange function is defined as follow :
NSRange NSMakeRange (
NSUInteger loc,
NSUInteger len
);

Yes, it possible, but in fact it will no sense since negative value will translated to another very big positive value.
NSUInteger loc = -1; // equal to 4294967295
1.So, you are in need of a very long string.
2.So, you need to invert your negative value to enormous big value in order to make your example worked
NSString *string = #"abc";
NSRange r1 = NSMakeRange(-NSUIntegerMax, 1);
NSString *myString = [string substringWithRange:r1];
NSLog(#"%#",myString);

Related

How to shorten an NSString that might include e.g. Emojis to the maximal length allowed for a HFS+ filename

Apples documentation says:
[...] current file systems such as HFS+ (used by Mac OS X) allow you to create filenames with a 255-character limit [...] symbols may actually take up to the equivalent of nine English characters to store [...] This should be considered when attempting to create longer names.
How do I limit the length of a NSString in a way that it is truly shorter than 255 characters, even when it includes symbols that might take more than one character to store?
I add my current implementation below. If i add e.g. emojis to the string, while length answers the resulting string would be by far smaller than 255, it is still too long to be accepted by a NSSavePanel as file name.
NSRange stringRange = {0, MIN([fileName length], 255)};
stringRange = [fileName rangeOfComposedCharacterSequencesForRange:stringRange];
fileName = [fileName substringWithRange:stringRange];
As suggested by #JoshCaswell, I did modify this answer to a similar question. It apparently does work (I wrote several tests), but it seems strange to me. Such an obvious task cannot be so complicated to achieve?
// filename contains the NSString that should be shortened
NSMutableString *truncatedString = [NSMutableString string];
NSUInteger bytesRead = 0;
NSUInteger charIdx = 0;
while (bytesRead < 250 && charIdx < [fileName length])
{
NSRange range = [fileName rangeOfComposedCharacterSequencesForRange:NSMakeRange(charIdx, 1)];
NSString *character = [fileName substringWithRange:NSMakeRange(charIdx, range.length)];
bytesRead += [character lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
charIdx = charIdx + range.length;
if (bytesRead <= 250)
[truncatedString appendString:character];
}
rangeOfComposedCharacterSequencesForRange: is basically doing the opposite of what you want: you give it a range that counts 255 composed characters, and it gives you the byte range that encompasses those, which might end up being much more than you want.
Unfortunately to do the reverse, you have to count the bytes manually. This isn't too hard, however, with enumerateSubstringsInRange:options:usingBlock:. Passing NSStringEnumerationByComposedCharacterSequences for the options gives you exactly what it says: each composed character in turn. You can then count the size of each with lengthOfBytesUsingEncoding:, passing the final encoding you'll be using (presumably UTF-8). Add up the bytes, keeping track of the character-based index, and stop when you've seen too many.
NSString * s = /* String containing multibyte characters */;
NSUInteger maxBytes = ...;
__block NSUInteger seenBytes = 0;
__block NSUInteger truncLength = 0;
NSRange fullLength = (NSRange){0, [s length]};
[s enumerateSubstringsInRange:fullLength
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:
^(NSString *substring, NSRange substringRange,
NSRange _, BOOL *stop)
{
seenBytes += [substring lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
if( seenBytes > maxBytes ){
*stop = YES;
return;
}
else {
truncLength += substringRange.length;
}
}];
NSString * truncS = [s substringToIndex:truncLength];

Objective C, Trim a float

I have float like 3500,435232123. All I want to know if exists (in Objective C) a function that let me keep just the last 4 digits in my case is 2123.
You can use NSNumberFormatter
NSNumberFormatter *format = [[NSNumberFormatter alloc]init];
[format setNumberStyle:NSNumberFormatterDecimalStyle];
[format setRoundingMode:NSNumberFormatterRoundHalfUp];
[format setMaximumFractionDigits:4];
[format setMinimumFractionDigits:4];
string = [NSString stringWithFormat:#"%#",[format stringFromNumber:[NSNumber numberWithFloat:65.50055]] ;
Or simply
NSString *string = [NSString stringWithFormat:#"%.04f", floatValue];
If you want only last four digits, convert the float to a string
NSString *string = [NSString stringWithFormat:#"%f", floatValue];
and get the last four characters
NSString *lastFour = [string substringFromIndex: [string length] - 4];
It you want to get the decimal part, you can do x - floor(x). For instance:
float x = 3500,435232123;
NSString *string = [NSString stringWithFormat:#"%.04f", x - floor(x)];
And to get 4 decimal digits do what Fawad Masud says.
No there is no such function, as far as i know. But here is a way to achieve exactly what you want.
First you have to round it to four digits after point:
NSString *exampleString = [NSString stringWithFormat:#"%.04f", valueToRound];
Then you get the location for the comma inside the exampleString:
NSRange commaRange = [valueString rangeOfString:#","];
Finally you create the finalString with the values from that NSRange. The substring starts at commaRange.location+commaRange.lengthbecause thats the index directly after the comma.
NSString *finalString = [valueString substringWithRange:NSMakeRange(commaRange.location+commaRange.length,valueString.length-commaRange.location-commaRange.length)];
Hope that helps you.
I think is no predefined function for that.
and the solution i thought of is:
float floatNum = 3500.435232123;
converting float number to string and trim/substring the string, like for example:
NSString *stringFloat = [NSString stringWithFormat:#"%f", floatNum];
NSString *newString = [stringFloat substringWithRange:NSMakeRange(stringFloat.length - 4, stringFloat.length)];
NSLog(#"%#", newString);
another is something like:
NSString *stringFloat = [NSString stringWithFormat:#"%f", floatNum];
//separates the floating number to
arr[0] = whole number
arr[1] = decimals
NSArray *arr=[str componentsSeparatedByString:#"."];
since you just want to work on the decimal, i think arr[1] is what you need..
NSString *stringDecimals = (NSString *)arr[1];
if ( stringDecimals.length > 4) //check the length of the decimals then cut if exceeds 4 character..
{
stringDecimals = [stringDecimals substringWithRange:NSMakeRange(stringDecimals.length - 4, stringDecimals.length)];
}
NSLog(#"stringDecimals: %#", stringDecimals);

Find substring range of NSString with unicode characters

If I have a string like this.
NSString *string = #"πŸ˜€1πŸ˜€3πŸ˜€5πŸ˜€7πŸ˜€"
To get a substring like #"3πŸ˜€5" you have to account for the fact the smiley face character take two bytes.
NSString *substring = [string substringWithRange:NSMakeRange(5, 4)];
Is there a way to get the same substring by using the actual character index so NSMakeRange(3, 3) in this case?
Thanks to #Joe's link I was able to create a solution that works.
This still seems like a lot of work for just trying to create a substring at unicode character ranges for an NSString. Please post if you have a simpler solution.
#implementation NSString (UTF)
- (NSString *)substringWithRangeOfComposedCharacterSequences:(NSRange)range
{
NSUInteger codeUnit = 0;
NSRange result;
NSUInteger start = range.location;
NSUInteger i = 0;
while(i <= start)
{
result = [self rangeOfComposedCharacterSequenceAtIndex:codeUnit];
codeUnit += result.length;
i++;
}
NSRange substringRange;
substringRange.location = result.location;
NSUInteger end = range.location + range.length;
while(i <= end)
{
result = [self rangeOfComposedCharacterSequenceAtIndex:codeUnit];
codeUnit += result.length;
i++;
}
substringRange.length = result.location - substringRange.location;
return [self substringWithRange:substringRange];
}
#end
Example:
NSString *string = #"πŸ˜€1πŸ˜€3πŸ˜€5πŸ˜€7πŸ˜€";
NSString *result = [string substringWithRangeOfComposedCharacterSequences:NSMakeRange(3, 3)];
NSLog(#"%#", result); // 3πŸ˜€5
Make a swift extension of NSString and use new swift String struct. Has a beautifull String.Index that uses glyphs for counting characters and range selecting. Very usefull is cases like yours with emojis envolved

How to do primary maths with cocoa and cocoa touch

I'm quite new to xcode and am making a app where you put two numbers in to a text input and I don't know how to make xcode to do the adding sum, I tried this but it did not work
self.answer.text = self.label.text + self.label2.text
Does anybody know how to do this.
Use :
NSInteger firstNumber=[self.label.text integerValue];
NSInteger secondNumber=[self.label2.text integerValue];
NSInteger total=firstNumber + secondNumber;
NSString *string=[NSString stringWithFormat:#"%d",total];
self.answer.text = string;
If you want to take double value replace integerValue with doubleValue
Here is another interesting way:
//Some string with expression which was taken from self.label.text
NSString *s = #"2*(2.15-1)-4.1";
NSExpression *expression = [NSExpression expressionWithFormat:s];
float result = [[expression expressionValueWithObject:nil context:nil] floatValue];
NSLog(#"%f", result);
self.answer.text=[NSString stringWithFormat:#"%f",result];

What does NSMakeRange(i, 1) mean?

I just start to learn iOS.
What does "NSMakeRange(i, 1)" mean?
for (int i = 0; i < [name length]; i++)
{
NSRange range = NSMakeRange(i, 1);
NSString *subString = [name substringWithRange:range];
const char *cString = [subString UTF8String];
if (strlen(cString) != 3)
{
return NO;
}
}
Where is it used?
NSMakeRange(i, 1) creates a range with location i and length 1. See the documentation for NSMakeRange and NSString substringWithRange for further information and related functions.
Alt-click the function name in Xcode, you’ll get a reference. The function creates a range that starts at i and has length of 1. In essence, you’re picking individual characters from the string.

Resources