Please explain Objective-C instance definitions - objective-c

NSString * aString;
What I don't understand is the *, what exactly does that operator do and what else can go there if anything?
Sorry I know this is a rather novice question but I am self taught; whenever I see "*" I think wildcard and I don't see why you would cast an object NSString ;

This means that aString points to where the NSString object is in memory. You might want to check out Binky Pointer Fun ( youtube version ) to get a hang of what Pointers are!
You can also read a bit more about pointers ( and even Double pointers! ) here.
A pointer is exactly what it sounds like, it's something that Points out where to go. Your memory is divided into "boxes" and each box is labeld with what we call a Memory Address. You you write:
NSString myString;
it means that you allocate an NSString object in memory. But when you decide to write:
NSString *myString;
it means that you create a Pointer to an NSString somewhere in your memory. In short it means that myString in the latter example will contain the Memory Address to the "real"
NSString object.

The * means that you are creating a pointer to an object. Note that this is part of the C language, not Objective-C (Objective-C is a strict superset of C).
http://cocoadevcentral.com/d/learn_objectivec/

Related

Lifespan of NSString cStringUsingEncoding return value

I have an NSTextField and get its contents like so
NSString *s = [textField stringValue]
Now I want to convert this NSString to a string that my platform-independent C code can handle. Thus I'm doing:
const char *cstr = [s cStringUsingEncoding:NSISOLatin1StringEncoding];
What I don't understand now is how long this "cstr" pointer stays valid. Apple docs for cStringUsingEncoding say:
The returned C string is guaranteed to be valid only until either the
receiver is freed, or until the current memory is emptied, whichever
occurs first. You should copy the C string or use
getCString:maxLength:encoding: if it needs to store the C string
beyond this time.
Two questions about this:
I suppose the aforementioned "receiver" is the NSString returned by the [textField stringValue]. Since I don't own this NSString how can I tell when this will be freed? Is it safe to assume that this NSString won't be freed before the NSTextField widget will be freed?
What does "until the current memory is emptied" mean precisely? I don't understand this at all.
Of course, I could just go ahead and make a copy but I'd like to understand how long the string pointer returned by cStringUsingEncoding is valid.
I know there are several similar questions here but none could really answer my question since in my case, the owner of the NSString is the NSTextField widget and I don't know when this widget will release the NSString or if it stays valid for the complete lifespan of the widget itself.
I suppose the aforementioned "receiver" is the NSString returned by the [textField stringValue]
yes, in this case the receiver is s
Since I don't own this NSString how can I tell when this will be freed?
you don't. you should retain s by storing it in an instance variable for as long as you need it
Is it safe to assume that this NSString won't be freed before the NSTextField widget will be freed?
no, because you don't know what or how the text field returned s to you
What does "until the current memory is emptied" mean precisely? I don't understand this at all.
good question. also, hard to tell, because you don't own the string or know about its underlying implementation. say it was a mutable string that was mutated and had to reallocate memory...
you can be pretty sure of your safety if you copy s, store the copy in an instance variable and then use the copy to get the C string (or just copy the C string).
Receiver for sure means the string s, and the danger to cstr is clear when s is freed. I think the phrase "or until current memory is emptied" is a documentation bug introduced by ARC. It can be read as "or until an ARC-implied release is executed".
See the doc quoted here in 2010 as evidence. I think the author, probably searching for 'autorelease pool' for places to update the docs, was grasping for a harmless, ARC-compatible synonym for "or until the current autorelease pool is emptied". I think it would have been better to just drop the disjunction.
Anyway, either take control of the NSString, or copy the cstring.

Objective-C Casting with Pointer [duplicate]

This question already has answers here:
Objective-C and Pointers
(3 answers)
why most of the objects we create in iphone are pointers
(1 answer)
Closed 9 years ago.
I am new to Objective-C and come from a Java background. I have just gone over casting in Objective-C but the book I am using failed to explain the use of the '*'/pointer when casting. Here is the example they gave me:
myFraction = (Fraction *) fraction;
Aren't pointers for specific objects so they have their own unique memory location? So then why must I use a pointer when simply referencing a class? In this case, Fraction.
Thanks I hope this makes sense and I know this is a simple question that I should know and understand but I could find nothing explaining this.
The * symbol has multiple meanings (beside multiplication :):
Dereference (follow) pointers. This code follows pointer stored in pointerToInt and then assigns a value to it.
(*pointerToInt) = 5;
Declares a pointer type. When you write int * it means “reference to an integer”.
int x = 5;
int * xPtr = &x
Now, objects are a kind of structures, but we only manipulate with them via pointers. Never directly. This basically means, that 99% of time when you see * (and it's not multiplication :) it is the second case: a part of type declaration:
NSString * = pointer to NSString structure (you can't use NSString alone)
Fraction * = pointer to Fraction structure and Fraction structure is described in Fraction class
So it's not “pointer to the Fraction class”, but rather “pointer to structure of Fraction class”.
I will go a little further and answer your future question about two **. You may see this usually with NSError arguments that are defined like methodWithError:(NSError **)errorPtr.
Short story: int is to int * as NSError * is to NSError **.
Long story: If we cannot manipulate with objects directly (without pointers to them), the single pointer becomes standard part of declaration. Now what if we want to make indirect access to the object? We use double pointer! First * is required for object, second is for indirection.
NSError *error = nil; // Empty.
NSError **errorPtr = &error; // Reference to our local `error` variable.
[data writeToURL:URL options:kNilOptions error:errorPtr];
// That method uses: (*errorPtr) = [NSError errorWith...];
NSLog(#"Error: %#", error); // Our local error is no longer empty.
I believe pointers are weird when you come from Java. They are a bit of legacy from C, but they are not used in any crazy way.
The * symbol is simply syntax that's used when referring to pointers.
Here, myFraction, and fraction are both variables that hold pointers (they aren't objects themselves – in fact you never have variables that hold Objective-C objects, objects must always be referred to with pointers).
The (Fraction*) syntax describes a cast to a pointer-to-a-Fraction of the expression on its right (in this case the fraction variable).
Remember that a pointer is just a variable that holds a memory location.
In Objective-C, when you have an object, what you really have is a pointer to an object, that is, a variable whose value is the memory address where the object really is.
Casting a pointer to a pointer of another type has no effect at runtime (at least for objects). In fact all your objects could be of type (void *). The casting helps the compiler to know what kind of object the pointer is pointing to, and generate errors or warnings.
If these two little paragraphs don't make much sense to you right now, consider reading some basic information or tutorials on pointers. Understanding pointers can be challenging for a beginner or from someone transitioning form the Java world.
...failed to explain the use of the '*'/pointer when casting...
Pointers have little to do with casting, other than being part of a type specifier. Consider:
Fraction is a type -- for the sake of argument, let's imagine that it's the name of a class, and that Fraction is a subclass of another class called Number.
Fraction * is a pointer to an instance of the Fraction class. In Objective-C, you always use pointers to refer to objects, so you'll see a lot of variables with types of the form ClassName *.
Casting is simply a matter of telling the compiler that it should treat a variable as a certain type. So, let's say you've got a variable number of type Number * and you know that the object it points to is actually a Fraction. However, you can't use any of the methods that are specific to Fraction because, as far as the compiler is concerned, number is just a Number *. You can use a type cast to tell the compiler: "I know what I'm doing, and number is definitely pointing to an instance of Fraction, so please treat number as a Fraction *." You do it like this:
Fraction *f = (Fraction *)number;
But again, the * doesn't have any special significance in the casting operation beyond the fact that Fraction * is the type to which you're casting number.

What does the Apple documentation mean when it refers to the correct place to include ARC attributes?

When casting around (no pun intended) to clarify when to use __strong in a variable declaration I came across these lines in the Transitioning to ARC Release Notes:
You should decorate variables correctly. When using qualifiers in an object variable declaration, the correct format is:
ClassName * qualifier variableName;
for example:
MyClass * __weak myWeakReference;
MyClass * __unsafe_unretained myUnsafeReference;
Other variants are technically incorrect but are “forgiven” by the compiler. To understand the issue, see http://cdecl.org/.
I suspect this is some sort of in-joke on Apple’s part, but I don’t suppose I get it. It clearly doesn’t matter but I would like to do it right. What is the importance of correctly “decorating” a variable declaration, and what point is cdecl.org trying to make?
Edit: to clarify, I want to understand precisely why writing
qualifier ClassName * variableName;
is "technically incorrect."
So I think I have an answer, but I can’t be sure if I’m correct. Feel free to provide a better one, or comment/upvote if you think I’ve nailed it.
CDecl is a C program which you can download from that same website. It exists to solve problems such as in this question.
Variable declarations in C can be pretty notorious, especially when typedefs are taken into account. There is a good introduction to this over at Unixwiz.net. You’ll find there a helpful introduction that will allow you to read even such monsters as char *(*(**foo [][8])())[]; (foo is array of array of 8 pointer to pointer to function returning pointer to array of pointer to char).
The rule with these is effectively proximity. Consider the simple example
const int * foo
This declares foo as a pointer to a constant int. However,
int * const foo
will declare foo as a constant pointer to an int. The subtle difference is discussed thoroughly in this question. (essentially, in the first example you can make foo point to another constant int, but cannot modify the constant int through foo; in the second, you can modify the int which foo points to, but you can’t make foo point to any other location in memory).
With these ARC attributes, the syntax of using
__strong NSString * myString
would declare myView as a pointer to a “strong” UIView. This is nonsensical. Only pointers to objects can have the attribute of being strong (or weak or whatever) under ARC. Therefore it is good practice to write
NSString * __strong myString
since this is in line with other C keywords.
I did ask myself: what happens under ARC if you declare a strong object pointer to a weak object pointer to, say, an NSString, like so
NSString * __weak * __strong myContrivedPointer;
but the same applies. Nothing but an object pointer can have these keywords. Consequently, it is nonsensical to declare a pointer to a pointer “strong”.

Using malloc to allocate an array of NSStrings?

Since NSSstring is not defined in length like integer or double, do I run the risk of problems allocating an array of NSStrings for it using malloc?
thanks
ie:
NSString ***nssName;
nssName = (NSString***) malloc(iN * sizeof(NSString*));
the end result with for_loops for the rows is a 2D array, so it is a little easier to work then NSArray(less code).
No problems should arise, allocating an array of NSStrings is like making an array of the pointers to string objects. Pointers are a constant length. I would recommend just using NSArray but it is still fine to use a C array of NSStrings. Note that this may have changed with ARC.
Here is completely acceptable code demonstarting this:
NSString** array = malloc(sizeof(NSString*) * 10); // Array of 10 strings
array[0] = #"Hello World"; // Put on at index 0
NSLog(#"%#", array[0]); // Log string at index 0
Since NSString is an object (and to be more precise: an object cluster) you cannot know its final size in memory, only Objective-C does. So you need to use the Objective-C allocation methods (like [[NSString alloc] init]), you cannot use malloc.
The problem is further that NSString is an object cluster which means you do not get an instance of NSString but a subclass (that you might not even know and should not care about). For example, very often the real class is NSCFString but once you call some of the methods that treat the string like a path you get an instance of NSPathStore2 or whatever). Think of the NSString init methods as being factories (as in Factory Pattern).
After question edit:
What you really want is:
NSString **nssName;
nssName = (NSString**) malloc(iN * sizeof(NSString*));
And then something like:
nssName[0] = #"My string";
nssName[1] = [[NSString alloc] init];
...
This is perfectly fine since you have an array of pointers and the size of pointer is of course known.
But beware of memory management: first, you should make sure the array is filled with NULLs, e.g. with bzero or using calloc:
bzero(nssName, iN * sizeof(NSString*));
Then, before you free the array you need to release each string in the array (and make sure you do not store autoreleased strings; you will need to retain them first).
All in all, you have a lot more pitfalls here. You can go this route but using an NSArray will be easier to handle.
NSStrings can only be dealt with through pointers, so you'd just be making an array of pointers to NSString. Pointers have a defined length, so it's quite possible. However, an NSArray is usually the better option.
You should alloc/init... the NSString*s or use the class's factory methods. If you need an array of them, try NSArray*.
You should not use malloc to allocate data for Objective-C types. Doing this will allocate memory space but not much else. Most importantly the object will not be initialized, and almost as importantly the retain count for the object will not be set. This is just asking for problems. Is there any reason you do not want to use alloc and init?

Char * vs NSString *

I am trying to get rid of some confusion when working with C.
Is using char *name in some sense the same as working with NSString *name in the sense that the pointer still points to the first memory allocation for it?
Ofcourse NSString has a bunch of extras but that isnt what I mean, will working with char *name allow me to work as if it was a NSString *name, so that I could in the future just work with the pointer "name" ?
The answer is no.
char* is meant to point to a simple array of (or single) char data values.
char* myCharPtr = "This is a string.";
//In memory: myCharPtr contains an address, e.g. |0x27648164|
//at address 0x27648164: |T|h|i|s| |i|s| |a| |s|t|r|i|n|g|.|\0|
On the other hand, NSString *name will be a pointer to an object which could have lots of extras, and you can't rely on where the actual character data is stored, or how. It is not encoded as ASCII (Sherm Pendley down below said it's UTF-16), and it could have extra data like the string's length, etc.
NSString* myStringPtr = #"This is an NSString.";
//In memory: myStringPtr contains e.g. |0x27648164|
//at address 0x27648164: |Object data|length|You don't know what else|UTF-16 data|etc.|
You alter and access unknown objects through their exposed methods because you don't know how they are formatted in memory, and thus can't access their data directly. (Or because they encapsulate themselves to hide it from you.)
You can still use the NSString pointer in future if you declare it as NSString *name though. This is what I mean:
NSString *name = #"This is a string.";
NSString *sameName = name; //This is pointing to the same object as name
NSLog(#"%#", sameName); //This prints "This is a string.", and if NSStrings were mutable, changing it would change name as well.
//They point to the same object.
char* and NSString* are two completely different implementations of strings.
NSString can only be used in Objective C (not in plain C), represents immutable strings, is based on Unicode characters and - being an object-oriented class - provides many methods. Furthermore, they are reference counted and always allocated on the heap.
char* is just any array of bytes, whose encoding is not well defined, it's mutable and it isn't object-oriented. char arrays can be allocated on the heap (with malloc) or on the stack. The former requires a call to free, while the latter must never be freed.
Is using char *name in some sense the
same as working with NSString *name in
the sense that the pointer still
points to the first memory allocation
for it?
I think you should regard the NSString* name as a handle to the object rather than a pointer to the object and as such not assume it points to the first memory allocation. I think that would be a better metaphor.
No,
char * is a pointer to an array of characters. NSString is a pointer to an NSString object. I cannot find any documentation of it, but I believe that NSString boxes a char *. Doing name[1] against NSString *name would refer to the 2nd element of an array of NSString objects.
In a sense - a somewhat non-useful sense, to be sure - they are the same, in that both are pointer types that refer to a memory address. That similarity turns out to be not very useful in practice though. To make use of either one, you have to take into account the type of "thing" they point to, and how one uses an array of char and an NSString instance is entirely different. Even for something as simple as assignment, one needs to handle the NSString instance in accordance to Cocoa's memory-management rules, using either -copy or -retain instead of a simple "foo = bar" assignment.