Can someone explain to me what (NSString *) means with Obj-C? - objective-c

I just started with Objective-C and I would like to understand the meaning of the following lines of code as I see it everywhere in objective-c but I'm not quite getting it 100%:
- (id)initWithName:(NSString *)name;
I understand that the above line is a instance method passing one argument, what I don't understand is (NSString *)name.
another example is:
-(NSString *)name;
or
person.height = (NSObject *)something;
Thanks for your help

In this line:
- (id)initWithName:(NSString *)name;
(NSString *) is simply the type of the argument - a string object, which is the NSString class in Cocoa. In Objective-C you're always dealing with object references (pointers), so the "*" indicates that the argument is a reference to an NSString object.
In this example:
person.height = (NSObject *)something;
something a little different is happening: (NSObject *) is again specifying a type, but this time it's a "type casting" operation -- what this means is to take the "something" object reference (which could be an NSString, NSNumber, or ...) and treat it as a reference to an NSObject.
update -
When talking about Objective-C objects (as opposed to primitive types like int or float), everything's ultimately a pointer, so the cast operation means "take this pointer an X and treat it as if it's pointing to a Y". For example, if you have a container class (like NSArray) that holds generic NSObjects, but you know that the the objects are actually strings, you might say:
NSString *myString = (NSString *)[myArray objectAtIndex:0];
which means "retrieve the first object from the array, treating it as a string".
The cast is not actually converting the value, it's just a way of saying to the compiler "hey, I know that I'm assigning an X to a Y here, so don't give me a warning about it".

- (id)initWithName:(NSString*)name;
Is a signature of a method that takes one parameter called name which is a pointer to NSString.
-(NSString *)name;
Is an accessor method called name that returns pointer to NSString.
person.height = (NSObject *)something;
Typecasts something to a NSObject pointer and then it is assigned to person.height property.
See more explanation in Learning Objective-C: A Primer

- (id)initWithName:(NSString *)name;
-----------------------------------------
'-' means its an instance method (+ is used for static methods)
'(id)' is the return type
'initWithName' is the function name, the name implies its a constructor
':' start of parameter
'(NSString*)' parameter type
'name' parameter name
its the equivalent of
(id)initWithName( NSString* name )

(NSString *)name
is saying that a variable name is a pointer * to a NSString object. Its a pointer because the name variable isn't the string but rather it is just the address in memory for that string.

Related

objective C Warning that I Don't Understand

Can anyone explain to me why I get these warnings:
Conflicting parameter types in implementation of 'setCardsSelected': 'NSMutableArray *' vs 'NSUInteger' (aka 'unsigned long')
Conflicting return type in implementatin of 'setCardsSelected': 'void' vs 'NSMutableArray *'
I'm just trying to pass in an NSUInteger to a function. Why does this not work? Is my method declaration wrong? Thanks!
- (NSMutableArray *) setCardsSelected:(NSUInteger) index
{
if (!_cardsSelected) _cardsSelected = [[NSMutableArray alloc] init];
return _cardsSelected;
}
edit:
the problem is you have defined the property cardsSelected and the associated setter is setCardsSelected: (which is of course -(void)setCardsSelected:(NSMutableArray*)array).
You will have to change your method name (what abut selectCards:?) or declare your property with a different setter, like this:
#property ( nonatomic, strong, setter=setterSelector: ) NSMutableArray * cardsSelected
I think renaming your method is preferable.
Yes, your method declaration is wrong.
I guess you are overriding a method setCardsSelected: in a subclass; in the superclass (or adopted protocol) I guess it's -(void)setCardsSelected:(NSMutableArray*)array

what is the difference between (NSString) *name and (NSString *) name in objective c

i can't understand when to use (NSString *) name and when to use (NSString) *name.
i hope someone can help me/
You should never need to use (NSString)*name. NSString * is a type: a pointer to an instance of NSString. So in a method declaration like this:
- (NSString *)capitalisedString: (NSString *)string
Each time (NSString *) appears it means "the thing that follows has type NSString *". The first one means that the return value of the method is an NSString instance, the second means that the type of the argument string is an NSString instance.
This discussion also applies to casting, which is when you tell a compiler to treat a variable as if it's of a particular type. Because NSString * is a type, you would cast like this:
id object = //...
NSString *myString = (NSString *)object;
The parentheses constitute a cast operator. I.e. (NSString*) name means, that the compiler should interpret name as a pointer to NSString; whereas (NSString) *name means that the compiler should interpret the dereferenced value (i.e., the value name points to) as NSString.

NSString inheritance

I'm doing an useless thing for my first step in Obj-C
#interface String : NSString
{
int m_isnull;
}
- (id) init;
- (int) isNull;
#end
#implementation String
- (id) init
{
self = [super init];
m_isnull=1;
return self;
}
- (int) isNull
{
return m_isnull;
}
#end
test :
String *a;
a=#"ok";
Works fine, but just 2 little questions
1) When I'm compiling I have this warning
warning: incompatible Objective-C types assigning 'struct NSString *', expected 'struct String *'
I don't know how to avoid it !?
2) a=#"ok" is a fastest way to initialize a string, but when I'm debugging, I don't stop by at my init constructor why ?
#"ok" is actually a NSString like 1 is an integer. That's why you get this compiler warning.
There are also #"" NSString literals.
It is essentially shorthand for
NSString's +stringWithUTF8String
method. Mac Player
already stated that it is used to
distinguish this sort of string
literal from a char * string literal
in C.
Source http://guides.macrumors.com/Objective-C_Tutorial#The_.40_symbol
Normally you would create a Category in Objective-C to extend the NSString Class.
Take a look at the NSString class reference:
It is possible to subclass NSString (and NSMutableString), but doing so requires providing storage facilities for the string (which is not inherited by subclasses) and implementing two primitive methods. The abstract NSString and NSMutableString classes are the public interface of a class cluster consisting mostly of private, concrete classes that create and return a string object appropriate for a given situation. Making your own concrete subclass of this cluster imposes certain requirements (discussed in “Methods to Override”).
If you really want to add an -isNull method to NSString you would probably be better off adding it as a category.
I think you might also want to try writing -(BOOL) isNotBlank instead. Consider what happens if you call -isNull on a nil pointer, is that the return value you would expect?
#"ok" is an NSString object. You're creating an instance of the superclass and trying to assign it to a subclass pointer. Think of subclassing as an "is-a" relationship. In your example, String is an NSString. NSString is not a String. Therefore, you can't assign an NSString object to a String pointer.

Objective-C constants in protocol

In my objective-c project, I have a protocol like this:
#protocol MyProtocol
-(id) get:(NSString *) key;
-(void) set:(NSString *) key withValue:(id) value;
-(NSValue *) getSize;
-(void) setSize:(NSValue *) value;
-(NSValue *) getBounds;
-(void) setBounds:(NSValue *) value;
#end
OBJC_EXPORT const NSString *MYPROTOCOL_SIZE;
OBJC_EXPORT const NSString *MYPROTOCOL_BOUNDS;
And basically, those specific methods (getSize, getBounds, setSize, setBounds) are supposed the value that is supposed to be stored in MYPROTOCOL_SIZE and MYPROTOCOL_BOUNDS, respectively.
However, I cannot find an effective way to set those constant strings, by concatenating the results of other methods, because it gives me the error: initializer element is not constant when I try to set them directly. Is there a way I can guarantee that the objects will always be initialized. (e.g. in a classes load method), without having to manually call code when my program runs?
Well first of all, you should learn the naming convention, for accessors you have - (Type); and - (void)set:(Type)value; whereas in your case you did: - (Type)get; and - (void)set:(Type)value;
I advise you to use #property for your size and bounds accessors too.
Now about the "const" in the NSString variable declaration, it doesn't make sense. Const applies to the type on its left and in case it is at the beginning of the line it applies to the token directly on its right. So what you have is a "const NSString" which doesn't make sense because NSString is already immutable, and sending mutating messages to a const object doesn't issue any warning or errors...
What you actually want is "NSString *const" which states that the pointer to your NSString is constant, you can only assign it at initialization and then it doesn't change...
Now about the protocol... Are you sure you want a protocol in your case ? And not an abstract class that would have your 2 NSString as readonly accessors ?

Why use (id) in a method signature when (NSObject *) would be more precise?

Whenever I implement a method in my own code that can accept or return objects of more than one class, I always try to use the most specific superclass available. For example, if I were going to implement a method that might return an NSArray * or an NSDictionary * depending on its input, I would give that method a return type of NSObject *, since that's the most direct common superclass. Here's an example:
#interface MyParser()
- (BOOL)stringExpressesKeyValuePairs:(NSString *)string;
- (BOOL)stringExpressesAListOfEntities:(NSString *)string;
- (NSArray *)parseArrayFromString:(NSString *)string;
- (NSDictionary *)parseDictionaryFromString:(NSString *)string;
#end
#implementation MyParser
- (NSObject *)parseString:(NSString *)string {
if ([self stringExpressesKeyValuePairs:string]) {
return [self parseDictionaryFromString:string];
}
else if ([self stringExpressesAListOfEntities:string]) {
return [self parseArrayFromString:string];
}
}
// etc...
#end
I've noticed many cases in Foundation and other APIs where Apple uses (id) in certain method signatures when (NSObject *) would be more precise. For example, here's a method of NSPropertyListSerialization:
+ (id)propertyListFromData:(NSData *)data
mutabilityOption:(NSPropertyListMutabilityOptions)opt
format:(NSPropertyListFormat *)format
errorDescription:(NSString **)errorString
The possible return types from this method are NSData, NSString, NSArray, NSDictionary, NSDate, and NSNumber. It seems to me that a return type of (NSObject *) would be a better choice than (id), since the caller would then be able to call NSObject methods like retain without a type-cast.
I generally try to emulate the idioms established by the official frameworks, but I also like to understand what motivates them. I'm sure that Apple has some valid reason for using (id) in cases like this, but I'm just not seeing it. What am I missing?
The reason why (id) is used in method declarations is two fold:
(1) The method may take or return any type. NSArray contains any random object and, thus, objectAtIndex: will return an object of any random type. Casting it to NSObject* or id <NSObject> would be incorrect for two reasons; first, an Array can contain non NSObject subclasses as long as they implement a certain small set of methods and, secondly, a specific return type would require casting.
(2) Objective-C doesn't support covariant declarations. Consider:
#interface NSArray:NSObject
+ (id) array;
#end
Now, you can call +array on both NSArray and NSMutableArray. The former returns an immutable array and the latter a mutable array. Because of Objective-C's lack of covariant declaration support, if the above were declared as returning (NSArray*), clients of the subclasses method would have to cast to `(NSMutableArray*). Ugly, fragile, and error prone. Thus, using the generic type is, generally, the most straightforward solution.
So... if you are declaring a method that returns an instance of a specific class, typecast explicitly. If you are declaring a method that will be overridden and that override may return a subclass and the fact that it returns a subclass will be exposed to clients, then use (id).
No need to file a bug -- there are several already.
Note that ObjC now has limited co-variance support through the instancetype keyword.
I.e. NSArray's +array method could now be declared as:
+ (instancetype) array;
And the compiler would treat [NSMutableArray array] as returning an NSMutableArray* while [NSArray array] would be considered as returning NSArray*.
Using id tells the compiler it will be an object of unknown type. Using NSObject the compiler would then expect you to only be using messages available to NSObject. So... If you know an array was returned and it's casted as id, you can call objectAtIndex: without compiler warnings. Whereas returning with a cast of NSObject, you'll get warnings.
You can already call -retain on pointers of type id without casting. If you use a specific superclass type, you'll have to cast the pointer every time you call a subclass's method in order to avoid compiler warnings. Use id so the compiler won't warn you and to better signify your intent.
(id) is also often returned in order to enable objects to be subclassed more easily. For instance, in initializer and convenience methods, returning (id) means that any subclass doesn't have to override the superclass's methods unless there is a specific reason to do so.