-1

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:?

5 Answers5

1

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.

Jon Shier
  • 12,200
  • 3
  • 35
  • 37
1

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.

Earl Grey
  • 7,426
  • 6
  • 39
  • 59
1

- 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.

Filip Radelic
  • 26,607
  • 8
  • 71
  • 97
1

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];
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    Fix the method name explanation please. It has a non-contiguous name explicitly including the parameter's names in it. Looks like swift naming conventions creeped in :) – Earl Grey Feb 23 '15 at 23:08
1

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.
mc01
  • 3,750
  • 19
  • 24