NSLog pointer syntax - iphone

I'm a little bit confused about the syntax of NSLog. For example,
NSString *nameString = #"Name";
NSLog(#"nameString is: %#", nameString);
If my understanding is correct (which it very well may not be), then nameString is defined to be a pointer to a String. I thought then that this would print the memory address that nameString holds, not the value of that address. So, if that is true, then in the NSLog statement, to get the value of the pointer, shouldn't we need to use the asterisk notation to access what nameString points to like this:
NSLog(#"nameString is: %#", *nameString);
?
It has been a little while since programming in C, but since Objective-C is a superset of C I thought they would behave similarly.
An explanation would be greatly appreciated! Thanks!

The command %# is like "shortcut" that calls the method -description on the receiver. For an NSString it simply display the string itself, since is inherited from NSObject you can override it, very usefull if you create for own class. In that case the default behaviur is print the value of the pointer. If you want to print the address of the pointer in the string just replace with :
NSLog(#"nameString is: %p", nameString)

I think that you use an asterisk only to declare a pointer. Then, you only use the name you decided. For example:
NSString *foo = [[NSString alloc] initWithString:#"Hello"];
NSLog(#"%#", foo);
Correct me if I am wrong :)

It's an object and NSLog is a function that uses its format specifiers to determine what to do with the argument. In this case the specifier is %# which tells NSLog to call a method on an object.
Normally this will call the method "description" which returns an NSString but it probably does respondsToMethod first and falls through to some other string methods.

Related

is there any way to get the return value from a method by using #selector except using double pointer?

I don't want to use double pointer. I am using a function in simpler form as below.
-(NSString *) getName
{
return name;
}
So what is the correct way to take the returned NSString *?
By using #selector(getName) i am not able to get the returned value name.
Thank you in advance
You should use NSInvocation object instance for calling a selector and resolving returned result.
performSelector: does give you the return value directly.
NSString * s = #"NEXT WE HAVE NUMBER FOUR, 'CRUNCHY FROG'.";
NSString * l = [s performSelector:#selector(lowercaseString)];
NSLog(#"%#", l); // prints "next we have number four, 'crunchy frog'."

Write a replaceTokensWithStrings: method with varargs

I want to do the following:
["Hello <firstname> <middlename> <lastname>". replaceTokensWithStrings:
#"firstname", someFirstName,
#"middlename", middleNameMightBeNilObject,
#"lastname", lastNameObject];
It looks like this is not possible because of the "nil as a terminator problem".
However NSLog also takes multiple arguments and can handle nil as parameters too:
NSString *nilValue = nil;
NSLog(#"Value of nilValue=%#", nilValue);
output
Value of nilValue=(null)
So how can I achieve this in my replaceTokensWithStrings:... method?
Update: The signature of my method:
-(NSString *)replaceTokensWithStrings:(NSString *)input, ... NS_SOMETHING_SPECIAL_HERE{
NSLog counts the number of format specifiers (%#, %i, etc.) in its format string (the first argument, the literal string) in order to know how many arguments it should pull off the call stack. This is why it can handle nil arguments -- it is using the count to terminate its processing (and, incidentally, why it will often crash if you give it too few arguments).
Since you have a format-type string, you can do the same thing -- just whip up a helper method that counts the number of <something> elements in the string on which replaceTokensWithStrings: has been called, and use the results to limit your processing of the va_list.
The NS_SOMETHING_SPECIAL in your method declaration would be NS_REQUIRES_NIL_TERMINATION for the case where you're using nil as a sentinel. You don't need anything special if you're getting the count of arguments from somewhere.
Can't you change nil to be #"" so it will replace with a blank string?
Don't work?
["Hello <firstname> <middlename> <lastname>". replaceTokensWithStrings:
#"firstname", #"Peter",
#"middlename", #"", // or myStr
#"lastname", #"Smith"];
or check value:
#"middlename", myStr ? myStr : #"",
EDIT:
If you want variable parameters, you should read http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

CFURLCreateStringByAddingPercentEscapes returning NULL

I am having issues with a category method used to percent-escape illegal symbols.
This is the code that i am using for the task:
#implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
NSString *s = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",CFStringConvertNSStringEncodingToEncoding(encoding));
NSLog(#"S: %#, Self: %#", s, self);
return [s autorelease];
}
#end
When ever i run this method on a string without any of the symbols found in the above matching-string, the method runs fine and the same string is returned back to me.
For instance if i have a string like #"test" it will output:
S: test, Self: test
But if i instead use a string like #"test&symbols" it will output:
S: null, Self: test&symbols
Hence something seems to be wrong with the use of CFURLCreateStringByAddingPercentEscapes.
Now i want to escape symbols such as & because they can occur in strings used as values in a query string, which would cause the query string to be misinterpreted.
Any idea's about what may be the issue here?
Thank you in advance! / Magnus
After finding out my big mistake.
I was told to answer the question to my self.
What i did wrong that i didn't pass NSStringEncoding value to the method, like NSUTF8StringEncoding but instead of that I was passing a CF value such as kCFStringEncodingUTF8.
The value is passed thru a converter to make it CF value which caused an error and it was already had the correct type.
Sorry for any inconvenience.
-Magnus

is NSString value cannot be changed once it is provided a value?

Hi I got an information that NSString value is immutable and cannot be changed once it is provided a value.
But I have created and tested the following code:
NSString *str=[[NSString alloc] initWithString:#"Hello"];
NSLog(#"\n\nstr = %#",str);
str=#"asdasd";
NSLog(#"\n\n new str = %#",str);
and this gives "Hello" as first str value and "asdasd" as second str value. If it is so what is the relevance of calling NSString immutable?Thanks in advance.
What you're doing on the third line is just creating a new string and pointing it with the str variable. You didn't change the original string, but rather made the variable point to a new one.
NSString is immutable. You cannot mutate it. Your confusion arises from the fact that your variable (pointer) is not const.
All you're doing is reassigning the pointer to a different immutable string.
If you were to attempt to append a string to either, then an error would ensue. This, specifically, is "…the relevance of calling NSString immutable". You should interpret this as the string instance may not be mutated, even though the variable you have declared may be assigned another NSString instance because it is not const.
You can make both the pointer const and the string immutable like so:
NSString * const aStr = #"aStr";
You're confusing an immutable object and a constant pointer (plus you're leaking memory). Here you don't really change the NSString instance (that is, the object itself), but just a pointer to it. The point is that you can assign different instances of an NSString to the same variable, it won't change the internal contents of the object, nor would it make it respond to NSMutableString's mutation messages such as appendString etc.
Use this will sol your problem...
NSString *str=[NSString stringWithFormat:#"Hello"];
NSLog(#"\n\nstr = %#",str);
str = nil;
str=#"asdasd";
NSLog(#"\n\n new str = %#",str);
This some basic that you should know..
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string2"];
NSString *s3 = [NSString stringWithFormat:#"string3"];
s1 in this case is a pointer to a constant string. s2 and s3 both point to new strings that you've created, but s2 has been retained for you, and s3 has been autoreleased. If you just need a temporary object, the autoreleased object s3 or the constant object s1 are good choices. If you need to keep the string around, you should use s2 (actually now that I think about it s1 will work in this case too - it's not really idiomatic, though).
You can make s1 or s3 equivalent to s2 by sending them a retain message. You could also turn s2 into an equivalent object by sending it an autorelease message.

Obj-C: Difference between "Fairfield" and #"Fairfield" (with at string)?

I just had a ridonkulous typo in my iPhone app, answered here.
Now I'm wondering about the #"..." notation.
why this works:
NSArray *someArray = [NSArray arrayWithObjects: #"Fairfield", nil];
and this does not (even though it compiles, it will throw an EXC_BAD_ACCESS):
NSArray *someArray = [NSArray arrayWithObjects: "#Fairfield", nil];
Edit:
Ok, so you guys have pointed out that I can't add a C string to an NSArray, because it's obviously not an object.
Now another question: Isn't this somewhat of an oversight? I mean, why does the "...WithObjects:" message specify a list of (id) instead of (NSObject *)?
"#Fairfield" is a normal C string with an '#' character in it. #"Fairfield" is an Objective-C string (NSString on OS X) with no literal '#' in it.
You cannot add C strings to Cocoa collections.
It accepts id rather than NSObject because all initialisers return id. All initialisers return id because subclasses would otherwise override the return type of their ancestors' initialisers.
For example, -[NSMutableString init] can't return NSMutableString * because it subclasses -[NSString init], which can't return NSString * because it overrides -[NSObject init].
Unfortunately, implicit type-casting between const char * and id is perfectly legit, so the compiler won't throw a warning, however a static analyser may be able to pick this sort of mishap up fairly easily.
"Fairfield" is a C string, #"Fairfield" is an Objective-C string.
#"Fairfield" is an object (NSString), so you can send it methods ([#"Fairfield" uppercaseString]) and add it to Objective-C arrays ([NSArray arrayWithObjects:#"Fairfield",nil]). You can only add objects to NSArrays.
On the other hand, "Fairfield" is a C string, and is generally not used in Cocoa. For the most part, you can get by with only using #"Fairfield"
The other reason that a number of things in Cocoa deal with id rather than NSObject* is because, unlike some other languages (say, Java and C#), where all objects in the language must inherit from some global base class, it's entirely possible to have objects that do not descend from NSObject (NSProxy being one example). It's not something you'd do often, but it is possible. The id type means "pointer to any Objective C instance".