Localizing difficulties with latitude and longitude - ios

In my app there is some code to retrieve a position. The standard display method is as a float. (54.23456) I was able to "convert" it to a format with degrees, minutes an seconds. The characters (N)orth, (S)outh (E)ast and (W)est are also added. See my code:
double actLat = [[latitude text]doubleValue];
int latSeconds = actLat * 3600;
int latDegrees = latSeconds / 3600;
latSeconds = abs(latSeconds % 3600);
int latMinutes = latSeconds / 60;
latSeconds %= 60;
char latChar = (latitude > 0) ? 'N' : 'S';
double actLon = [[longitude text]doubleValue];
int lonSeconds = actLon * 3600;
int lonDegrees = lonSeconds / 3600;
lonSeconds = abs(lonSeconds % 3600);
int lonMinutes = lonSeconds / 60;
lonSeconds %= 60;
char lonChar = (longitude > 0) ? 'E' : 'W';
NSString *actPosition = [[NSString alloc]initWithFormat:#"Actual: %i° %i' %i\" %c" " " #"%i° %i' %i\" %c \n", latDegrees, latMinutes, latSeconds, latChar,lonDegrees, lonMinutes, lonSeconds, lonChar];
NSString* tempActPos = NSLocalizedString(actPosition, #"");
_actualPosition.text = tempActPos;
Right now I'm trying to localize the NSString *actPosition. Actual -> Huidig (in dutch) then the position and the characters (N)oord, Z(uid), (O)ost, (W)est.
I'm completely stuck here. Reading up for several days now on localization but for now I'm unable to understand it apparently. Please advice.

I changed my code. I added separate localizable strings for the words Actual (NSLocalizedString (#"WordWatched",#"") and added this newly created string in a NSString object to show on my view.
Here is a piece of sample code:
NSString *lonStringLocal = NSLocalizedString((valueLon > 0) ? #"East" : #"West", #"");
tempPos = [[CLLocation alloc] initWithLatitude:valueLat longitude:valueLon];
NSString *watchedPosWord = NSLocalizedString (#"WordWatched", #"");
NSString *recPosition = [[NSString alloc]initWithFormat:#"%# %i° %i' %i\" %#" " " #"%i° %i' %i\" %# \n", watchedPosWord, latDegrees, latMinutes, latSeconds, latStringLocal,lonDegrees, lonMinutes, lonSeconds, lonStringLocal];

Related

Drupal and Objective C Base 64 mismatch

I have this sequence of bytes (printed from an HTML, so apologizes for the ugly format)
193<br/>250<br/>194<br/>129<br/>62<br/>60<br/>12<br/>171<br/>199<br/>96<br/>13<br/>125<br/>166<br/>175<br/>80<br/>85<br/>137<br/>29<br/>15<br/>189<br/>33<br/>231<br/>237<br/>98<br/>165<br/>35<br/>75<br/>250<br/>181<br/>150<br/>35<br/>175<br/>129<br/>174<br/>13<br/>13<br/>121<br/>229<br/>30<br/>173<br/>112<br/>210<br/>2<br/>165<br/>110<br/>113<br/>141<br/>166<br/>102<br/>105<br/>33<br/>82<br/>220<br/>233<br/>118<br/>36<br/>73<br/>88<br/>196<br/>152<br/>15<br/>231<br/>164<br/>119<br/>
When I use the Drupal function: [_password_base64_encode][1] I get the following base64 string:
/fjk/u1DAgulUpETay8IJZM5DoP6briMZCmGuLfZXwOUiqE1tJi5h0bo0IePlpcdaZK6GlRuqFGGMFAaDQCdr/
But when I use this sequence of bytes in my iOS application with the code:
NSString *base64Encoded = [hash base64EncodedStringWithOptions:0];
I get:
wfrCgT48DKvHYA19pq9QVYkdD70h5+1ipSNL
Why this behavior?
Thanks
Ported the function _password_base64_encode to iOS:
- (NSString*)drupalBase64PasswordEncode:(NSData*)data {
NSUInteger count = [data length];
int i = 0;
NSString *itTo64String = #"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char *itTo64 = [itTo64String cStringUsingEncoding:NSUTF8StringEncoding];
char *input = [data bytes];
NSMutableString *output = [[NSMutableString alloc] init];
do {
unsigned char value = (unsigned char)input[i++];
int value2;
unsigned char toInsert = itTo64[value & 0x3f];
[output appendString:[NSString stringWithFormat:#"%c" , toInsert]];
if (i < count) {
value2 = value | ((unsigned char)input[i] << 8);
}
toInsert = itTo64[(value2 >> 6) & 0x3f];
[output appendString:[NSString stringWithFormat:#"%c" , toInsert]];
if (i++ >= count) {
break;
}
if (i < count) {
value2 = value2 | ((unsigned char)input[i] << 16);
}
toInsert = itTo64[(value2 >> 12) & 0x3F];
[output appendString:[NSString stringWithFormat:#"%c" , toInsert]];
if (i++ >= count) {
break;
}
toInsert = itTo64[(value2 >> 18) & 0x3F];
[output appendString:[NSString stringWithFormat:#"%c" , toInsert]];
}while(i < count);
return output;
}
The most likely explanation is that you're encoding junk along with your intended string - can you dump the actual string that gets encoded, such as
$string = ' ... ';
var_dump($string);
$base64_string = _password_base64_encode($string);
var_dump($string);
It is most likely that you are including different characters ( breaks, newlines in different format, etc ) than you intended when encoding.
In addition, you might want to compare the output with PHP's native base64_encode function, and compare results.

conversion of decimal to binary output

I am facing problem with the objective c code to convert decimal to binary. When I enter small values it shows me the output.
For e.g. 12 -> 1010
But when I enters large numbers, it shows me the output as "10..." (includes dots in the output)
Please help me.
My program is as follows:
NSUInteger x = [newDec integerValue];
//int y[30];
int i=0;
int m =1;
while (x != 0) {
int mod = x % 2;
x /= 2;
i = i + mod * m;
m = m * 10;
string = [NSString stringWithFormat:#"%d", i];
}
There are two problems with your code.
1) Your label size is perhaps not able to accommodate your string. So check the length of it.
2) Your code will not support the conversion if value of x is large. The reason is that int has limited capacity. Check this question regarding memory size of in-built variable. So, consider making your string mutable and add 0s or 1s in it. I am attaching my snippet of code.
NSMutableString *string = [[NSMutableString alloc] init];
while (x != 0) {
int mod = x % 2;
x /= 2;
[string insertString:[NSString stringWithFormat:#"%d", mod] atIndex:0];
}
NSLog(#"String = %#", string);

Generate any random NSInteger with exactly 18 digits

I tried this:
NSInteger numberFinal = 100000000000000000 + ((float)arc4random() / UINT32_MAX) * (999999999999999999 - 100000000000000000);
but it returns zero... I don't want to specify the range, but just want any number with 18 digits...
For your requirement, as #duDE mentioned you can't use a NSInteger to save 18 digit number, but there is a solution using NSString.
NSString *eighteenDigitNumberString = [[NSNumber numberWithInt:1 + arc4random_uniform(9)] stringValue];
for (int i = 0; i < 17; i++) {
eighteenDigitNumberString = [eighteenDigitNumberString stringByAppendingString:[[NSNumber numberWithInt:arc4random_uniform(10)] stringValue]];
}
NSLog(#"eighteenDigitNumberString : %#", eighteenDigitNumberString);
There we go, no need to explain everything is straightforward.
EDITED: if you really want a long long value you can do so:
long long eighteenDigitNumberLongLong = [eighteenDigitNumberString longLongValue];
EDITED: To avoid the leading 0 the initial string has been initiated with a non-zero number and the loop is running only 17 times.
As the maximum value of an NSInteger is NSIntegerMax, you cann't use NSInteger for your purpose:
enum {
NSNotFound = NSIntegerMax
};
Prior to OS X v10.5, NSNotFound was defined as 0x7fffffff.
This is 2147483647 (decimal).
If you need "any number" with 18 digits (as #A-Live assumes), you can take NSFloat for example.
A 18 digit integer will require a long long type.
Create two 9 digit random numbers, multiple one by 10^9 and add to the other.
const u_int32_t digits9 = 1000000000;
u_int32_t ms = arc4random_uniform(digits9);
u_int32_t ls = arc4random_uniform(digits9);
unsigned long long random18 = ((unsigned long long)ms * digits9) + ls;
NSLog(#"Example random18: %018llu", random18);
Output:
Example random18: 501895974656079554
If the number must have a leading non zero digit:
const u_int32_t digits81 = 100000000;
const u_int32_t digits89 = 900000000;
const u_int32_t digits9 = 1000000000;
u_int32_t ms = arc4random_uniform(digits89) + digits81;
u_int32_t ls = arc4random_uniform(digits9);
unsigned long long random18 = ((unsigned long long)ms * digits9) + ls;
If you need strictly 18 digits it would be better to use this code:
NSString *stringNumber = [NSString string];
for (int i = 0; i < 18; i++) {
if (i == 0) {
stringNumber = [stringNumber stringByAppendingString:[NSString stringWithFormat:#"%#", #(arc4random_uniform(9) + 1)]];
} else {
stringNumber = [stringNumber stringByAppendingString:[NSString stringWithFormat:#"%#", #(arc4random_uniform(10))]];
}
}
long long value = stringNumber.longLongValue;
You need the first condition because with the possibility of 0.1 you may receive 0 as the first digit, then your 18-digit integer would become 17-digit, with 0.01 possibility - 16-digit integer etc.
You're getting into unsigned long long territory...
#define ARC4RANDOM_MAX 0x100000000
float val = ((double)arc4random() / ARC4RANDOM_MAX);
unsigned long long numberToAdd = val * (900000000000000000-1);
unsigned long long numberFinal = 100000000000000000 + numberToAdd;
NSLog( #"value = %llu", numberFinal);

iOS Calculating number don't show decimals

When I calculate with numbers in my App, there are no decimals in my output!
this is the code I am using:
int Vijfhonderdmeter = [_VijfHonderd.text intValue];
int vijftienhonderdmeter = [_vijftienhonderd.text intValue];
int vijfdeeldrie = vijftienhonderdmeter / 3;
int puntentotaal = Vijfhonderdmeter + vijfdeeldrie;
_PuntenTotaal.text = [NSString stringWithFormat:#"%d",puntentotaal];
The real output should be 87,18667, but my _Puntentotaal label only shows 87.
Has anyone got a solution?
By the way:
(_VijfHonderd.text intValue = 44.05).
(_vijftienhonderd.text intValue = 129.41).
Thank you for your time and help :)
3 problems:
1) You are using integer division with integer value. If you want floating point numbers you need to floating point values and do floating point division:
double Vijfhonderdmeter = [_VijfHonderd.text doubleValue];
double vijftienhonderdmeter = [_vijftienhonderd.text doubleValue];
double vijfdeeldrie = vijftienhonderdmeter / 3.0;
2) You are formatting the result using %d. Use %f with the double values.
3) Use NSNumberFormatter, not stringWithFormat: to format the numbers. This will ensure they look correct for all users based on their locale.
Your code will always return a non decimal value as you are operating with int datatype.
int Vijfhonderdmeter = [_VijfHonderd.text intValue]; here you are getting a non decimal value & later also you are operating it with other non-decimal values. To get decimal values, you should use `double` or `float` datatype.
For now,try this:
float Vijfhonderdmeter = [_VijfHonderd.text floatValue];
float vijftienhonderdmeter = [_vijftienhonderd.text floatValue];
float vijfdeeldrie = vijftienhonderdmeter / 3;
float puntentotaal = Vijfhonderdmeter + vijfdeeldrie;
_PuntenTotaal.text = [NSString stringWithFormat:#"%f",puntentotaal];
Refer this link for more knowledge about premitive datatypes in objective-C

iOS Format Number with Abbreviations [duplicate]

Is there a simple way to do something like..
[NSMagicDataConverter humanStringWithBytes:20000000]
..which would return "19.1MB"?
Starting in OS X 10.8 and iOS 6, you can use NSByteCountFormatter.
Your example would look like this:
[NSByteCountFormatter stringFromByteCount:20000000 countStyle:NSByteCountFormatterCountStyleFile];
I would mush this into an NSFormatter subclass.
#import <Foundation/Foundation.h>
#interface SOFileSizeFormatter : NSNumberFormatter
{
#private
BOOL useBaseTenUnits;
}
/** Flag signaling whether to calculate file size in binary units (1024) or base ten units (1000). Default is binary units. */
#property (nonatomic, readwrite, assign, getter=isUsingBaseTenUnits) BOOL useBaseTenUnits;
#end
static const char sUnits[] = { '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
static int sMaxUnits = sizeof sUnits - 1;
#implementation SOFileSizeFormatter
#synthesize useBaseTenUnits;
- (NSString *) stringFromNumber:(NSNumber *)number
{
int multiplier = useBaseTenUnits ? 1000 : 1024;
int exponent = 0;
double bytes = [number doubleValue];
while ((bytes >= multiplier) && (exponent < sMaxUnits)) {
bytes /= multiplier;
exponent++;
}
return [NSString stringWithFormat:#"%# %cB", [super stringFromNumber: [NSNumber numberWithDouble: bytes]], sUnits[exponent]];
}
#end
Usage:
NSString *path = ...; // path to a file of 1,500,000 bytes
NSString *sizeString = nil;
NSNumber *sizeAttrib = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:NULL]objectForKey:NSFileSize];
SOFileSizeFormatter *sizeFormatter = [[[SOFileSizeFormatter alloc] init] autorelease];
[sizeFormatter setMaximumFractionDigits:2];
sizeString = [sizeFormatter stringFromNumber:sizeAttrib];
// sizeString ==> #"1.43 MB"
[sizeFormatter setUseBaseTenUnits:YES];
sizeString = [sizeFormatter stringFromNumber:sizeAttrib];
// sizeString ==> #"1.5 MB"
Here's my own take on the problem:
enum {
kUnitStringBinaryUnits = 1 << 0,
kUnitStringOSNativeUnits = 1 << 1,
kUnitStringLocalizedFormat = 1 << 2
};
NSString* unitStringFromBytes(double bytes, uint8_t flags){
static const char units[] = { '\0', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
static int maxUnits = sizeof units - 1;
int multiplier = (flags & kUnitStringOSNativeUnits && !leopardOrGreater() || flags & kUnitStringBinaryUnits) ? 1024 : 1000;
int exponent = 0;
while (bytes >= multiplier && exponent < maxUnits) {
bytes /= multiplier;
exponent++;
}
NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
if (flags & kUnitStringLocalizedFormat) {
[formatter setNumberStyle: NSNumberFormatterDecimalStyle];
}
// Beware of reusing this format string. -[NSString stringWithFormat] ignores \0, *printf does not.
return [NSString stringWithFormat:#"%# %cB", [formatter stringFromNumber: [NSNumber numberWithDouble: bytes]], units[exponent]];
}
By default (if 0 is passed for flags), it will output SI units (base ten). You can set kUnitStringBinaryUnits to select binary (base two) units suitable for memory, or kUnitStringOSNativeUnits to have the unit type selected automatically based on OS version (pre-Leopard gets base two, post-Leopard gets base ten). Setting kUnitStringLocalizedFormat formats the string based on the user's current locale. For example:
unitStringFromBytes(1073741824, 0); // → "1.07 GB"
unitStringFromBytes(1073741824, kUnitStringBinaryUnits); // → "1 GB"
unitStringFromBytes(1073741824, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "1.07 GB" (In Mac OS 10.6)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12,345.68 YB" (In Mac OS 10.6, in the US)
unitStringFromBytes(12345678901234567890123456789, kUnitStringOSNativeUnits | kUnitStringLocalizedFormat); // → "12.345,68 YB" (In Mac OS 10.6, in Spain)
Here's the helper function required for OS-native units:
BOOL leopardOrGreater(){
static BOOL alreadyComputedOS = NO;
static BOOL leopardOrGreater = NO;
if (!alreadyComputedOS) {
SInt32 majorVersion, minorVersion;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
Gestalt(gestaltSystemVersionMinor, &minorVersion);
leopardOrGreater = ((majorVersion == 10 && minorVersion >= 5) || majorVersion > 10);
alreadyComputedOS = YES;
}
return leopardOrGreater;
}
NSString *stringFromFileSize(NSInteger theSize)
{
/*
From http://snippets.dzone.com/posts/show/3038 with slight modification
*/
float floatSize = theSize;
if (theSize<1023)
return([NSString stringWithFormat:#"%i bytes",theSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:#"%1.1f KB",floatSize]);
floatSize = floatSize / 1024;
if (floatSize<1023)
return([NSString stringWithFormat:#"%1.1f MB",floatSize]);
floatSize = floatSize / 1024;
return([NSString stringWithFormat:#"%1.1f GB",floatSize]);
}
Here is a more Objective C-like function (uses NSNumber, NSArray, NSStirng, etc...) for doing this conversion.
This is based on Sidnicious's answer, so a big thanks for the initial work done there. Also based on Wikipedia articles.
Use it generally like this: [HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue]].
But, it looks like you want SI units with a 1024 multiplier so you would use it like this: [HumanReadableDataSizeHelper humanReadableSizeFromBytes:[NSNumber numberWithDouble:doubleValue] useSiPrefixes:YES useSiMultiplier:NO]
The reason I default to binary prefixes (ki, Mi) is because those seem to be the most appropriate unit prefix set to use for sizes of data on a computer. What you requested was the SI unit prefixes but using a multiplier of 1024, technically incorrect. Though I will note that SI prefixes for multiples of 1024 is fairly common and binary prefixes are not well accepted (according to Wikipedia).
HumanReadableDataSizeHelper.h
#interface HumanReadableDataSizeHelper : NSObject
/**
#brief Produces a string containing the largest appropriate units and the new fractional value.
#param sizeInBytes The value to convert in bytes.
This function converts the bytes value to a value in the greatest units that produces a value >= 1 and returns the new value and units as a string.
The magnitude multiplier used is 1024 and the prefixes used are the binary prefixes (ki, Mi, ...).
*/
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes;
/**
#brief Produces a string containing the largest appropriate units and the new fractional value.
#param sizeInBytes The value to convert in bytes.
#param useSiPrefixes Controls what prefix-set is used.
#param useSiMultiplier Controls what magnitude multiplier is used.
This function converts the bytes value to a value in the greatest units that produces a value >= 1 and returns the new value and units as a string.
When useSiPrefixes is true, the prefixes used are the SI unit prefixes (k, M, ...).
When useSiPrefixes is false, the prefixes used are the binary prefixes (ki, Mi, ...).
When useSiMultiplier is true, the magnitude multiplier used is 1000
When useSiMultiplier is false, the magnitude multiplier used is 1024.
*/
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes useSiPrefixes:(BOOL)useSiPrefixes useSiMultiplier:(BOOL)useSiMultiplier;
#end
HumanReadableDataSizeHelper.m
#implementation HumanReadableDataSizeHelper
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes
{
return [self humanReadableSizeFromBytes:sizeInBytes useSiPrefixes:NO useSiMultiplier:NO];
}
+ (NSString *)humanReadableSizeFromBytes:(NSNumber *)sizeInBytes useSiPrefixes:(BOOL)useSiPrefixes useSiMultiplier:(BOOL)useSiMultiplier
{
NSString *unitSymbol = #"B";
NSInteger multiplier;
NSArray *prefixes;
if (useSiPrefixes)
{
/* SI prefixes
http://en.wikipedia.org/wiki/Kilo-
kilobyte (kB) 10^3
megabyte (MB) 10^6
gigabyte (GB) 10^9
terabyte (TB) 10^12
petabyte (PB) 10^15
exabyte (EB) 10^18
zettabyte (ZB) 10^21
yottabyte (YB) 10^24
*/
prefixes = [NSArray arrayWithObjects: #"", #"k", #"M", #"G", #"T", #"P", #"E", #"Z", #"Y", nil];
}
else
{
/* Binary prefixes
http://en.wikipedia.org/wiki/Binary_prefix
kibibyte (KiB) 2^10 = 1.024 * 10^3
mebibyte (MiB) 2^20 ≈ 1.049 * 10^6
gibibyte (GiB) 2^30 ≈ 1.074 * 10^9
tebibyte (TiB) 2^40 ≈ 1.100 * 10^12
pebibyte (PiB) 2^50 ≈ 1.126 * 10^15
exbibyte (EiB) 2^60 ≈ 1.153 * 10^18
zebibyte (ZiB) 2^70 ≈ 1.181 * 10^21
yobibyte (YiB) 2^80 ≈ 1.209 * 10^24
*/
prefixes = [NSArray arrayWithObjects: #"", #"ki", #"Mi", #"Gi", #"Ti", #"Pi", #"Ei", #"Zi", #"Yi", nil];
}
if (useSiMultiplier)
{
multiplier = 1000;
}
else
{
multiplier = 1024;
}
NSInteger exponent = 0;
double size = [sizeInBytes doubleValue];
while ( (size >= multiplier) && (exponent < [prefixes count]) )
{
size /= multiplier;
exponent++;
}
NSNumberFormatter* formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; // Uses localized number formats.
NSString *sizeInUnits = [formatter stringFromNumber:[NSNumber numberWithDouble:size]];
return [NSString stringWithFormat:#"%# %#%#", sizeInUnits, [prefixes objectAtIndex:exponent], unitSymbol];
}
#end
You can use FormatterKit and its TTTUnitOfInformationFormatter class:
https://github.com/mattt/FormatterKit
It is also available through CocoaPods with:
pod 'FormatterKit', '~> 1.1.1'
- (id)transformedValue:(id)value
{
double convertedValue = [value doubleValue];
int multiplyFactor = 0;
NSArray *tokens = #[#"bytes",#"KB",#"MB",#"GB",#"TB"];
while (convertedValue > 1024) {
convertedValue /= 1024;
multiplyFactor++;
}
return [NSString stringWithFormat:#"%4.2f %#",convertedValue, tokens[multiplyFactor]];
}
I know the questions is for Obj C but if anyone looking for a swift version:
public static func fileSizeDisplay(fromBytes:Int) -> String {
let display = ["bytes","KB","MB","GB","TB","PB"]
var value:Double = Double(fromBytes)
var type = 0
while (value > 1024){
value /= 1024
type = type + 1
}
return "\(String(format:"%g", value)) \(display[type])"
}

Resources