Efficiency NSString vs NSInteger/int - only for textual representation - ios

I'd like to know if it would make any sense to cast/convert a number, parsed from a csv file, e.g. customer id, to a NSString?
Or maybe better a simple int? As I'm quite new to obj-c, I'm not really sure, wether to consistently use the NSxyz types, or use what I'm used to, coming from Java/C/C++.
Actually the value only is stored in a variable, and then loaded into some textfields (which again would imply a conversion back to NSString I guess?).
Would there be any benefit in less memory being used? Let's assume the ids had 6 digits, parsing roughly 10'000-100'000 customers. Same would apply to smaller numbers, e.g. the addresses street number.

In a string, 1 letter == 1 byte, so if you have 6 digits, you are occupying 6 bytes.
An int instead takes generally 2 (short), 3 or 4 (long) bytes. It can arrive also to 8 bytes with an int_64. But, you are limited because for example in the 2 byte case (16 bit) you can consider 2^16 numbers.
In your case you could use an int, but i would use an NSString, also because you need it in your textfield.
An NSInteger is an int. An NSUInteger is an unsigned int.
An NSNumber is an Object (so no primitive) which can store an int, a float, a double or a boolean. So you can store many type of primitive in this type of variable and then use the appropriate:
[number floatValue];
[number boolValue];
...

Related

What type is NSString and how many bytes?

I am new to objective c. Trying to find out the type of NSString in Objective C. I use the sizeof() method from C and lengthOfBytesUsingEncoding method using UTF8 encoding from NSString.
NSString *test=#"a";
NSLog(#"LengthOfBytesUsingEncoding: %lu bytes", [test lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
printf("NSString: %lu\n", sizeof(test));
This is gonna give me in Console
LengthOfBytesUsingEncoding: 1 bytes
and NSString: 8 bytes
What is the difference between the two results?
Why LengthOfBytesUsingEncoding returns 1 bytes and sizeof method returns 8 bytes?
What is the type of NSString? Int, float, long, long double?
The length of bytes gives you the length of text content using the specified encoding. In this case the string contains a single character, which in UTF8 is encoded as 1 byte.
The sizeof gives you the size of the variable's type, which, in this case is a pointer to NSString. The size of all pointers on 64bit architectures is 8 bytes. It's essentially the size of memory address, where NSString data is stored. sizeof is not a method and it's not even a function. It's an operator. The result is known at compile-time.
In other words:
The actual string contents are stored in memory in a format that is opaque and shouldn't interest you.
On another place in memory, there is NSString data structure that contains a pointer to the contents. You can get the size of this structure using sizeof(NSString) (actually the size will differ depending on concrete NSString subclass, e.g. NSMutableString, NSPlaceholderString etc).
Your variable contains a pointer to NSString, that is, its size is sizeof(NSString*), which is always 8 bytes.
sizeof operator shouldn't interest you much in Objective-C, unless you are dealing with pointer arithmetics, which should be rather rare.

Getting Garbage value while convert into long Objective -C

I am trying to convert NSString to long but I am getting garbage value. Below is my code :
long t1 = [[jsonDict valueForKeyPath:#"detail.amount"]doubleValue] * 1000000000000000000;
long t2 = [[jsonDict valueForKeyPath:#"detail.fee"]doubleValue] * 10000000000000000;
NSLog(#"t1: %ld",t1);
NSLog(#"t2: %ld",t2);
detail.amout = 51.74
detail.fee = 2.72
O/P :
t1: 9223372036854775807 (Getting Garbage value here)
t2: 27200000000000000 (Working fine)
Thanks in advance.
Each number types (int, long, double, float) has limits. For your long 64 bit (because your device is 64bit) number the upper limit is :9,223,372,036,854,775,807 (see here: https://en.wikipedia.org/wiki/9,223,372,036,854,775,807)
In your case, 51.74 * 1,000,000,000,000,000,000 =
51,740,000,000,000,000,000
While Long 64bit only has a maximum of
9,223,372,036,854,775,807
So an overflow happens at 9,223,372,036,854,775,808 and above. Which is what your calculation evaluates into.
Also to note, that what you are doing will also cause problem if you only cater for 64bit long range, because what happens when your app runs on a 32bit (like iPhone 5c or below)?
Generally a bad idea to use large numbers, unless you're doing complex maths. If number accuracies are not critical, then you should consider simplifying the number like 51,740G (G = Giga). etc.
It's because you're storing the product to long type variables t1 and t2.
Use either float or double, and you'll get the correct answer.
Based on C's data types:
Long signed integer type. Capable of containing at least the
[−2,147,483,647, +2,147,483,647] range; thus, it is at least 32
bits in size.
Ref: https://en.wikipedia.org/wiki/C_data_types
9223372036854775807 is the maximum value of a 64-bit signed long. I deduce that [[jsonDict valueForKeyPath:#"detail.amount"]doubleValue] * 1000000000000000000 is larger than the maximum long value, so when you cast it to long, you get the closest value that long can represent.
As you read, it is not possible with long. Since it looks like you do finance math, you should use NSDecimalNumber instead of double to solve that problem.

Convert string to only byte in Objective-C

I have a problem, want to convert a decimal byte to a hexadecimal byte, pass it to string to be able to make the conversion more quickly but now my question is as follows. Know how can I convert a string to a byte the string
example:
NSString *var = #"0x21";
To
Byte cmd = 0x21;
You can convert an instance of NSString to an instance of NSData with -dataUsingEncoding:allowLossyConversion: or to a C array with -getCString:maxLength:encoding:(NSStringEncoding)encoding.
In both cases you have a pointer to an object resp. to a char[]. Putting that pointer into the Byte array, will convert the pointer and copy its value, but not the referenced data.
Additionally: In your example you try to save 0.4 (zero – period – four) and 0.5 (zero – period – 5) into a Byte[]. This will not do the job, you probably expect. It will convert the value to a value of type Byte (an integer type!) and store that value. Integer values greater than 255 will be converted, too.
Therefore you have to use a mutable data object and concat the binary representation of the different types individually.

In Core Data which attribute type (Integer 16 / 32 / 64) should I use to store small numbers? [duplicate]

I want to keep NSUInteger into my core data and I don't know which type should I use (integer 16, 32, 64) to suit the space needed.
From my understanding:
Integer 16 can have minimum value of -32,768 to 32,767
Integer 32 can have minimum value of -2,147,483,648 to 2,147,483,647
Integer 64 can have minimum value of -very large to very large
and NSUInteger is type def of unsigned long which equal to unsigned int (Types in objective-c on iPhone)
so If I convert my NSUInteger to NSNumber with numberWithUnsignedInteger: and save it as NSNumber(Integer 32) I could retrieve my data back safely right?
Do you really need the entire range of an NSUInteger? On iOS that's an unsigned 32 bit value, which can get very large. It will find into a signed 64 bit.
But you probably don't need that much precision anyway. The maximum for a uint32_t is UINT32_MAX which is 4,294,967,295 (4 billion). If you increment once a second, it'll take you more than 136 years to reach that value. Your user's iPhone won't be around by then... :)
If at all possible, when writing data to disk or across a network, it's best to be explicit about the size of value. Instead of using NSUInteger as the datatype, use uint16_t, uint32_t, or uint64_t depending on the range you need. This then naturally translates to Integer 16, 32, and 64 in Core Data.
To understand why, consider this scenario:
You opt to use Integer 64 type to store your value.
On a 64-bit iOS device (eg iPhone 6) it stores the value 5,000,000,000.
On a 32-bit iOS device this value is fetched from the store into an NSUInteger (using NSNumber's unsignedIntegerValue).
Now because NSUInteger is only 32-bits on the 32-bit device, the number is no longer 5,000,000,000 because there aren't enough bits to represent 5 billion. If you had swapped the NUInteger in step 3 for uint64_t then the value would still be 5 billion.
If you absolutely must use NSUInteger, then you'll just need to be wary about the issues described above and code defensively for it.
As far as storing unsigned values into the seemingly signed Core Data types, you can safely store them and retrieve them:
NSManagedObject *object = // create object
object.valueNumber = #(4000000000); // Store 4 billion in an Integer 32 Core Data type
[managedObjectContext save:NULL] // Save value to store
// Later on
NSManagedObject *object = // fetch object from store
uint32_t value = object.valueNumber.unsignedIntegerValue; // value will be 4 billion

Handling 64 bit integers on a 32 bit iPhone

I would like to handle 64 bit unsigned integers on a iPhone 4s (which of course has a 32 bit ARM 6 processor).
When trying to work with 64 bit unsigned integers, e.g. Twitter IDs, I have the following problem:
// Array holding the 64 bit integer IDs of the Tweets in a timeline:
NSArray *Ids =[timelineData valueForKeyPath:#"id"];
// I would like to get the minimum of these IDs:
NSUInteger minId = (NSUInteger) Ids.lastObject;
The array Ids contains the following numbers (= Tweet Ids):
491621469123018752,
491621468917477377,
491621465544851456,
491621445655867393
However, minId returns the incorrect value of 399999248 (instead of 491621445655867393)
How can I find the minimum or the last object in an Array of 64 bit integers on an iPhone 4s?
You need to use a type that is always 64 bit instead of NSUInteger. You can use uint64_t or unsigned long long. You also need to get the integer value out of the NSNumber (arrays can't store C types). to do this you need to call
uint64_t minID = [Ids.lastObject longLongValue];
Edit
Changed to use uint64_t in example code as it has been correctly pointed out this shows your intent better.

Resources