What does this syntax mean in Objective-C? - 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;

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];

Empty method name, what does this actually do?

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.

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

Selectors in Objective-C?

First, I'm not sure I really understand what a selector is. From my understanding, it's the name of a method, and you can assign it to a class of type 'SEL' and then run methods such as respondToSelector to see if the receiver implements that method. Can someone offer up a better explanation?
Secondly, to this point, I have the following code:
NSString *thing = #"Hello, this is Craig";
SEL sel = #selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? #"YES" : #"NO");
NSLog (#"Responds to lowercaseString: %#", lower);
if ([thing respondsToSelector:sel]) //(lower == #"YES")
NSLog(#"lowercaseString is: %#", [thing lowercaseString]);
However, even though thing is clearly a kind of NSString, and should respond to lowercaseString, I cannot get the 'respondsToSelector' conditional to return "YES"...
You have to be very careful about the method names. In this case, the method name is just "lowercaseString", not "lowercaseString:" (note the absence of the colon). That's why you're getting NO returned, because NSString objects respond to the lowercaseString message but not the lowercaseString: message.
How do you know when to add a colon? You add a colon to the message name if you would add a colon when calling it, which happens if it takes one argument. If it takes zero arguments (as is the case with lowercaseString), then there is no colon. If it takes more than one argument, you have to add the extra argument names along with their colons, as in compare:options:range:locale:.
You can also look at the documentation and note the presence or absence of a trailing colon.
Selectors are an efficient way to reference methods directly in compiled code - the compiler is what actually assigns the value to a SEL.
Other have already covered the second part of your q, the ':' at the end matches a different signature than what you're looking for (in this case that signature doesn't exist).
That's because you want #selector(lowercaseString), not #selector(lowercaseString:). There's a subtle difference: the second one implies a parameter (note the colon at the end), but - [NSString lowercaseString] does not take a parameter.
In this case, the name of the selector is wrong. The colon here is part of the method signature; it means that the method takes one argument. I believe that you want
SEL sel = #selector(lowercaseString);
NSString's method is lowercaseString (0 arguments), not lowercaseString: (1 argument).
Don't think of the colon as part of the function name, think of it as a separator, if you don't have anything to separate (no value to go with the function) then you don't need it.
I'm not sure why but all this OO stuff seems to be foreign to Apple developers. I would strongly suggest grabbing Visual Studio Express and playing around with that too. Not because one is better than the other, just it's a good way to look at the design issues and ways of thinking.
Like
introspection = reflection
+ before functions/properties = static
- = instance level
It's always good to look at a problem in different ways and programming is the ultimate puzzle.
From my understanding of the Apple documentation, a selector represents the name of the method that you want to call. The nice thing about selectors is you can use them in cases where the exact method to be called varies. As a simple example, you can do something like:
SEL selec;
if (a == b) {
selec = #selector(method1)
}
else
{
selec = #selector(method2)
};
[self performSelector:selec];
As per apple docs:
https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html
A selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled. A selector by itself doesn’t do anything. It simply identifies a method. The only thing that makes the selector method name different from a plain string is that the compiler makes sure that selectors are unique. What makes a selector useful is that (in conjunction with the runtime) it acts like a dynamic function pointer that, for a given name, automatically points to the implementation of a method appropriate for whichever class it’s used with. Suppose you had a selector for the method run, and classes Dog, Athlete, and ComputerSimulation (each of which implemented a method run). The selector could be used with an instance of each of the classes to invoke its run method—even though the implementation might be different for each.
Example:
(lldb) breakpoint --set selector viewDidLoad
This will set a breakpoint on all viewDidLoad implementations in your app.
So selector is kind of a global identifier for a method.