0

I'm new in Objective C and stuck on this problem already 5 days)) What i have to do is write implementation for simple task about city and metropolis. I have class City with properties and class metropolis that has an global array which adds city object through createCity method. I have implemented this task but this arrays returns nothing. Can anybody help me?

Here is part of the task:

1. Write a “City” class, which inherits from NSObject. Your class should contain the following:
Variables:
name, age, population.
Instance methods:
setName:age:population (single method) which set city’s name, age and population. getName, getAge, getPopulation which return city’s name, age and population, respectfully.
nextDay which adds a random number to city’s population, then subtracts a random number from city’s population. Figure out a way to generate random numbers yourself.
2. Create an instance of City class, set its name, age and population as you want.
3. Write a for-­‐loop (if in doubt how to do it – google or use Xcode’s help system) for 10 steps. Each step send ‘nextDay’ message to your object and print out the population.

    4. Write a “Metropolis” class. It should contain the following:
Variable:
array of 10 cities.
Instance method:
createCity:atIndex:withPopulation: (single method) which creates a city with first parameter being a name at index (from the second parameter) and sets its population to that of third parameter. So, you should be able to do this:
[myMetropolis createCity: @”Almaty” atIndex: 2 withPopulation: 1500000]
5. Create an instance of Metropolis class and create all 10 cities.

Here is my implementation:

City.h

#import <Foundation/Foundation.h>

@interface City : NSObject
{
    NSString* name;
    int age;
    int population;
}

-(void)setName: (NSString*)n age: (int)a population: (int)p;
-(NSString*)getName;
-(int)getAge;
-(int)getPopulation;
-(void)nextDay;


@end

City.m

#import "City.h"

@implementation City

-(void)setName:(NSString*)n age:(int)a population:(int)p
{
    name = n;
    age = a;
    population = p;
}

-(NSString*)getName
{
    return name;
}

-(int)getAge
{
    return age;
}

-(int)getPopulation
{
    return population;
}

-(void)nextDay
{
    int r = arc4random() % 100;
    int r2 = arc4random() % 100;
    population = population + r;
    population = population - r2;

}


@end

Metropolis.h

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

@interface Metropolis : NSObject{
        NSMutableArray* myArray;
    }



-(void)createCity: (NSString*)n atIndex: (int)a withPopulation: (int)p;

-(NSMutableArray*) getArray;

@end

Metropolis.m

#import "Metropolis.h"
#import "City.h"
@implementation Metropolis

NSMutableArray* myArray = nil;
- (void)initialize {
        myArray = [[NSMutableArray alloc]initWithCapacity:10];
}

-(void)createCity:(NSString*)n atIndex:(int)a withPopulation:(int)p
{
    City* newCity = [[City alloc]init];
    [newCity setName:n age:0 population:p];

    [myArray insertObject:newCity atIndex:a];

}
-(NSMutableArray*)getArray
{
    return myArray;
}




@end

main.m

#import <Foundation/Foundation.h>
#import "City.h"
#import "Metropolis.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Metropolis* myMetropolis = [[Metropolis alloc]init];
        [myMetropolis createCity:@"Aktobe" atIndex:0 withPopulation:15];
        [Metropolis initialize];
        NSMutableArray* c = [[NSMutableArray alloc]init];
        c = [myMetropolis getArray];


        NSLog(@"%@", [[c objectAtIndex:0] getName]);

    }
    return 0;
}
0

3 Answers 3

1

The method for initialization is -(void)init; this method should be overwritten in your implementation of Metropolis. You are calling - (void)initialize; which is wrong in this case.

So, simply change - (void)initialize { to -(void)init { in your implementation of Metropolis and delete the line: [Metropolis initialize]; in main.

After the comment below the proper init method should be:

-(id) init { 
self = [super init]; 
if (self) { 
    myArray = [[NSMutableArray alloc]initWithCapacity:10]; 
    } 
    return self; 
} 
Sign up to request clarification or add additional context in comments.

4 Comments

U mean just rename it and don't call in Main?
No rename it! Because you call [[Metropolis alloc]init] which is correct, but remove [Metropolis initialize];. Note: you are confused because the init-method is called initialize, but there is a class method called initialize which you will not use, but you can see a description for it here: stackoverflow.com/questions/6191480/…
Simply renaming initialize to init is not enough you will also need to assign self to a call to [super init] and return self.
Joe is right. You have to use the following: -(id) init { self = [super init]; if (self) { myArray = [[NSMutableArray alloc]initWithCapacity:10]; } return self; }
1

I've rewritten my answer to make it more complete, and to incorporate some of the other ideas generated in the other answers, especially @Hannes Sverrisson

The easy way to fix your issue is to call initialize BEFORE createCity (otherwise your trying to add objects to a nil array) and to also make sure you're not calling initialize from a static context. i.e. change [Metropolis initialize]; to [myMetropolis initialize];

The better way, and by better I mean more consistent with typical objective-c design, you should override the instance method init. This is done in the Metropolis implementation and replaces your initialize method.

-(id) init { 
    self = [super init]; 
    if (self) { 
        myArray = [[NSMutableArray alloc]initWithCapacity:10]; 
    } 
    return self; 
} 

or to make it more fun, create a new init method that takes the number of cities as a parameter.

    -(id) initWithNumberOfCities:(NSInteger)numCities { 
    self = [super init]; 
    if (self) { 
        myArray = [[NSMutableArray alloc]initWithCapacity:numCities]; 
    } 
    return self; 
} 

Then in your main method, remove the call to [Metropolis initialize]. The reason for this is when you say:

Metropolis* myMetropolis = [[Metropolis alloc]init];

or

Metropolis* myMetropolis = [[Metropolis alloc]initWithNumberOfCities:10];

the init method is being called inline after the allocation takes place.

3 Comments

unfurtunatly it didn't help((
also, you need to call initialize before createCity. otherwise your array is still nil when you try to do the insert
If that solved the issue, please mark the answer as accepted. Also, just as another tip, you don't need to allocate a new array before assigning it to c. simply NSMutableArray *c = [myMetropolis getArray] should work.
0

You don't need to write getters or create backing instance variables. You can use Objective-C 2.0's @property syntax.

@property (strong) NSString *name;
@property (assign) NSInteger age;
@property (assign) NSInteger population;

- (void)setName:(NSString*)name age:(NSInteger)age population:(NSInteger)population;
- (void)nextDay;

Then you access the properties using self.name, self.age, self.population or if you need to access the backing variable itself, _name, _age, _population.

1 Comment

Thank u so much, but our teacher demand to write code in that way. Because we have just started studying Objective-c

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.