0

I had a few questions regarding my objective-C code I wrote and was hoping someone can help clear my doubts. This is my code so far:

This is my Header File:

#import <Foundation/Foundation.h>

@interface Animal : NSObject

@property NSString *name;
@property NSString *favoriteFood;
@property NSString *sound;

@property float weight;

-(instancetype) initWithName:(NSString *) defaultName;

-(void) getInfo;

-(float) getWeightInKg: (float) weightInLbs;

-(NSString *) talkToMe: (NSString *) myName;

-(int) getSum: (int) num1
   nextNumber: (int) num2;

@end

This is my Implementation File:

@implementation Animal

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.name = @"No Name";
    }
    return self;
}

-(instancetype) initWithName:(NSString *) defaultName{
    self = [super init];
    if (self) {
        self.name = defaultName;
    }
    return self;
}

-(void) getInfo{
    NSLog(@"Random Info About Animal");
}


-(float) getWeightInKg:(float)weightInLbs{
    return weightInLbs * 0.4545;
}

-(NSString *) talkToMe:(NSString *)myName{
    NSString *response = [NSString stringWithFormat: @"Hello my name is %@", myName];
    return response;
}

-(int) getSum: (int) num1 nextNumber: (int)num2{
    return num1 + num2;
}
@end

This is my main.m file:

#import <Foundation/Foundation.h>
#import "Animal.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Animal *dog = [[Animal alloc]init];

        [dog setName:@"Bro"];

        NSLog(@"The Dog's name is %@", [dog name]);

        Animal *newDog = [[Animal alloc]initWithName:@"Spot"];

        NSLog(@"The Dog's weight is equal to %.2f", [newDog getWeightInKg:50]);

        NSLog(@"5 + 3 = %d", [newDog getSum:5 nextNumber:3]);

        NSLog(@"%@", [newDog talkToMe:@"Bob"]);

    }
    return 0;
}

I had a few questions regarding this code I wrote:

1) When I define properties such as:

 @property NSString *name;
 @property NSString *favoriteFood;
 @property NSString *sound;

Do I need to synthesize these properties in my implementation file to receive the setter and getter methods? I was a little confused on this since in my main.m file I was able to use the setter method ( [dog setName:@"Bob"] ) for the property: "@property NSString *name;" even though I didn't synthesize that property in my implementation file.

2) Also let's say that I synthesized my name property by doing:

@synthesize name = _name;

What does the _name represent? I read online that it is convention to synthesize a property like this but what is the point of synthesizing and how do I use the "_name" in my implementation or main.m files?

3) In my implementation file in the "-(instancetype)init" method why do we call self = [super init]? What exactly does this "super init" line return in the brackets?

4) Also in my implementation file when I write self.name = @"No Name", what does this self keyword refer to? I read online that "self refers to the actual object that is executing the current method." But my question is what object is this self keyword referring to in my code when I do self.name = @"No Name"?

Shamas S
  • 7,507
  • 10
  • 46
  • 58
  • One question per question, please. – jscs Jun 23 '15 at 18:07
  • Soulchined Thank you so much! That post really cleared up all my doubts! –  Jun 23 '15 at 18:07
  • Yea sorry about including four questions in one post. I will make sure to keep that in mind next time. –  Jun 23 '15 at 18:08
  • As of way back around iOS6 & XCode 4 (?) you no longer need to explicitly use @synthesize. XCode now automatically generates/names the backing instance variable and getter/setter methods for you when you declare the @property. You still *can* do it if you want to override the default names & method implementation. You can also override just the names in the declaration: `@property (nonatomic, strong, setter = setterForSound) NSString *sound` - but this often isn't necessary & could break standard naming convention. It's often done with BOOLs though: e.g. Bool done, setter = isDone – mc01 Jun 23 '15 at 18:08
  • For the rest of the questions: [Why in ObjC do we use self = \[super init\]; instead of just \[super init\]?](http://stackoverflow.com/q/10139765) | [How does an underscore in front of a variable in a Cocoa/ObjC class work?](http://stackoverflow.com/q/822487) | [Difference between self.ivar and ivar?](http://stackoverflow.com/q/4142177/) | [Properties and accessors](http://stackoverflow.com/q/6085080/) – jscs Jun 23 '15 at 18:08
  • Thank you so much for the help John! Cleared up all my questions! –  Jun 23 '15 at 18:12
  • Also if you do not mind can I ask one more question to clarify something? In the self = [super init] line of code, which super class is super init referring to? Like in my main.m file when I do Animal *dog = [[Animal alloc] init]; Does this mean that self = [super init] will return the object dog? –  Jun 23 '15 at 18:16

2 Answers2

3

Do I need to synthesize these properties in my implementation file to receive the setter and getter methods?

No, as long as you don't create your own getter and setter (or only getter for readonly properties), the backing ivars, getters and setters will be automatically created.

What does the _name represent?

This would be the ivar backing your property. If you the @synthesize out, the compiler will create one for you automatically -- unless you try to override both accessor methods.

Why do we call self = [super init]?

Because your class can only function properly if its superclass has been initialized beforehand. init returns the object itself by convention, or nil if something went wrong.

Also in my implementation file when I write self.name = @"No Name", what does this self keyword refer to?

self refers to the object in whose context the method is executed. Since it's an instance method, it is always executed in the context of a single object, and that very object is self. In your method you want to modify the object on which the method was called, hence you access self.name.

Eiko
  • 25,601
  • 15
  • 56
  • 71
Christian Schnorr
  • 10,768
  • 8
  • 48
  • 83
0

You do not need to synthesize unless it's not clear that you'll be using a standard backing ivar. By that I mean this, let's say we have a property as such:

@propert (strong, nonatomic, readonly) id someObject;

If we were to override its getter:

- (id)someObject {
    if (!_someObject) {
        _someObject = ...;
    } 
    return _someObject;
}

This would not work. By overriding the getter of a readonly property, Xcode isn't sure that we actually need a backing ivar. We'd have to synthesize it ourselves.

The same is true for a readwrite property where the setter & the getter are overridden.

JRG-Developer
  • 12,454
  • 8
  • 55
  • 81
Logan
  • 52,262
  • 20
  • 99
  • 128