Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
J V
1,774 Pointsios- Designated Initializers and Convenience Constructors
Please provide me with tips to get this correct.
Fill in the convenience constructor below for the class Song, which calls a designated initializer named: initWithSinger: (NSString*) singer
-
( id ) ????? : (NSString*) singer {
return [[ ????? alloc]
initWithSinger: ??????? ];
}
4 Answers
Thomas Anthony
iOS Development Techdegree Student 22,352 PointsAs you know, a convenience constructor performs the allocation and initialization of a receiver with a single message.
+ (id)songWithSinger:(NSString *)singer
{
return [[self alloc] initWithSinger:singer];
}
The name of the method itself is yours to define, however, as you may have noticed with some of the many class methods within the Foundation and UIKit frameworks; there is a particular convention that Apple uses. The first word portion of the method name is the name of the receiver (the class in this case), followed by the word portion 'With', followed by whatever operations the method performs or whatever the method receives as a parameter. A good example of this is the NSData convenience constructor [NSData dataWithContentsOfURL]. You then pass whatever parameters you may have in the convenience constructor's call stack to the designated initializer's call stack. You must remember to define this method as a class method (indicated by the '+' sign at the beginning of it's definition) and not an instance method as it would defeat it's purpose.
UPDATE: I rectified the code sample above to display the correct method for defining a convenience constructor. It is important to remember that unlike the initializer, the receiver of the alloc message cannot be super, it must instead be self as the designated initializer is not defined on the super class.
bidorbuy IT
Courses Plus Student 9,474 PointsWhat have you tried so far?
J V
1,774 Points( id ) self: (NSString*) singer { return [[ super alloc] initWithSinger: @"singer" ];
Joseph Finkenbinder
5,340 PointsWhat is the correct answer? After 6 tries I've given up.
`+ (id) initWithSinger : (NSString *) singer {
return [[self alloc] initWithSinger: singer]
}
`
I've already seen your other answer on this post: https://teamtreehouse.com/forum/help-with-question-4-on-ios-designated-initializers-and-convenience-constructors
which I don't understand and still don't know the answer.
Thomas Anthony
iOS Development Techdegree Student 22,352 Points- (id)songWithSinger:(NSString *)singer { return [[self alloc] initWithSinger:singer]; }
Remember that the naming convention for convenience constructors are somewhat parallel to naming scheme of the designated initializer with the exception of the first "word phrase" being the name of the class (without the class prefix). For example, stringWithFormat: and stringWithContentsOfURL:encoding:error: are just two of many convenience constructors for the NSString class. Note that this is simply a convention and not required for convenience constructor to be valid; however, it helps you and other developers understand your code much easier as the syntax is clear and the convention is heavily used within the foundation framework.
Essentially, all of the heavy-lifting –so to speak– is done within the designated initializer. All that is being done inside of the convenience constructor is the forwarding of the arguments (singer, in this case) to the designated initializer. The only real benefit of the convenience constructor is –of course– convenience; you do not have to send the alloc message because that is done within the constructor. So instead of performing the usual [[Song alloc] initWithSinger: @"James Brown"] routine that some developers find to be verbose, you can have the convenience of simply stating [Song songWithSinger:@"James Brown"].
Stu Cowley
26,287 PointsStu Cowley
26,287 PointsThis one worked for me! Thanks Thomas :)