2

This is my first time trying to create an object to store my data and am having some trouble. Im not sure im going about this the right way.

song.h:

#import <Foundation/Foundation.h>

@interface Song : NSObject{
    NSString *songID;
    NSString *title;
    NSString *artist;
    NSString *album;
    NSString *length;
    NSString *votes;
}
-(void)setSongID:(NSString*) p_songId;
-(void)settitle:(NSString*) p_title;
-(void)setartist:(NSString*)p_artist;
-(void)setalbum:(NSString*) p_album;
-(void)setlength:(NSString*) p_length;
-(void)setvotes:(NSString*) p_votes;

-(NSString*)getSongID;
-(NSString*)gettitle;
-(NSString*)getartist;
-(NSString*)getalbum;
-(NSString*)getlength;
-(NSString*)getvotes;

@end

song.m

#import "Song.h"

@implementation Song


-(void)setSongID:(NSString*) p_songId;{

}
-(void)settitle:(NSString*) p_title{

}

-(void)setartist:(NSString*)p_artist{

}
-(void)setalbum:(NSString*) p_album{

}
-(void)setlength:(NSString*) p_length{

}
-(void)setvotes:(NSString*) p_votes{

}

-(NSString*)getSongID{

}
-(NSString*)gettitle{

}
-(NSString*)getartist{

}
-(NSString*)getalbum{

}
-(NSString*)getlength{

}
-(NSString*)getvotes{

}

@end

My implementation file cannot see any of the variables, for example I cannot set the songID with self.songID = p_songID

Does objective-c have a built in way of dealing with these setters/getters, am I going about this the wrong way?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
john cs
  • 2,220
  • 5
  • 32
  • 50
  • You didn't declare your symbols as "properties", so you can't use the `self.` notation to address them. Instead, you must use `self ->` as you would in C++ to address instance fields. It's confusing, I know. – Hot Licks Aug 26 '13 at 00:52
  • It's important to understand that "under the covers" the compiler is generating the getters/setters you want, if you use properties. – Hot Licks Aug 26 '13 at 02:40

4 Answers4

7

Objective C has a way of setting up getters and setters for you so that you don't have to worry about writing them yourself. It does this through properties. To set up a property, in your header file write

@property (strong, nonatomic) NSString *songID;

Typically, you will use the strong and nonatomic modifiers unless you have a reason not to. You can research other parameters if you're interested. After writing that line, the getters and setters are generated for you.

To use this property within the class, you simply use dot notation and the self object. For example, to set the value, you write

self.songID = @"66777888";

You access the value of the property in the same way. For example, to assign another string equal to the value, you write

NSString *other = self.songID; 

If you want to access these values outside of the subclass, you still use dot notation, except now using the instance of the class. For example, if you want to set the songID from another class, you can write

Song *song = [[Song alloc] init];
song.songID = @"790";
Erik Godard
  • 5,930
  • 6
  • 30
  • 33
  • 2
    It should be noted that more often than not `NSString` (and sometimes `NSArray` properties) should have the `copy` identifier instead of `strong`. – eric.mitchell Aug 26 '13 at 00:35
  • Thank you Erik and thanks Rickay for the information, reading up on all the different properties now. – john cs Aug 26 '13 at 00:37
  • 1
    I would also note that if you are using ARC and have auto synthesizing properties on, the compiler makes the instance variables behind the properties available directly, prefixed with an underscore. You could access or set the value of songID for example like so: `_songID = value` I prefer this to distinguish between internal properties – atomkirk Aug 26 '13 at 01:03
  • Yeah, while that's an option, you should really only use that if you're overriding a getter or setter. – Erik Godard Aug 26 '13 at 01:04
  • I disagree. When using ARC, there is no advantage to using self.* internally (like there was under MRC). I do it this way almost exclusively now because it's a clearer distinction between accessing my own data and the data of another object. – atomkirk Aug 26 '13 at 01:07
  • While there may not be a performance benefit, it's best to always go through getters and setters and not access instance variables directly. What happens when you have to write a custom getter/setter for that in the future? – Erik Godard Aug 26 '13 at 01:14
  • If you have an atomic property (as opposed to nonatomic) then there is a big difference between 'self.variable = blah' and '_variable = blah'. – dmitri Aug 26 '13 at 02:01
  • You will also need to have a `@synthesize` declaration if 1. you want to use the same variable names, or you are using OS X 32-bit code. – MaddTheSane Aug 26 '13 at 02:20
1

Does objective-c have a built in way of dealing with these setters/getters, am I going about this the wrong way?

Yes, Objective-C has his own way : @property.

You just want to declare a property like that :

@interface Song : NSObject
@property (strong, nonatomic) NSString * songID;
@end;

This will generate, automatically :

- (void)setSongID:(NSString *)songID;
- (NSString *)songID;

So you don't have to write your own one.

By the way, strong means that you want to own the object, it's yours. And nonatomic is about thread safety.

DCMaxxx
  • 2,534
  • 2
  • 25
  • 46
1

You would simply write your class as

@interface Song : NSObject

@property (strong, nonatomic) NSString *songID;
@property (strong, nonatomic) NSString *title;
@property (strong, nonatomic) NSString *artist;
@property (strong, nonatomic) NSString *album;
@property (strong, nonatomic) NSString *length;
@property (strong, nonatomic) NSString *votes;

@end

Member variables and getters/setters are generated by the compiler. If you do not want a setter for a member then you would use readonly specifier:

@property (strong, nonatomic, readonly) songID;

You only need to provide an implementation of a getter or a setter manually if you need a special processing. Just an artificial example:

@implementation Song

void setTitle:(NSString*)title
{
    if (some conditions)
        self.votes = @"winner";

    self.title = title;
}

@end

Letting the compiler to generate getters and setters not only saves you boring typing and creates a more concise code but also takes care of synchronisation and reference counting issues. It doesn't apply in all cases though. These are the things one need to worry about if generating atomic properties and/or not using ARC.

It was noted here that compiler generates member variables for you by prefixing properties with underscores. E.g. _songID or _title, etc. Inside the class implementation you may access and set variables like

self.title = @"title";
_title = @"title";

Which one is appropriate? self.title - in most cases, _title - in some. Remember non ARC code and atomic implementation if applies.

If you want to make your property accessible from you class only (aka private member) then use class extension. In your implementation .m file:

@interface Song()
@property (strong, nonatomic) foo;
@end

@implementation Song
...
@end

And for completeness I'd add that you may make only getter or setter 'private'.

dmitri
  • 3,183
  • 23
  • 28
  • s/are/can be/. You still need to `@synthesize` the properties in your implementation section in order for the compiler to generate getters, setters, and backing variables. – cHao Aug 26 '13 at 00:43
  • 1
    @cHao: no, the compiler will now [automatically synthesize](http://stackoverflow.com/questions/9368676/under-what-conditions-is-synthesize-automatic-in-objective-c) in many cases. – Kurt Revis Aug 26 '13 at 00:46
  • @KurtRevis: OK, now that's plain spiffy. :) It's good that they're removing more and more of the boilerplate crap. – cHao Aug 26 '13 at 00:46
0

The naming convention for accessor methods is that getters have the same name as the property possibly, for boolean properties, prefixed with is. They should not be prefixed with get. And setters are named with the prefix set followed by the capitalized property name.

So, you might have:

- (NSString*) title;
- (void) setTitle:(NSString*)newTitle;

Etc.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154