Reputation: 525
I have an xcode project which has 2 classes - Stem & Player, I'm trying to ensure my code is solid from an object-orientated perspective, I believe it's acceptable programming practice for my Player Class to access information in my Stem Class.
I want to access indices from an array in stem - I can do this from my view controller using
stem.index[i]
when I try to do this from player I'm not allowed as stem is undeclared. I've tried importing Stem.h into my Player.m file & declaring stem in player (similar to how one does this in the view controller), only to get errors (expected specifier-qualifier-list before 'Stem').
What's the correct way to do this? Please excuse any loose use of terminology as I'm relatively new to this. Thanks in advance :)
Edit
Here is some code that might shed some light on things, In the viewController I declare stem & player
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#import "Stem.h"
#import "Player.h"
@interface TestApp_v1ViewController : UIViewController {
Stem *stem;
Player *player;
I alloc & init my two objects stem & player in viewController.m
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Init Successful");
[self loadMOV];
[self setupInterface];
stem = [[Stem alloc] init];
player = [[Player alloc] init];
}
I then move to Stem.h where I declare stem again (so that stem is accessible to player when stem.h is imported to player.h - as per glogic's comment)
#import <Foundation/Foundation.h>
@interface Stem : NSObject {
int *index;
int numberOfStems;
Stem *stem;
}
@property(nonatomic,readwrite) int *index;
@property(nonatomic, retain) Stem *stem;
Player.h looks like this:
// Player.h
#import <Foundation/Foundation.h>
#import "Stem.h"
@interface Player : NSObject {
NSMutableArray *player1;
}
@property(nonatomic,retain) NSMutableArray *player1;
-(void) playAudio;
@end
Finally in Player.m I try to access the index array
#import "Player.h"
@implementation Player
@synthesize player1;
-(void)playAudio {
NSLog(@"play audio called");
NSLog(@"index[0] is: %i", stem.index[0]);
}
@end
I'm still being told that stem is undeclared, any ideas?
Edit #2 - adding bare-bones program
I hope this is considered ok but I've decided to post my program (pared down to the bare essentials). I think it may be the only way that the issue might be figured out - since a lot is going on across classes. I've been trying to get this to work for hours now arrrgh...
I alloc'd & initialised my stem & player objects in the viewController - i thought this was the best way to go about this, but maybe there is a better method.
//Part (i)
// TestApp_v1ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#import "Stem.h"
#import "Player.h"
@interface TestApp_v1ViewController : UIViewController {
Stem *stem;
Player *player;
}
@property(nonatomic, retain) Stem *stem;
@property(nonatomic, retain) Player *player;
@end
//Part (ii)
// TestApp_v1ViewController.m
#import "TestApp_v1ViewController.h"
#import <MediaPlayer/MediaPlayer.h>
@implementation TestApp_v1ViewController
@synthesize stem;
@synthesize player;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Init Successful");
stem = [[Stem alloc] init];
[stem loadURLs];
player = [[Player alloc] init];
[player playAudio];
int index = stem.value;
NSLog(@"r is: %i", index); //checking to see if I can get a value from the index array - this works fine, so 'value' can be accessed from the viewController
}
Here I declare an int array & the int "value" which I want to access later from my player (this is what turns out to be the problem)
//Part (iii)
// Stem.h
#import <Foundation/Foundation.h>
@interface Stem : NSObject {
NSMutableArray *urlArray;
int *index;
int value;
int numberOfStems;
Stem *stem;
}
- (void)loadURLs;
- (void)randomiseAudioForInitialPlay;
@property(nonatomic,retain) NSMutableArray *urlArray;
@property(nonatomic,readwrite) int *index;
@property(nonatomic,readwrite) int numberOfStems;
@property(nonatomic,readwrite) int value;
@property(nonatomic, retain) Stem *stem;
@end
//Part (iv)
// Stem.m
#include <stdio.h>
#import "Stem.h"
@implementation Stem
@synthesize numberOfStems;
@synthesize urlArray;
@synthesize index;
@synthesize stem;
@synthesize value;
- (void)loadURLs
{
NSLog(@"Loading URLs");
numberOfStems = 20;
urlArray = [[NSMutableArray alloc] init];
for ( int i = 1; i <= numberOfStems; i++ ) {
NSString *soundName = [NSString stringWithFormat:@"stem-%i", i];
NSString *soundPath = [[NSBundle mainBundle] pathForResource:soundName ofType:@"mp3"];
NSURL *soundFile = [[NSURL alloc] initFileURLWithPath:soundPath];
[urlArray addObject:soundFile];
[soundFile release];
}
[self randomiseAudioForInitialPlay];
}
- (void)randomiseAudioForInitialPlay
{
index = malloc(numberOfStems*sizeof(int));
for (int i = 0; i < numberOfStems; i++)
{
index[i] = i;
}
for (int i = (numberOfStems - 1); i > 0; i--)
{
int randomIndex = arc4random() % i;
int tmp = index[i];
index[i] = index[randomIndex];
index[randomIndex] = tmp;
}
value = self.index[10]; //this is what needs to be accessed later, from player
NSLog(@"value at index 10 is:%i", value);
}
@end
Here I include 'Stem.h' since player will require stem in order to return stem.value
//Part (v)
// Player.h
#import <Foundation/Foundation.h>
#import "Stem.h"
@interface Player : NSObject {
Player *player;
}
@property(nonatomic, retain) Stem *stem;
@property(nonatomic, retain) Player *player;
-(void) playAudio;
@end
This is where things go wrong, my NSLog statement tells me that value is 0, even though I can see that it's (e.g.) 14 in stem. The compiler gives no errors either.
//Part (vi)
// Player.m
#import "Player.h"
@implementation Player
@synthesize player;
@synthesize stem;
-(void)playAudio {
int value = stem.value;
NSLog(@"value is:%i", value );
}
@end
This is my first proper go at an object-orientated project so I'm learning on the job, any suggestions as to why I can't access stem.value in my Player class?
My ideas on how the various objects in such a program interact with one another (& the correct syntax) are still hazy so please forgive me for crazy n00b errors in my code :)
Upvotes: 1
Views: 159
Reputation: 4092
where are you declaring stem within player? if you are declaring it within the player.h then you will need the import of stem.h within the player.h and not player.m.
edit: yeah its still undeclared because you have stem declared in the view controller not the player. hmm seems to be afew things out of whack here. it really depends on how your code will actually work
#import Stem.h
@interface Player : NSObject {
NSMutableArray *player1;
}
@property(nonatomic,retain) NSMutableArray *player1;
@property(nonatomic,retain) Stem *stem;
-(void) playAudio;
@end
#
import "Player.h"
@implementation Player
@synthesize player1, stem = _stem;
-(void)playAudio {
NSLog(@"play audio called");
NSLog(@"index[0] is: %i", _stem.index[0]);//stem.index[0] will be a problem here as its not a c array
}
@end
and then in ur controller
player.stem = stem;
and im not sure why ur creating a stem pointer within the stem class.
@interface Stem : NSObject {
int *index;
int numberOfStems;
}
@property(nonatomic,readwrite) int *index;
and if its an array of stems you want then create that in the controller
edit : after you have the lines
player = [[Player alloc] init];
[player playAudio];
add
player.stem = stem;
you have to assign the pointer within player to the stem that you created in the view controller
Upvotes: 3
Reputation: 112873
The best way is to create a method in the Stem
class like:
value = [stem valueAtIndex:i];
That way there is less coupling and the way the values are held in the Stem
class is not exposed and can be changed later if necessary without preaching the access calls.
Upvotes: 2