Objective C - importing headers with same variable names

I have a android game ready to launch and I'm currently working on porting it to iOS.

I'm fairly new to Objective C and C in general and I'm not sure exactly how @properties and @synthesize and #imports work.

My game shares a method file called gMain. This file includes the shared methods between objects. I have an object called Fish and in that object contains a method which requires the x,y value of another object called Fish2.

I'm unsure of how to access the variables when both Fish and Fish2 share the same variable names, int x, int y.

will this work?

//Fish.h 
@interface Fish 
{
     int x, y; 
} 
@property int x, y; 
-(void)blah;
@end  


//Fish2.h
@interface Fish2
{
    int x, y;
}
@property int x, y; 
@end    


//Fish.m 
#import Fish.h 
@implementation Fish  
@synthesize x, y;

-(void)blah
{
    x = Fish2.x;
    y = Fish2.y;
}
@end 


//Fish2.m
#import Fish2.h
@implementation Fish2
@synthesize x, y;
@end

Answers


I'm not sure if you are wanting to deal with a single class, with two instances, two separate classes. I'll try to give an example of each and try to explain what the code is doing.

Single Class, Two Instances

Fish.h

@interface Fish : NSObject
@property (nonatomic, assign) int x;
@property (nonatomic, assign) int y;
- (void) someMethod;
@end

So you are defining a new object called FishA and the object has 2 public properties, x and y. The 2 items in parenthisis nonatomic and assign tell the compiler extra information about the properties. Bassicaly nonatomic means not to worry about thread safty and assign means that the property is a base type, not an object.

Fish.m

#import "Fish.h"

@implementation Fish
@synthesize x = _x;
@synthesize y = _y;

- (id) init {
    self = [super init];
    if (self) {
        // Initilize default values
        // Only use the _x and _y in init
        // no other place
        _x = 0;
        _y = 0;
    }
    return self;
}

- (void) someMethod {
    // Set the values
    self.x = 10;
    self.y = 10;

    // Access the values
    NSLog(@"X: %d", self.x)
    NSLog(@"Y: %d", self.y)
}

So the @synthesize statments will create two methods for you, one to set the value and one to get the value. In the statements above the x tells the compiler to create the methods for the x property, the _x is the name of the interal storage variable for the property. It is much better that the property and the internal storage are separatly named, it makes the code cleaner and easier to understand whats going on.

In th init method we directly set the internal variable with the initial values. The init method is generally the only place you want to access the internal variables.

Use

#import "Fish.h"

- (void) example {
    Fish *fishA = [[Fish alloc] init];
    Fish *fishB = [[Fish alloc] init];

    fishA.x = 10;
    fishB.x = 20;

    [fishA someMethod];
    [fishB someMethod];
}
Separate Classes

FishA.h

@interface FishA : NSObject
@property (nonatomic, assign) int x;
@property (nonatomic, assign) int y;
@property (nonatomic, assign) int size;
- (void) someMethod;
@end

FishA.m

#import "FishA.h"

@implementation FishA
@synthesize x = _x;
@synthesize y = _y;
@synthesize size = _size;

- (id) init {
    self = [super init];
    if (self) {
        // Initilize default values
        // Only use the _x and _y in init
        // no other place
        _x = 0;
        _y = 0;
        _size = 10;
    }
    return self;
}

- (void) someMethod {
    // Set the values
    self.x = 10;
    self.y = 10;

    // Access the values
    NSLog(@"X: %d", self.x)
    NSLog(@"Y: %d", self.y)
}

FishB.h

@interface FishB : NSObject
@property (nonatomic, assign) int x;
@property (nonatomic, assign) int y;
@property (nonatomic, strong) NSColor *color;
- (void) someMethod;
@end

The color propery looks a little different. Because color is an object and not a base type we need to tell the compiler how we want to handle it. The strong tells the compiler to hold on to this object untill we are done with it. The other option would be weak and that tells the compiler not to hold on to the object. Generally speaking, with objectes, use strong.

FishB.m

#import "FishB.h"

@implementation FishB
@synthesize x = _x;
@synthesize y = _y;
@synthesize color = _color;

- (id) init {
    self = [super init];
    if (self) {
        // Initilize default values
        // Only use the _x and _y in init
        // no other place
        _x = 0;
        _y = 0;
        _color = [NSColor blueColor];
    }
    return self;
}

- (void) someMethod {
    // Set the values
    self.x = 10;
    self.y = 10;

    // Access the values
    NSLog(@"X: %d", self.x)
    NSLog(@"Y: %d", self.y)
}

So I've created two separate classes, FishA has a size property and FishB has a color property. Both fish have the x and y properties. Not overly exciting but it makes the two classes different.

Use

#import "FishA.h"
#import "FishB.h"

- (void) example {
    FishA *fishA = [[FishA alloc] init];
    FishB *fishB = [[FishB alloc] init];

    fishA.x = 10;
    fishB.x = 20;

    fishA.size = 50; // Works
    fishB.size = 50; // Will not work

    fishA.color = [NSColor redColor]; // Will not work
    fishB.color = [NSColor redColor]; // Works
}

does this synthesize both xs and ys from the 2 objects?

No.

Your code won't compile. You've left out all the @interface, @implementation, and @end directives that tell the compiler what class you're talking about. A @synthesize directive will always be included between @implementation *classname* and @end, and it will only synthesize a property for the indicated class.

If you correct your code, the effect of the @synthesize should be obvious.

//Fish.h
@interface Fish
{
    int x, y;
}
@property int x, y;

@end

//Fish.m
#import Fish.h
#import Fish2.h       // it's not clear why you'd need this

@implementation Fish

@synthesize x, y;     // creates accessors for properties x and y of class Fish

@end

This will not work

    -(void)blah
{
    x = Fish2.x;
    y = Fish2.y;
}

You need to create a pointer for Fish2. Something like this...

    -(void)blah
{
    Fish2 *selectedFish = //wherever the instance of the fish is.
    x = selectedFish.x;
    y = selectedFish.y;
}

If Fish creates an instance of fish2 maybe doing something like this would be more helpful.

    -(void)blahWithFish:(Fish2)currentFish
{
    x = currentFish.x;
    y = currentFish.y;
}

If you do something like that you can pass the fish to this method.

Also is there a reason for fish2? Are you not just creating 2 fish objects? Do they perform the same task? Maybe fish2 should inherit from Fish?

Does that help?


Need Your Help

Is there a keyboard shortcut for cycling through pragma marks or methods in Xcode?

xcode

Often I want to quickly switch my focus back-and-forth between different methods in my code.

Confusion with Reusable Cells (incorrect cells affected after scroll)

ios ios4 uitableview

I'm sure this question is not unique, but I've not found other sources to solve it. Actually, those have been causing more confusion. Please shed light if you can.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.