Empty method name, what does this actually do? - objective-c

I'm currently learning myself objective-c and iOS programming and found myself stuck with non-working code due to this subtle error for an hour.
Consider the following code:
#property (strong, nonatomic) NSString *name;
- (NSString *):name { return #"Some name"; }
At first glance (and for anyone new) this looks like an overridden getter for the name property. But theres a very subtle : that shouldn't be there. You get no warning/error from the compiler/parser/runtime here, so my question is what does this actually end up as?
I tried to figure a way of calling this method once I saw the error, but didn't succeed in my few attempts.

The method signature - (NSString *):name breaks down to the following:
- It is an instance method (versus a class method with a +).
(NSString *) It returns a string.
: If you were to speak the name of this method, it would simply be called "colon". : tells the compiler that your method accepts one parameter as well.
name There is a parameter called name.
When you don't specify a type, the compiler assumes you meant id, so this method actually fleshes out to be - (NSString *):(id)hello
A valid call to this method would be: [self :#"hello"].
You can do really weird things because : is a valid name for a method, and the compiler assumes id. You could, if you really wanted to, have a method called - :::. The compiler would assume you meant - (id):(id):(id):(id), a method that returns an object of type id and takes three parameters of type id. You'd call it like so: [self :#"hello" :anObject :myObject];

A method declare like the one you posted is rare (and poor style, imo). Objective-C is supposed to be verbose. Methods break down like this:
First character: Either - or +. - means it is an instance method, + means it is a class method.
Value in parentheses: The return type of the method. In your example, the method returns an (NSString *).
The rest (before the curly braces) is the method name along with any parameters they take. You could have a name with no parameters, in which case the method name would not have a : in it. Such as - (void) reload; This would be a method that doesn't return a value and takes no parameters.
If your method takes parameters, they will be mixed into the method name and usually will declare the type (unlike your example). Such as - (NSString *) reverseString:(NSString *) stringToReverse; In this example your method name would be reverseString: it takes one parameter, an NSString* that will be called stringToReverse in the method definition.
Usually, if you see a : with no type it will be a case like - (float) addThreeValues::: This method returns a float and takes 3 parameters. This would be an appropriate definition because the three values don't matter what order they are provided because we are just adding them.

Related

I do not understand Objective-C Initializer for a class.

This code is from the Sams Teach Yourself Swift book, Chapter 21. The Song.h file contains the following code:
//Song.h
#import <Foundation/Foundation.h>
#interface Song : NSObject;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *artist;
#property (nonatomic, strong) NSNumber *rating;
- (instancetype)initWithTitle:(NSString *)title artist:(NSString *)artist rating:(NSNumber *)number;
#end
To my understanding, the - (instancetype) creates an instance method, returning an instancetype. The two (NSString *)s declare that the parameter will be an NSString. I assume that the word title immediately following the first (NSString *) is the parameter name, same with the artist following the (NSString *). What is the initWithTitle: and the artist:?
You pretty much have it correct.
An Obj-C instance method begins with a hyphen, "-" followed by the return type in parentheses. A Class method, begins with a plus "+" but is otherwise the same.
That's followed by the rest of the method signature, which can include multiple parameters. Each parameter is preceded by a colon ":", then the required type for the argument/parameter in parentheses, e.g. NSString *, which is followed finally an internal name for the value that will be passed in. You read the entire method name by stating each parameter...
initWithTitle:artist:rating
Read as a sentence, you're saying:
"Inititialize a Song instance with a title (that's an NSString*), an artist (also an NSString*), and a rating (this requires an NSNumber *)"
-(returnType)firstPartofMethodNameThatTakestheArgument:(NSString *)argument1 andArgumentTwo:(NSString *)argument2
The instanceType is a relatively new alternative for id which meant the return type could effectively be anything. This instead ensures that it can only be an instance of the type containing the method, in this case a Song.
As for the duplicate argument names... The first part "artist: is the external name that appears when you call the method (if you use code completion for example, that's what shows up). The part after the argument's type (NSString *)artist is the internal name that will be used inside the method implementation. Those can be the same, but they don't have to be.
Swift has a similar construction, but with more options where you can choose to write different internal and external parameter names, or just use 1 (or use in-out parameters whose values chance, use variadic parameters that can be an arbitrary number of elements, etc - look into Swift Functions for more details on those topics).
func initWith(externalTitle internalTitle:String, #artist:String, #rating:Int) -> Song
//When calling, you'd see "externalTitle:artist:rating"
//but in the method implementation you'd use "internalTitle" instead.
instancetype is a replacement for the id (and in fact the compiler coverts id to instancetype for init methods at compile time) or specific type class usually returned by init methods and can't be used anywhere else. It allows the compiler to check that assignments from that init method are the appropriate type while still allowing subclasses to inherit initializers. So this init method most likely takes the initial values and assigns them to the properties.
It is the method's signature. In other words ..this is how the method is named.
Btw. "instancetype" is a compiler keyword, that represents the instance's type, so actually the method will return a Song instance.
- initWithTitle:artist:rating: is the method's name, or in Objective-C terms, selector. title, artist and rating are parameter names.
As for - (instancetype), the minus sign - means it's an instance method (class methods begin with a plus sign +), while instancetype is a return type of a method. It's just a keyword that tells the compiler this method will always return an object of type of class on which it was called. If you want to know more about it, I suggest reading the NSHipster post about instancetype.
You said:
To my understanding, the - (instancetype) creates an instance method, returning an instancetype.
The - designates an instance method. The instancetype is a special keyword designating that it returns an instance of the class, a Song instance in this case.
The two (NSString *)s declare that the parameter will be an NSString.
Yes, the two (NSString *) references indicate that the first two parameters are string values. The following (NSNumber *) indicates that the third parameter is a number object.
I assume that the word title immediately following the first (NSString *) is the parameter name, same with the artist following the (NSString *). What is the initWithTitle: and the artist:?
The word immediately following the (NSString *) is the name of the parameter used within the implementation of that method.
Consider the declaration:
- (instancetype)initWithTitle:(NSString *)title artist:(NSString *)artist rating:(NSNumber *)number;
This declares a method called initWithTitle:artist:rating:, that takes three parameters, a title, artist, and rating. So if you wanted to create a song called "Ticket to Ride" by the "Beatles" and a rating of 5, you would call this method with something like:
Song *song = [[Song alloc] initWithTitle:#"Ticket to Ride" artist:#"Beatles" rating:#5];

Declaring and implementing a method that itself executes one line of code

I've many times seen a case where a programmer needs to assign some value (Object or primitive type, does not matter). And let's say this value is an NSString and can be obtained from the following expression
[myObject description]// returns NSString
But for some reason I've seen many people declare another method that itself returns an NSString and executes the above command only. Like:
-(NSString*)getDescription{
return [myObject description];
}
Is this just a matter of preference, or is is there some benefit from it?
Is this just a matter of preference, or is is there some benefit from it?
Those one line wrappers are often used to:
introduce behavior of a method that is meant to be overridden
or (more frequently) to simplify the program. If the method did not exist, you may find the complexity of the program grows. It serves to demonstrate intent, for clarity, documentation, and to minimize redundant implementations (simplifying the program).
There is definitely some "benefit" of creating a method or even better, overriding the "standard" NSObject description method..
If you have a custom NSObject for example and override the +(NSString *)description method you can then return information directly inside that object.
Take for example the following was overwritten in the NSObject we called foo.
+ (NSString *)description {
return #"Hello there";
}
Now, if you ever called [foo description] it would return the string "Hello there".
However, if you just returned description without overwriting the description method, it'd return something like <foo>0x12234 or something.
So yeah, it definitely has a lot of benefit to overriding a custom NSObject description.

What does this syntax mean in Objective-C?

Consider the following:
- (id)initWithTitle:(NSString *)newTitle
boxOfficeGross:(NSNumber *)newBoxOfficeGross
summary:(NSString *)newSummary;
What does this mean? I've guessed that it returns id, and takes three params, but what does each part of the syntax mean? I come from a Ruby/JS background and am finding this syntax a little hard to grasp.
It's an instance method (ie, not a static or "class" method) called initWithTitle:boxOfficeGross:summary: that returns an object of type id (generic object). It takes three parameters: a String object, a Number object, and another String object.
You invoke it like this:
NSNumber * gross = [NSNumber numberWithInteger:1878025999]
Movie * avatar = [[Movie alloc] initWithTitle:#"Avatar"
boxOfficeGross:gross
summary:#"Pocahontas in the 22nd century"];
//or you can do it all on one line, like so:
Movie * avatar = [[Movie alloc] initWithTitle:#"Avatar" boxOfficeGross:gross summary:#"Pocahontas in the 22nd century"];
- means that the method is an instance method, not a class method.
(id) means it returns an id, as you surmised.
initWithTitle:, boxOfficeGross:, and summary: are part of the method name. In Objective-C, each parameter generally has an associated method name part. The entire name of the method is initWithTitle:boxOfficeGross:summary.
(NSString *), etc., denote the type of the parameter.
newTitle, etc., is the name of the parameter.
The - designates an instance method, whereas if it were a + it would be a class method.
The (id) is what the method will return, which is simply a reference to an object.
The rest of the line shows the parameters. When calling the function, you write out the part of each parameter before the :, such as [class initWithTitle:#"my title"];
The reason why there are two names for each parameter is because the method itself will refer to the variable by whatever is after the :, so the title will be newTitle.
This was confusing to me at first, but there are advantages to it.
Also, the parts of each parameter inside parenthesis are the object type of the parameter. (NSString *) is a pointer to a NSString. If you were to pass something that wasn't an NSObject, such as an NSIntger, you would not need the *. You'd simply do:
-(id)initWithInteger:(NSIntger)newInteger;

Elementary Obj-C Question bout Methods

take example:
-(void)setName:(NSString *)name age:(int)age;
How would you call this method (in other words, the method's name is setName but what is the "age" parameter doing in there) and what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
[ myObject setName: #"Adam" age:18 ];
The age parameter is the second parameter in the method signature.
The types in parentheses are the expected types for the argument. e.g. name is expecting only an NSString and age is expecting only an int.
The - means that the method is an instance method, not a class method, which is denoted using a + instead.
The type in parentheses right after the - is the return type.
This is a great site for learning the basics of Objective-C: CocoaDevCentral
To answer, one would need a bit more information, but I'll be guessing this is from some sort of class named aClass, and you have an instance of aClass, named instance.
-(void)setName:(NSString *)name age:(int)age;
means you have a method, named setName:age:, that needs two arguments, one NSString, one int, and it returns a void. As it has a - as it's first character, it is an instance method.
[instance setName:#"James Hargrove" age:21];
Would call setName:age: on the instance.
(The instance should be created using, say,
aClass *instance = [[aClass alloc] init];
which would create an instance of aClass named instance, and initialize it.
This is the standard Objective-C method syntax. This could be read as:
A method with no return value (void) that
sets the name of the object (an NSString * parameter)
and the age (and integer
parameter).
Dissecting the method:
"-" The hyphen states that this is an instance method.
(void) The return type is void - or
no return type expected
setName:(NSString *) The first
parameter to be passed is the "name"
and is an NSString *.
age:(int)age The second parameter
to be passed is the "age" and is
an int.
In reality, the method syntax is actually quite self-documenting once understood (and quite foreign if you're used to more tradition C/C++ or Java syntax).
The actual example of the call of this method would be:
[someObject setName:#"Rich" age:101];
The method name is actually this:
setName:age:
You call it like this:
[someObject setName:#"Alice" age:20];
setName:age: is also the unique signature of that method, and with that signature you can call that method on any object you wish. For example:
NSArray* objects = ...
SEL mySelector = #selector(setName:age:);
for (id object in objects)
{
if ([object respondsToSelector:mySelector])
{
[object setName:#"Alice" age:20];
}
}
what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
Yes, those are "C casts". If everything was an object you wouldn't need those, but because you can pass and return plain old C types to and from your methods, the compiler needs to know the types of your parameters and return values.
You'd call this method like so:
[classInstance setName:#"name" age:123];
The first instance of "age:" indicates that the method receives another parameter, called "age" when used in the implementation of the method.
The types in parentheses indicate the types of data that are expected for each parameter, with the exception of the first one, "void", which means that this method returns nothing.
So, you would call this method as follows.
Say it is a method of an object named foo (of class Foo). Then you would call:
[foo setName:someName age:someAge].
If it were a static method, it would be preceded by a + instead of a minus as follows:
+(void)setName:(NSString *)name age:(int)age;
Then you would call
[Foo setName:someName age:someAge] //use the classname instead of the object name
The types are indeed there for type-checking by the compiler. You'll get warnings if you pass the wrong sort of data, and you will get warnings if your header doesn't match your implementation.
You can actually write Obj-C functions in a couple of different styles though, omitting some of this stuff. You can even write straight up C-style.

How do I pass multiple parameters in Objective-C?

I have read several of the post about Objective-C method syntax but I guess I don't understand multiple names for a method.
I'm trying to create a method called getBusStops with NSString and NSTimeInterval parameters and a return type of NSMutableArray. This is how I have constructed the method but it obviously gets errors at runtime:
- (NSMutableArray *)getBusStops:(NSString *)busStop
(NSTimeInterval *)timeInterval;
I saw another example with a method:
-(NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
I don't understand why this method has a method name for each parameter. Should I do the same with something like:
- (NSMutableArray *)getBusStops:(NSString *)busStop
forTime:(NSTimeInterval *)timeInterval
You need to delimit each parameter name with a ":" at the very least. Technically the name is optional, but it is recommended for readability. So you could write:
- (NSMutableArray*)getBusStops:(NSString*)busStop :(NSTimeInterval*)timeInterval;
or what you suggested:
- (NSMutableArray*)getBusStops:(NSString*)busStop forTime:(NSTimeInterval*)timeInterval;
Objective-C doesn't have named parameters, so everything on the left side of a colon is part of the method name. For example,
getBusStops: forTime:
is the name of the method. The name is broken up so it can be more descriptive. You could simply name your method
getBusStops: :
but that doesn't tell you much about the second parameter.
Yes; the Objective-C method syntax is like this for a couple of reasons; one of these is so that it is clear what the parameters you are specifying are. For example, if you are adding an object to an NSMutableArray at a certain index, you would do it using the method:
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
This method is called insertObject:atIndex: and it is clear that an object is being inserted at a specified index.
In practice, adding a string "Hello, World!" at index 5 of an NSMutableArray called array would be called as follows:
NSString *obj = #"Hello, World!";
int index = 5;
[array insertObject:obj atIndex:index];
This also reduces ambiguity between the order of the method parameters, ensuring that you pass the object parameter first, then the index parameter. This becomes more useful when using functions that take a large number of arguments, and reduces error in passing the arguments.
Furthermore, the method naming convention is such because Objective-C doesn't support overloading; however, if you want to write a method that does the same job, but takes different data-types, this can be accomplished; take, for instance, the NSNumber class; this has several object creation methods, including:
+ (id)numberWithBool:(BOOL)value;
+ (id)numberWithFloat:(float)value;
+ (id)numberWithDouble:(double)value;
In a language such as C++, you would simply overload the number method to allow different data types to be passed as the argument; however, in Objective-C, this syntax allows several different variants of the same function to be implemented, by changing the name of the method for each variant of the function.
The text before each parameter is part of the method name. From your example, the name of the method is actually
-getBusStops:forTime:
Each : represents an argument. In a method call, the method name is split at the :s and arguments appear after the :s. e.g.
[getBusStops: arg1 forTime: arg2]
for create method:
-(void)mymethods:(NSString *)aCont withsecond:(NSString *)a-second {
//method definition...
}
for call the method:
[mymethods:self.contoCorrente withsecond:self.asecond];
(int) add: (int) numberOne plus: (int) numberTwo ;
(returnType) functionPrimaryName : (returnTypeOfArgumentOne) argumentName functionSecondaryNa
me:
(returnTypeOfSecontArgument) secondArgumentName ;
as in other languages we use following syntax
void add(int one, int second)
but way of assigning arguments in OBJ_c is different as described above