Assigning pointer in Objective C or C - ios

NSHost *instance = [NSHost currentHost];
NSString *answer = [instance localizedName];
NSLog(#"%#",answer);
Ok, I know the basics of pointer but I have some doubts on this 3 line of code. After posting a similar question on this website, still the answer i got doesn't really answer my question.
So, first of all,
I know that pointer needs to hold an address.
But why don't we do something like this?
NSHost*instance=&[NSHost currentHost];
adding &. This is because only & shows the address of something.
2nd question what does
[NSHost currentHost]
return
does it return address of its instance?
IF not how can we assign NSHost*instance=[NSHost currentHost]; its wrong.
third question,
I know that NSString *answer = [instance localizedName]; returns an instane of NSString because its written in a book and I'm using it now to complete the challenge in the book.
in this code NSString *answer = [instance localizedName]
are we assigning a pointer to a pointer?? because [instance localizedName] returns a pointer of NSString.

When teaching Objective-C classes, I use this analogy to explain the (somewhat confusing) concept of pointers:
1) When you create an uninitialized variable, like int val;, it creates a "bucket" that can hold an integer value. The bucket itself has a memory address.
2) When you assign a value to the variable with val = 5;, you put that value into the bucket:
3) A pointer variable (one with a leading asterisk *) like int *ptr; is a "bucket", that does not contain a value, but the memory address of another "bucket":
4) To a pointer variable you assign not the value that is contained in another bucket, but the memory address of that other bucket. You get the "bucket address" of a value's bucket by putting the & (ampersand) character in front of the variable name:
That being said, when a method already returns a pointer variable (like NSString *), you already get the memory address and don't have to ask for it again by using &.
To bring the point home, in this example, we have 2 buckets:
NSString *text = #"Test";
The first bucket contains the value (#"Test"), the second bucket contains the memory address of the first bucket. Or, to use the bucket analogy again: #"Test" is in the left bucket, and the right bucket (the variable text) contains the memory address of the left bucket. We can see that by running this:
NSLog(#"value: %#, bucket that contains value: %p, bucket that contains the memory address of the bucket containing the value: %p", text, text, &text);
// output: value: Test, bucket that contains value: 0x1032f5030, bucket that contains the memory address of the bucket containing the value: 0x7fff5c90bb68
Hope this helps!

You don't add a &, because currentHost already returns a pointer. Check out its header:
+ (NSHost *)currentHost
It returns an NSHost* and you assign it to an NSHost*.
[NSHost currentHost] will return a pointer to a specific instance of NSHost.
Same thing here. localizedName returns a pointer to an NSString (NSString*) and you assign it to one.

1) & 2)
NSHost *instance = [NSHost currentHost]; returns a pointer of NSHost object.
So there is no need to put & before [NSHost currentHost].
In C language:
int *ptr = NULL;
int iVar;
You need to assign the address like:
ptr = &iVar;
If both are pointers:
int *ptr = NULL;
int *iVar = NULL;
You can assign the pointer like:
ptr = iVar;
This is what you are doing in the following code also:
NSHost *instance = [NSHost currentHost];
3)
NSString *answer = [instance localizedName]; here also the same thing is happening. The localizedName returns a pointer of NSString

Related

Get the data stored in address using the * operator

int i = 17;
int *addressOfI = &i;
printf("the int stored at addressOfI is %d\n", *addressOfI);
The question is: If I can get the data stored in addressOfI using the * operator, why it doesn't works for type NSString? like following:
NSString *string = #"Hello world!"
printf("the NSString stored at string is %#\n", *string);
why it doesn't works for type NSString?
Because NSString is an Objective-C object and not a primitive type. The NSString * pointer actually points to a struct objc_object which provides the framework for the object system. You can probably "see" some primitive types within this framework (i.e. members of objc_object) however it's supposed to be a black box to normal developers.
The actual reason your second piece of code will crash is that the %# format specifier expects to call the description method on the object you pass in as an argument and you have dereferenced that object pointer so it's no longer a valid object pointer.

Xcode, ios, Set name of variable to value of another variable?

I want to set the name of a variable to the value of another variable are there any other ways to do this because I don't think this is the way.
NSString *myint = #"a";
NSString *([NSString stringWithFormat:#"%#", myint]) = #"something";
NSLog(#"%#", a);
No, you can't do that. Once your code is compiled, your variables don't really have names -- just locations. The names you see in the debugger are provided by a symbol file which the debugger uses to map locations to names.
Key-value coding could help, depending on what you're really trying to accomplish. With KVC, you use key names to refer to values rather than accessing variables, much as you do with a dictionary. For example, if you have an object with properties foo and bar, you can then do something like this:
NSString *key = #"foo";
[myObject setValue:#(5) forKey:key];
You could even override -setValue:forKey: so that it accepts any key and remembers the value (which is exactly what a dictionary does).
You can go in the other direction (set a variable to the name of another variable) using the stringification operator, but it's kinda hacky and not usually all that useful. In a nutshell, macro parameters prefixed with a # are used as literal strings instead of being evaluated. So you'd create a macro like this:
#define string(x) #x
and then you'd use it somewhere in your code like this:
int foo = 5;
NSLog("The name of the variable is %s and its value is %d.", string(foo), foo);
with the following result:
The name of the variable is foo and its value is 5.
I agree with Paulw11. You could define a NSMutableDictionary to hold all your variables by key. I don't think there is any way the compiler can use a handle determined at runtime. But you can achieve the same affect.
So say, for instance, that both the variable handle and value were NSString, then you could do something like this.
NSMutableDictionary *myObjects = [[NSMutableDictionary dictionary] init];
NSString variableName = #"myString";
[myObjects setObject #"Variable value" forKey: variableName];
NSLog("Variable %# has value %#.", variableName, [myObjects objectForKey: variableName]);

basic programming concept: when to initialize new string versus just creating new variable

So I've been programming for a year but this concept still trips me up sometimes. My understanding is that if you don't initialize and allocate a new object when you create a new variable name using the pointer operator '*' that the danger is that the value of that new variable will always just be tied to whatever memory address it is you've pointed the name. For example, in #2 if string is set to '6' because array[1] is set to '6' but later the value of element #1 in array changes to '7' then string will return 7. But if I used method 1 where I use a string class method to allocate and initialize a memory address of its own for string then string would stay '6' even if later element #1 is changed to hold a value of '7'. Is this right?
What’s the difference between:
NSString *string = [NSString stringwithstring: array[1]];
AND
NSString *string = array[1];
As a sidenote: I have a tough time understanding how this will matter much because if array is immutable then the only way it could be changed is if a new array is initialized and reallocated with a different value for element #1. Also, once my view controller gets popped off of the stack when the user continues to navigate through my app, if it gets called again all of these objects will get recreated from scratch- so it usually won't matter. But I just want to make sure I am getting the concept anyways.
Actually, whether you use the 1st or 2nd option has nothing to do with the array itself.
The 2nd option would not result in any change even if the array was mutable and you replaced the object at index 1. string would still point to the original object.
In the example you've given, the choice of the two options only matters if in reality, the string you get from the array is an NSMutableString. If the string is an immutable NSString then either option gives the same result. But if you actually have a mutable NSMutableString, then option 2 means that your string value can change over time of another reference to the mutable string makes changes to the string.
Example:
NSMutableString *mutable = [NSMutableString stringWithString:#"hello"];
NSArray *array = #[ #"stuff", mutable ];
NSString *string1 = [NSString stringWithString:array[1]];
NSString *string2 = array[1];
NSLog(#"string1 = %#, string2 = %#", string1, string2);
[mutable appendString:#" there"];
NSLog(#"string1 = %#, string2 = %#", string1, string2);
The log output will be:
string1 = hello, string2 = hello
string1 = hello, string2 = hello there
See how string2 was changed as a result of modifying mutable.
(edit: per martin R's comment--suppose the strings in the example are mutable strings)
I made a diagram to help explain what's going on.
The first diagram is your initial setup. string = nil and you have a string reference in array[1].
1) do string = array[1]. Now string and array[1] point to the same string object.
2a) alternately, as in 2a, you can do string = [ NSString stringWithString:array[1]]... This will point string to a copy of the string in array[1]
Notice in all cases if you mutate the array, string still contains a reference to either a) the original string from array[1] or the copy you created.
2b) For example, let's do array[1] = #"test". [string description] will still return ABC
HTH
Your string pointer does not remember where the string was at the time you assigned it, so array-level changes don't matter.
The practical difference is about what happens if your array actually contains mutable strings instead of plain ones. Your first example creates a new string that has the content that's at array[1] when the assignment takes place. In your second example, the thing pointed to by string could be different moment-to-moment if some other code changed the underlying mutable string that's in array[1] at assignment time.

How to Convert NSValue to NSString

Some background... I am writing code that interacts with javascript via a ObjC-JS bridge utilizing UIWebView's stringByEvaluatingJavaScriptFromString:. The idea is that the "brains" of the app be in JS which tells Objective-C how to behave. There are multiple benefits to this like reduced binary size, flexible updates, etc. However, there is a case where there is some Objective-C only object that the JS needs to have a reference to (JS instructs ObjC when to use/remove the object). This is being done by placing the native object in a dictionary with a unique identifier which can be passed as a string to JS (over the bridge). My problem stems with coming up with a nice identifier for said native Objective-C object.
Thus, I am trying to convert a reference to an object to a string with no luck. This is what I have:
// anObject is a custom class
NSValue *handle = [NSValue valueWithPointer:(__bridge const void *)anObject];
NSData *data = [NSData dataWithValue:handle];
NSString *stringHandle = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
The dataWithValue: function (taken from this SO post):
+ (NSData *)dataWithValue:(NSValue *)value {
NSUInteger size;
const char* encoding = [value objCType];
NSGetSizeAndAlignment(encoding, &size, NULL);
void* ptr = malloc(size);
[value getValue:ptr];
NSData* data = [NSData dataWithBytes:ptr length:size];
free(ptr);
return data;
}
Walking through it in the debugger shows me a nil value for stringHandle:
What am I doing wrong?
What you're doing wrong is trying to treat an address as if it's a UTF-8 encoded string. An address -- or any other chunk of arbitrary data -- isn't very likely to be valid UTF-8 data. (If by chance it were, it still wouldn't be the string you expect.)
If you're trying to get a string containing the pointer value, i.e., the address of the original object, that's just [NSString stringWithFormat:#"%p", anObject];
If you really need to do it from the NSValue, then replace anObject with [theValue pointerValue].
If you want to pretty-print arbitrary data, see How to convert an NSData into an NSString Hex string?
You can get a string representation by calling the NSObject method "description". You can override the "description" method in a subclass if you need.
An NSValue of a pointer will be an object holding the 4 bytes of the 32-bit pointer. It will not hold any of the data pointed to in RAM.

stringWithUTF8string returns null

I tried to solve my issue for a week and the only hope is for You!
I receive from a user a string via uitextview and cast it using next code:
unsigned char* pAr = [myuitextview.text UTF8string];
Then after some work i want to show resulting pAr in the myuitextview using this code:
Myuitextview.text = [NSString stringWithUTF8string:pAr];
As result i see blank myuitextview.
After investigation i discovered,that stringWithUtf8string returns nil, but i received it in utf8 and create back with utf8.
Then i discovered that UTF8string
returns nil also.
Also i discovered that it happens when i use unsigned char* instead of const char* returned by utf8string method. When i receive to const char* it returns a c string but if i try unsigned char* it returns nil.
What can be the reason of null after stringwithutf8string? As i understand Unsigned char * and const char* are safe casts?
You can't so easily transfer unsigned char to NSString
Try this one
NSString* s = [[NSString alloc] initWithBytes:pAr length:sizeof(pAr) encoding:NSASCIIStringEncoding];
NSString has a method "UTF8String" (note the use of caps")
I don't see a method "utf8string" (all lower case). Where does that method come from? (Objective-C method names are case sensitive, so those are differennt method names.)
Also, note that in the docs for UTF8String say:
The returned C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you called this method.
If you use that method you meed to make sure that your text field sticks around and that you don't change it's string contents or the pointer you get back from the UTF8String method will become invalid.

Resources