This question already has an answer here:
Multiple arguments in stringWithFormat: “n$” positional specifiers
(1 answer)
Closed 7 years ago.
We need to format a string, but for some localisations we won't output all parameters. But it seems that it doesn't work to output less parameters than passed:
NSString *string = [NSString stringWithFormat: #"%2$#", #"<1111>", #"<22222>"];
NSLog(#"String = %#", string);
Outputs
String = <1111>
although i output the second parameter.
Is this a bug or a feature?
according to the related industrial standard, IEEE specification:
When numbered argument specifications are used, specifying the Nth argument requires that all the leading arguments, from the first to the (N-1)th, are specified in the format string.
which means in other words, you must use the first %1$# parameter in your string formatter somewhere before you address to use the second one – so, it is not a bug at all.
Related
I have a localized string that looks like this:
String(format: "unable_to_reach".localized(), name) //name is a string. I have also tried just "x"
The key/value pair in the localize file looks like this:
"unable_to_reach" = "Unable to reach %1$s";
Now, sometimes this works, othertimes it crashes with the EXC_BAD_ACCESS error. Why is this? isn't %1$s supposed to be used for string values?
The format specifier %1$s is %s with a positional specifier of $1 inserted into it. %s is the format specifier for a null-terminated C string. If you instead pass it a Swift String, bad things will happen. Don't do that. (It will likely cause a buffer overflow if the Swift string does not contain any null bytes.)
You want %# (or %$1#, to preserve the positional specifier.)
See the document on string format specifiers for more information.
Edit:
BTW, you should think about using Swift string interpolation instead:
let unableToReach = "unable_to_reach".localized()
let final = "\(unableToReach) \(name)"
That is more "Swifty".
Note that if you want to use localized placeholders to allow for different word ordering in different languages, you really still need to use String(format:) and the %# (or %1# positional syntax) version.
I've just come across this line in some legacy code I'm editing:
[UIImage imageNamed:#"data/visuals/interface/" #"backgroundViewController"];
^^^^
"Oops, what have I done here?"
I thought I must have accidentally just pasted something in the wrong place, but an undo didn't change that line. Out of curiosity, I built the program and it was successful!
Whaddyaknow? Obj-c has a more succinct way of concatenating string literals.
I added some more tests:
A simple log
NSLog(#"data/visuals/interface/" #"backgroundViewController");
data/visuals/interface/backgroundViewController
In parameters
NSURL *url = [NSURL URLWithString:#"http://" #"test.com" #"/path"];
NSLog(#"URL:%#", url);
URL:http://test.com/path
Using Variables
NSString *s = #"string1";
NSString *s2 = #"string2";
NSLog(#"%#", s s2);
Doesn't compile (not surprised by this one)
Other literals
NSNumber *number = #1 #2;
Doesn't compile
Some questions
Is this string concatenation documented anywhere?
How long has it been supported?
What is the underlying implementation? I expect it will be [s1 stringByAppendingString:s2]
Is it considered good practice by any authoritative body?
This method of concatenating static NSStrings is a compile-time compiler capability that has been available for over ten years. It is usually used to allow long constant strings to be split over several lines. Similar capabilities have been available in "C" for decades.
In the C Programming Language book, 1988 second edition, page 38 describes string concatenation so it has been around for a long time.
Excerpt from the book:
String constants can be concatenated at compile time:
"hello," " world" is equivalent to "hello, world"
This is useful for spitting long strings across several source lines.
Objective-C is a strict superset of "C" so it has always supported "C" string concatenation and my guess is that because of that static NSString concatenation has always been available.
It is considered good practice when used to split a static string across several lines for readability.
This question already has answers here:
NSString is integer?
(5 answers)
Closed 8 years ago.
I want to check that input string is number, is there any way?
Basically strings are recieved from text field so need to check that whether the string in number or not.
There are many solutions discussed in StackOverflow, take a look at:
Finding out whether a string is numeric or not
NSString *yourString = #"...";
[yourString doubleValue] / [yourString floatValue] - this function will return the following:
The floating-point value of the receiver’s text as a double. Returns HUGE_VAL or –HUGE_VAL on overflow, 0.0 on underflow. Returns 0.0 if the receiver doesn’t begin with a valid text representation of a floating-point number.
you can change the keyboard input type of the text field and then you make sure that the input is valid:
yourTextField.keyboardType = UIKeyboardTypeDecimalPad;
This question already has answers here:
How to read input from the keyboard in Objective-C
(3 answers)
Closed 9 years ago.
I'm trying to read an input of type NSString from the user but I couldn't find the format specifier for NSString, I know that %i is for integer variables, but which one is for NSString?
As a result, I created an array of char, read the input from a user, but I couldn't convert it to NSString and XCode gives me as an output weird things like ø¿_ÿ and sometimes (null) I have used many string encodings like (none of them worked):
NSASCIIStringEncoding
NSNEXTSTEPStringEncoding
NSJapaneseEUCStringEncoding
NSUTF8StringEncoding
NSISOLatin1StringEncoding
NSSymbolStringEncoding
NSNonLossyASCIIStringEncoding
NSShiftJISStringEncoding
NSISOLatin2StringEncoding
NSUnicodeStringEncoding
NSWindowsCP1251StringEncoding
NSWindowsCP1252StringEncoding
NSWindowsCP1253StringEncoding
NSWindowsCP1254StringEncoding
NSWindowsCP1250StringEncoding
NSISO2022JPStringEncoding
NSMacOSRomanStringEncoding
NSUTF16StringEncoding
NSUTF16BigEndianStringEncoding
NSUTF16LittleEndianStringEncoding
NSUTF32StringEncoding = 0x8c000100
NSUTF32BigEndianStringEncoding
NSUTF32LittleEndianStringEncoding
NSProprietaryStringEncoding
Could anyone tell me why?
This is my code:
//I have declared a class and called it Labtop
Labtop *myLabtop;
myLabtop = [[Labtop alloc] init];
char input[30];
NSLog(#"Hello,please enter which brand you will use this time:\n");
input[29] = getchar();// read the input from the user
NSString *b =[[NSString alloc] initWithCString:input encoding:NSISOLatin1StringEncoding];//convert from array char to NSString
[myLabtop labtopBrand:b];//labtopBrand fund will print what the user has entered
The result is:
Hello,please enter which brand you will use this time:
MacBook //this is the user's input
I will use ø¿_ÿ//this what Xcode shows me as an output Program ended
with exit code: 0
Format specifier for NSString is %#
There are some problems here. First off, getchar() returns one character, not a whole string. Second, this line:
input[29] = getchar();// read the input from the user
Just assigns the last character in input to the character the user types, which probably isn’t what you want at all. Maybe you meant gets()? Except you really shouldn’t use that since it has no bounds checking, and you still wouldn’t want to assign the results to the thirtieth character in your array. Maybe look at getline() instead.
Also, you’ll probably want to specify NSUTF8StringEncoding.
Good luck, keep experimenting!
I receive a NSDictionary using AFNetworking. that dictionary has many values.
one of these I think is an INT or NSNumber, dont know what's the automatic conversion. The numbers expected are 2 and 3 but somehow I always get a very long number... I tried all the things I know and could find but I cant get it to show the right number in the
cell.numberOfLikes.text
These are all the things I've tried with no success. I would appreciate some guidance
NSLog(#"%i",_myDownloadedInfo[#"routines"][indexPath.row][#"routine"][#"routineDownloads"]);
NSLog(#"%i",[NSNumber numberWithInt:_myDownloadedInfo[#"routines"][indexPath.row][#"routine"][#"routineDownloads"]]);
cell.numberOfDownloads.text = [NSString stringWithFormat:#"%i",_myDownloadedInfo[#"routines"][indexPath.row][#"routine"][#"routineDownloads"]];
cell.numberOfLikes.text =_myDownloadedInfo[#"routines"][indexPath.row][#"routine"][#"routineDownloads"]);
The %i format specified is for basic, integer data types. Since you have (or try to create) an NSNumber object, you can use %# to log it. %# is used for Objective-C objects in format specifiers.
But that doesn't help when you want to assign the NSNumber to your text field. You need to convert the number to an NSString. Ideally you should use an NSNumberFormatter to convert the NSNumber to an NSString.
Do this:
NSNumber *likesNumber = _myDownloadedInfo[#"routines"][indexPath.row][#"routine"][#"routineDownloads"];
NSString *numberText = [NSString stringWithFormat:#"%d". [likesNumber intValue]];
NSLog(#"Number: %#", numberText);
cell.numberOfLikes.text = numberText;
Several points.
First, the first argument of NSLog is a format specifier. It is entirely equivalent to the format specifier used in [NSString stringWithFormat:] and there's rarely a need for both.
Next, data in Objective-C can be individual int values, char values, char* values (which are C strings), float values, and Objective-C object values. (Plus a few assorted long, unsigned, etc values that you rarely use.)
An NSString is an Objective-C object, as is an NSNumber. An NSInteger, on the other hand, is an alias for a particular size of int and generally interchangeable with int. Very often people get confused with NSNumber (object) vs NSInteger (scalar int) -- they are not the same.
In an NSLog or stringWithFormat specifier you use % followed by one or more characters to indicate how a value (in the following list of values) is to be formatted. %d or %i is an int. (%d is preferred.) %f is a simple floating-point value (but the formatting of these can get more complicated). %s is a C-style string (ie, a char* value). %# is used for formatting an Objective-C object. You use %#, in particular, to format an NSString or (to get the default presentation) an NSNumber.
It's important to understand how %# works in a format string. When the format interpreter encounters it, it interprets the next item in the value list as a pointer to an Objective-C object and invokes the description method of that object. An NSString just returns itself as the result of description, while an NSNumber returns an NSString that represents the character representation of the number's value. Other objects (all Objective-C objects support description, if only by default) return either a simple identification of the object type or a representation of the object's internal values.
So, if you have an NSNumber, you can directly format it with %#, or you can extract the numeric value (eg, [someNSNumber intValue]) and then format that value appropriately (eg, %d). A reason for doing the latter would be if you wanted to specify the column width for the number (eg, %5d, to format the number into a 5-position field).
See here for some (gory) details on the various format specifiers.
Hint: %i is the conversion specifier for int.
one of these I think is an INT or NSNumber, dont know what's the automatic conversion
Now go back and read the documentation of NSArray, think about whether or not it can contain ints, then proceed reading.
So the objects in the dictionary are instances of NSNumber -> they're Objective-C objects -> they are implemented using pointers. Poor NSLog() tries to convert the pointer value to an integer. Either use %# to get the description of the number, or %i and [theNumber intValue] to print its integer value.