Reputation: 309
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;
}
Upvotes: 0
Views: 341
Reputation: 2409
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.
Upvotes: 1
Reputation: 18157
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;
}
Upvotes: 1
Reputation: 7710
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
.
Upvotes: 0