Use the variable of a for loop in a property name - objective-c

I want to use the variable of a for loop in a property name, example:
#interface
{
Player *rival1, *rival2, *rival3;
}
int number;
for (number=1; number<=3; number++){
rival+number = [[Player alloc] init]; //The compiler accepts this.
rival+number.name = #"";
//^This line gives the error: "use of undeclared identifier 'rival'"
//For the first loop, I want it work like: rival1.name = #"";
}

This isn't a particularly clean way of approaching this, but to answer the question as you've posed it:
- (void)generateRivals
{
for (int i = 1; i < 4; i++)
{
NSString *propertySetString = [NSString stringWithFormat:#"setRival%d", i];
Rival *rival = [[Rival alloc] init];
[self performSelector:#selector(NSSelectorFromString(propertySetString)) withObject:rival];
}
}
We create a selector (I haven't tested this, but it should work in theory) that corresponds to the getter for the property instance represented by i.
Based on comments you've added, it seems like what you really want is a variable number of players (perhaps not exceeding a certain number) with the ability to reference them individually.
Architecturally, rather than create properties pointing to each respective rival, put them all in an array (and keep it as a property on your class). So you'd create them like this:
- (void)generateRivals:(NSUInteger)numberOfRivals
{
NSMutableArray *rivalsArray = [[NSMutableArray alloc] initWithCapacity:numberOfRivals];
for (int i = 0; i < numberOfRivals; i++)
{
Rival *rival = [[Rival alloc] init];
[rivalsArray insertObject:rival atIndex:i];
}
[self setRivalsArray:rivals];
}
Then, when you need to access a particular rival, call a method like this, which will return the rival at the index number you pass:
- (Rival *)rivalWithNumber:(NSUInteger)number
{
return [[self rivalsArray] objectAtIndex:number];
}

you cant create the properties variable names on the fly and use it, as the names get lost during compilation
you can put them in an array and enumerate over it
Player rival1 = [[Player alloc] init];
Player rival2 = [[Player alloc] init];
Player rival3 = [[Player alloc] init];
for (Player *p in #[rival1, rival2, rival3]) {
p.name = #"";
}
probably the best way would be to maintain the rivales in the array from the beginning
#interface …
#property(strong) NSArray *rivals;
#end
#implementation …
//in some useful method, like initializer
_rivals = [NSMutableArray array]
for (int i = 0; i < 3 ++i){
//create player and add to array
}
#end
You might want to look into Key Value Coding.
You need to create properties for your rivals
#interface …
#property(strong) Player *rival1;
#property(strong) Player *rival2;
#property(strong) Player *rival3;
#end
#implementation …
-(id)init…
{
if(self = [super init…]){
for (int i = 1; i < 4; ++i) {
Player *rival = [[Player alloc] init];
rival.name = [NSString stringWithFormat:#"rival%d", i];
[self setValue: rival forKey:[NSString stringWithFormat:#"rival%d", i]];
}
}
return self;
}
#end

Instead of running a for loop to set the names of the players to #"" just add the line
name = #"" in your init method of your Player class. It's faster and more practical than to write a for loop. You can also create a method like
-(id)initWithName:(NSString *)initName{
self = [super init];
if (self){
name = initNane;
}
return self;
}
to set the name of your player at the moment it's created. Although if you want absolutely a for loop, you can use the method posted by vikingosegundo previously.

Related

Using method parameters check to see if array object is equal to another string (objective-C)?

I'm all self taught so please keep the techincal jargin to a minimum. Theoretically if I had a method and it had a parameter that is the name of an array. How do I check to see if that array index 5 is equal to #"Yes" or #"No". I know it's one of these because its testing to see if the picture is appearing in the veiw controller. Here is an example:
-(void)methodName :(NSMutableArray *)arrayNameInMethod {
if ( [NSMutableArray *(arrayNameInMethod) indexOfObject:5] == #"Yes"){
//Hide a different picture assocciated with the Array
} else {
//Unhide a different picture assocciated with the Array
};
Also how do you do use the parameter "arrayNameInMethod" to replace the object. Basically:
if(Picture Clicked and picture is Unhidden) {
[NSMutableArray *(differentArrayNameInMethod) replaceObjectAtIndex:5 withObject: #"True)
};
(this is all in another method)
Comment #2: You can't use the parameters the same way because it's a string. You can't access an array with a name as a string.
Thank you so much!
I think what you will need is a dictionary, mapping the name to the array. I will give a barebones implementation:
#interface YourClass()
{
NSMutableDictionary *_arrayMap;
}
#end
#interface YourClass
- (instancetype)init
{
self = [super init];
if (self) {
// You might do this somewhere else, like viewDidLoad:
_arrayMap = [NSMutableDictionary new];
}
return self;
}
- (void)someMethod
{
// Some functionality to add a new array:
// Note the array contains NSNumber and NSString objects:
_arrayMap[#"sampleName"] = [#[ #(0), #"one", #(2.0), #"three", #(4), #(YES)] mutableCopy];
}
-(BOOL)checkForConditionInArrayNamed:(NSString *)arrayName
{
BOOL retval = NO;
NSMutableArray *array = _arrayMap[arrayName];
if ([array count] > 5) {
id obj = array[5];
if ([obj isKindOfClass:[NSNumber class]])
retval = [obj boolValue];
}
return retval
};
#end
You then call checkForConditionInArrayNamed: to check for the condition of the named array and act accordingly.

Singleton How to Declare NSMutableArray

I am trying to implement a singleton which contains an NSMutableArray* what I've done so far is below.
Singleton.h
#import <Foundation/Foundation.h>
#interface Singleton : NSObject{
NSMutableArray* ClassArray;
}
#property NSMutableArray* ClassArray;
+(Singleton*) getInstance;
- (void) SetClassArray:(NSMutableArray *)InputClassArray;
- (NSMutableArray*) GetClassArray;
Singleton.m
#import "Singleton.h"
#implementation Singleton
#synthesize ClassArray;
static Singleton *singletonInstance;
+ (Singleton*)getInstance{
if (singletonInstance == nil) {
singletonInstance = [[super alloc] init];
}
return singletonInstance;
}
- (void) SetClassArray:(NSMutableArray *)InputClassArray{
ClassArray = InputClassArray;
}
- (NSMutableArray*) GetClassArray{
return ClassArray;
}
#end
what I'm wondering is where does [[NSMutableArray alloc]init]; go? or do i not need it. Also when ClassArray is initialised i want some default values, (the return from another function,[DatabaseFunctions GetClassDefaultArray] ) again where does this go?. I'm assuming the line below singletonInstance = [[super alloc] init]; however it doesn't accept ClassArray.
I have an application consisting of four view controllers, what I need is an nsmutablearray that can be accessed and written to from any of these views. There are three others in total.
Thanks
I'm wondering is where does [[NSMutableArray alloc]init]; go? or do i not need it
That depends on what you expect in your getter. Is reasonable for your use case to return nil in GetClassArray?
You could guard against it by returning an empty array if it is nil:
- (NSMutableArray*) GetClassArray{
if ( ! ClassArray ) {
ClassArray = [[NSMutableArray alloc] init];
}
return ClassArray;
}
i want some default values
You can populate your array as you see fit whenever you want, the best place to start would probably be your init method:
+ (Singleton*)getInstance{
if (singletonInstance == nil) {
singletonInstance = [[super alloc] init];
NSMutableArray *array = ...;
[singletoneinstance SetClassArray:array];
}
return singletonInstance;
}
As a side note, I would recommend reading up on some naming conventions so you don't mixed up between class names and variable names in the future.

Objective-C Array of Objects

Although experienced with OOP, I am an absolute newbie with Objective-C. I have the following code:
// header files have been imported before this statement...
CCSprite *treeObstacle;
NSMutableArray *treeObstacles;
#implementation HelloWorldLayer {
}
-(id) init
{
// create and initialize our seeker sprite, and add it to this layer
treeObstacles = [NSMutableArray arrayWithObjects: nil];
for (int i=0; i<5; i++) {
treeObstacle = [CCSprite spriteWithFile: #"Icon.png"];
treeObstacle.position = ccp( 450-i*20, 100+i*20 );
[self addChild:treeObstacle];
[treeObstacles addObject: treeObstacle];
}
NSLog (#"Number of elements in array = %i", [treeObstacles count]);
return self;
}
- (void) mymethod:(int)i {
NSLog (#"Number of elements in array = %i", [treeObstacles count]);
}
#end
The first NSLog() statement returns "Number of elements in array = 5". The problem is that (although treeObstacles is a file-scope variable) when calling the method "mymethod", I'll get an EXC_BAD_ACCESS exception.
Can anybody please help me?
Thanks a lot
Christian
you created treeObstacles by
treeObstacles = [NSMutableArray arrayWithObjects: nil];
which will return an autoreleased object, and you didn't retain it so it will be released soon
you have to retain it by calling retain on it
[treeObstacles retain];
of simple create it by
treeObstacles = [[NSMutableArray alloc] init];
and you need to remember to release it when done like
- (void)dealloc {
[treeObstacles release];
[super dealloc];
}
you need to read more about management in Objective-C
https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
or use ARC so no need to worry retain/release anymore
http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
another problem, you need to call [super init] in your init method
- (id)init {
self = [super init];
if (self) {
// your initialize code
}
}
otherwise your object won't initialize properly

Xcode Passing NSMutableArray from one class to another

I know this question has been asked countless of times. But none of them seems to be working! Please help! I am unable to pass arrays from one class to another. Blow are my codes
firstClass has an array declared
#FirstClass.h
- (void)viewDidLoad
{
testArray = [[NSMutableArray alloc] init];
[testArray addObject:#"test"];
[testArray addObject:#"test2"];
[testArray addObject:#"test3"];
//method to pass array
TableViewController *tvc = [[TableViewController alloc] init];
tvc.getData = [[NSMutableArray alloc] init];
tvc.getData = testArray;
NSLog(#"%i", [tvc.getData count]); // returns a value n
Here i get count of 3
}
TableViewController.h
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%i", [getData count]); // returns a value n
Here i get 0
//Set the title
self.navigationItem.title = #"Countries";
}
I tried
FirstClass *fc = [[FirstClass alloc] init];
getData = fc.testArray;
Doesn't work as well. I tried writing a method and calling the method from my second class.
Ended up with #interface error.
Sorry, this is my first time on objective c. Am java educated.
Please help!
For the second problem, why the fc.testArray does not work is that viewDidLoad is called only after the view property is called. (lazy initialization)
So it works if you do like
FirstClass *fc = [[FirstClass alloc] init];
fc.view;
getData = fc.testArray;

iOS - Storing groups of UILabels into a NSMutableArray

I'm creating UILabels dynamically in a for each loop. Every loop that is run creates 1-4 UILabels.
What I want is that I put these UILabels into my NSMutableArray and being able later to easy retrieve the data.
My original thought was to put these UILabels into a NSDictionary and use [dictGroupLabels setValue:uiLabel1 forKey:#"uiLabel1"] and then [dictGroupLabels setValue:uiLabel2 forKey:#"uiLabel2"] and so on. And then put this dictionary into my NSMutableArray for each loop. Later on I could access the values like UILabel *label = [[myArray objectAtIndex:0] valueForKey:#"uiLabel1"] BUT that unfortunately doesn't work since UILabels don't conform to the NSCopying protocol.
So with this in mind how would you solve this?
this question provided more information on what you are trying to accomplish. Since you know for a fact, the possible set of labels you are trying to create in each case, I would highly recommend using mutable dictionaries instead of arrays.
To illustrate, given the following hypothetical class definition:
#interface MyClass: NSObject {
NSMutableDictionary * _labelDict;
}
#property (nonatomic, retain) NSMutableDictionary * labelDict;
- ( void )methodA;
- ( void )methodB;
- (NSMutableDictionary *) labelsForRunLoop: (NSUInteger) loopIdx;
#end
You would have the following, hypothetical, class implementation:
#implementation MyClass
#synthesize labelDict = _labelDict;
- ( id ) init {
if( ( self = [ super init ] ) ) {
[self setLabelDict: [NSMutableDictionary dictionaryWithCapacity: 8]];
}
}
- ( void ) dealloc {
[ self.labelDict release ];
[ super dealloc ];
}
- ( void ) methodA {
for(NSUInteger i = 0; i < some index; i++) {
[self.labelDict setObject: [self labelsForRunLoop: i] forKey: [NSString stringWithFormat: #"%d", i]];
}
}
- ( void ) methodB {
// Locate the label you need to work with. Example based on this crude pseudo code
NSMutableDictionary * subDict = (NSMutableDictionary *) [self.labelDict objectForKey: #"0"];
UILabel * theLabel = (UILabel * ) [subDict objectForKey: #"UILabel.Z"];
theLabel.text = #"Label 1";
}
- (NSMutableDictionary *) labelsForRunLoop: (NSUInteger) loopIdx {
NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithCapacity: 4] ;
[dictionary setObject: create-w-label forKey: #"UILabel.W"];
[dictionary setObject: create-x-label forKey: #"UILabel.X"];
[dictionary setObject: create-y-label forKey: #"UILabel.Y"];
[dictionary setObject: create-z-label forKey: #"UILabel.Z"];
return [dictionary retain];
}
#end
This is basically pseudo code and will not successfully compile. However it will serve as a good starting point. You probably want to store each label dictionary under some key that makes sense, instead of just using the loop's index. Hope this helps.
They don’t need to adhere to NSCopying to be added to an array. It sounds like you just need to do something like this:
NSMutableArray *mainArray = [NSMutableArray array];
for(int i = 0; i < 5; i++)
{
NSMutableArray *subArray = [[NSMutableArray alloc] initWithCapacity:5];
for(int j = 0; j < 4; j++)
{
UILabel *label = [[UILabel alloc] init];
// etc.
[subArray addObject:label];
[label release];
}
[mainArray addObject:subArray];
[subArray release];
}
// then, to get one of the labels:
UILabel *someSpecificLabel = [[mainArray objectAtIndex:2] objectAtIndex:1];