To-One Relationship


#1

The chapter gives an example of a To-one relationship as
Person *spouse

It doesn’t give an example of what method to use to assign a spouse to the employee. I was hoping someone can give me an example of how to write the .h, .m, and main files. Thank you!


#2

I tried doing the property/synthesize for spouse, but it doesn’t return the name just the address. Not sure if I’m on the right track or not.


#3

I don’t quite understand the question, but maybe the following example might help to clarify.

main.m

//  main.m

#import <Foundation/Foundation.h>
#import "Couple.h"
#import "Person.h"

int main (int argc, const char * argv[])
{
    @autoreleasepool
    {
        Couple *C1 = [[Couple alloc] init];
        Person *P11 = [[Person alloc] init];
        Person *P12 = [[Person alloc] init];
        P11.name = @"P11";
        P12.name = @"P12";
        
        // Before forming to-one relationships
        NSLog (@"%@", C1);
        
        // Form to-one relationships
        C1.member1 = P11;
        C1.member2 = P12;
        
        // After forming to-one relationships
        NSLog (@"%@", C1);
    }
    return 0;
}

Couple.{h,m}

//  Couple.h

#import <Foundation/Foundation.h>

@class Person;

@interface Couple : NSObject

@property (strong) Person *member1;
@property (strong) Person *member2;

@end

//  Couple.m

#import "Couple.h"

@implementation Couple

@synthesize member1;
@synthesize member2;

- (NSString *)description
{
    return [NSString stringWithFormat:@"Couple {member1: %@ member2: %@}", member1, member2];
}

Person.{h,m}

//  Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (copy) NSString *name;

@end

//  Person.m

#import "Person.h"

@implementation Person

@synthesize name;

- (NSString *)description
{
    return [NSString stringWithFormat:@"Person {name: %@}", name];
}

@end

The output:

2012-09-19 13:32:20.183 To-One-Relationship[63017:403] Couple {member1: (null) member2: (null)}
2012-09-19 13:32:20.185 To-One-Relationship[63017:403] Couple {member1: Person {name: P11} member2: Person {name: P12}}

#4

Thanks for the reply! Since I’m new to Objective C, the only knowledge I am getting is what’s in the book and whatever I can find on the internet. Since there isn’t a “To-One” example in this book, I feel a little lost. Your code helps a lot, but I don’t know what this means:

// Form to-one relationships
        C1.member1 = P11;
        C1.member2 = P12;

I understand everything in your code except for the code above. Can you give me more details on that and is that necessary for every time we need to do a “To-One” relationship?

Also, what does (copy) mean in the following line:

@property (copy) NSString *name;

#5

These two assignment statements

// Form to-one relationships
C1.member1 = P11;
C1.member2 = P12;

are setting the values of the properties member1 and member2 in the Couple object C1.

They are equivalent to these statements:

[C1 setMember1:P11];
[C1 setMember2:P12];

They are all setting up relationships between objects (connecting one object to another object).

As for the copy attribute in the property declaration:

@property (copy) NSString *name;

That causes a copy operation to take place when the value of the name property is set:

NSString *someName = @"...";
Person *p = [[Person alloc] init];
p.name = someName;

if (p.name != someName)
{
     // name is a copy of someName, because of the copy attribute of name property.
     NSLog (@"name is a copy of someName!");
}
else
{
    // name would be a reference to someName, had the copy attribute of name property been assign, retain, or strong.
    NSLog (@"name is a reference!");
}

These are all fundamental concepts. You can read more about them in the official Objective-C document set.
Bring up the Documentation in Organizer in Xcode, and go to Tools & Languages/Objective-C and read as much as you can.

You can also find lots of examples in Class References. For example, if you look up the NSString Class Reference you will see two sections: Companion guides & Related sample code. So get into the habit of reading the Class References.


#6

Thanks for this simple example. It makes a lot of sense now. No way I would have figured this out on my own. I will work on this some more tonight and hopefully things will go well.


#7

ibex, if you don’t mind, can you take a quick look at this “to-one” program I made up just for the sake of practice?

state.h

#import <Foundation/Foundation.h>
@class Capital;

@interface State : NSObject
{
    NSString *stateName; 
    int statePopulation;
    Capital *city;
}

@property (strong) NSString *stateName; 
@property int statePopulation;
@property (strong) Capital *city; //To-One Relationship to city

-(NSString *) capitalCity;

@end

State.m

#import "State.h"
#import "Capital.h"

@implementation State

@synthesize stateName;
@synthesize statePopulation;
@synthesize city;

-(NSString *) capitalCity
{
    return [city capitalName];
}

@end

Capital.h

#import <Foundation/Foundation.h>

@interface Capital : NSObject
{
    NSString *capitalName;
}

@property (strong) NSString *capitalName;

@end

Capital.m

#import "Capital.h"

@implementation Capital

@synthesize capitalName;

@end

main.m

#import <Foundation/Foundation.h>
#import "State.h"
#import "Capital.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        //Create States
        State *state1 = [[State alloc] init];
        [state1 setStateName:@"Texas"];
        [state1 setStatePopulation];
        
        State *state2 = [[State alloc] init];
        [state2 setStateName:@"Louisiana"];
        [state2 setStatePopulation:5000000];
        
        State *state3 = [[State alloc] init];
        [state3 setStateName:@"California"];
        [state3 setStatePopulation];
        
        //Create Capitals
        Capital *city1 = [[Capital alloc] init];
        [city1 setCapitalName:@"Austin"];
        
        Capital *city2 = [[Capital alloc] init];
        [city2 setCapitalName:@"Baton Rouge"];
        
        Capital *city3 = [[Capital alloc] init];
        [city3 setCapitalName:@"Sacramento"];
        
        //Setting up the to-one relationship
        [state1 setCity:city1];
        [state2 setCity:city2];
        [state3 setCity:city3];
        
        NSMutableArray *states = [[NSMutableArray alloc] init];
        [states addObject:state1];
        [states addObject:state2];
        [states addObject:state3];
        
        for (State *s in states) {
            NSLog(@"The capital of %@ is %@ with a population of %d", [s stateName], [s capitalCity], [s statePopulation]);
        }
        
    }
    return 0;
}

#8

Looks good.
However, I would change the method -(NSString *)capitalCity to -(NSString *)nameOfCapitalCity, because -(NSString *)capitalCity sounds like it is returning a Capital object.


#9

Thanks ibex! Thanks to ALL your help, I am really enjoying learning out of this book.