I have a series of 5 iVars. (highscore01, highscore02, highScore03, highScore04, highScore05) I want to update a particular iVar with an integer value. The iVars are defined as ints. The iVars are in a Class called HighScores.
The particular iVar to be updated is the one with the lowest current value stored in it. I want to replace the lowest value with a new value.
I have a method that identifies the ivar with the lowest value and returns a String "theString" containing the name of the iVar to be updated.
My question: How do I use the "theString" to update the correct iVar.
Here is a sample of the code.
// If any of the highScore iVars contain 0, then they are still empty.
// Find the first empty iVar and store score there.
if (scoreVarsFullFlag == NO) // Flag to indicate if any iVars are still zero
{
if (theHighScores.highScore01 == 0)
theHighScores.highScore01 = mainScores.scoreTotal;
else if (theHighScores.highScore02 == 0)
theHighScores.highScore02 = mainScores.scoreTotal;
else if (theHighScores.highScore03 == 0)
theHighScores.highScore03 = mainScores.scoreTotal;
else if (theHighScores.highScore04 == 0)
theHighScores.highScore04 = mainScores.scoreTotal;
else if (theHighScores.highScore05 == 0)
{
theHighScores.highScore05 = mainScores.scoreTotal;
scoreVarsFullFlag = YES; // Last scores iVar turns nonzero - set Flag to YES, to indicate no non-zero iVars
}
}
else
{
NSLog(#"The Lowest is at %#", [theHighScores findLowestHighScore]);
NSString * theString;
theString = [NSString stringWithString:[theHighScores findLowestHighScore]];
NSLog(#"The String is: %#", theString);
theHighScores.theString = mainScores.scoreTotal; // This fails
}
The last line is where I try to set the iVar identified in "theString" to the new score number. "theString" does contain the name of the iVar to update, i.e. "HighScore03", etc.
If I was setting this manually, it would be;
theHighScores.highScore03 = mainScores.scoreTotal;
Any insight would be much appreciated.
If I were you I'd just use a mutable array instead to allow sorting and easily pick off the lowest item.
///store this in your app delegate
NSMutableArray *highscores = [[NSMutableArray alloc] init];
//then when you want to add a high score
[highscores addObject:[NSNumber numberWithDouble:mainScores.scoreTotal]];
NSSortDescriptor *myDescriptor;
myDescriptor = [[NSSortDescriptor alloc] initWithKey:#"doubleValue" ascending:NO];
[highscores sortUsingDescriptors:[NSArray arrayWithObject:myDescriptor]];
///remove the last object if it's over 5
if ([highscores count]>5) {
[highscores removeLastObject];
}
I think mjdth's solution is probably the best, but you could also use -setValue:forKey:, though you'd have to switch to using NSNumbers, rather than ints.
[theHighScores setValue: [NSNumber numberWithInt: mainScores.scoreTotal] forKey: [theHighScores findLowestHighScore]];
Sounds like you're trying to do some basic type introspection. Specifically, using NSSelectorFromString.
int newValue = 1;
SEL methodName = NSSelectorFromString(#"setHighScore03:");
[theHighScores performSelector:methodName withObject:newValue];
Related
I am trying to create an array of numbers that I will use later to determin the size of my tableviewcells.
However I am having some issues with the array, After my while statment it comes back as being NULL, yet when I log the values I am getting from my array of objects they are correct... and the if statement works perfectly.
This is my code
int count = 0;
// Cell heights
int smallCell = 69;
int largeCell = 120;
NSNumber *currentHeight = [[NSNumber alloc] init]; // allows int to be stored into NSArray
while (count < seriesSearchArray.count) {
myObj = (SeriesSearchResultItem*)[dataArrayOfObjects objectAtIndex:count];
if (![myObj.seriesNote isEqualToString:#""]) {
NSLog(#"%#", myObj.seriesNote);
currentHeight = [NSNumber numberWithInt:largeCell];
NSLog(#"%#", currentHeight); // correct value shown
[heightArray addObject:currentHeight];
}
else {
currentHeight = [NSNumber numberWithInt:smallCell];
NSLog(#"%#", currentHeight); // correct value shown
[heightArray addObject:currentHeight];
}
NSLog(#"%#", heightArray); // NULL Shown
count ++;
}
So thats if, I am trying to get the value from each of the objects in my array which works, the if statment works perfectly but then when I try to add them to my new array it always comes back as NULL.
Moving comment to answer
You need something like
heightArray = [NSMutableArray arrayWithCapacity:seriesSearchArray.count]
I want to get the index of an object within the NSMutableArray of categories.
The category object has an attribute "category_title" and I want to be able to get the index by passing the value of category_title.
I have looked through the docs and can't find a simple way to go about this.
NSArray does not guarantee that you can only store one copy of a given object, so you have to make sure that you handle that yourself (or use NSOrderedSet).
That said, there are a couple approaches here. If your category objects implement isEqual: to match category_title, then you can just use -indexOfObject:.
If you can't do that (because the category objects use a different definition of equality), use -indexOfObjectPassingTest:. It takes a block in which you can do whatever test you want to define your "test" - in this case, testing category_title string equality.
Note that these are all declared for NSArray, so you won't see them if you are only looking at the NSMutableArray header/documentation.
EDIT: Code sample. This assumes objects of class CASCategory with an NSString property categoryTitle (I can't bring myself to put underscores in an ivar name :-):
CASCategory *cat1 = [[CASCategory alloc] init];
[cat1 setCategoryTitle:#"foo"];
CASCategory *cat2 = [[CASCategory alloc] init];
[cat2 setCategoryTitle:#"bar"];
CASCategory *cat3 = [[CASCategory alloc] init];
[cat3 setCategoryTitle:#"baz"];
NSMutableArray *array = [NSMutableArray arrayWithObjects:cat1, cat2, cat3, nil];
[cat1 release];
[cat2 release];
[cat3 release];
NSUInteger barIndex = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
if ([[(CASCategory *)obj categoryTitle] isEqualToString:#"bar"]) {
*stop = YES;
return YES;
}
return NO;
}];
if (barIndex != NSNotFound) {
NSLog(#"The title of category at index %lu is %#", barIndex, [[array objectAtIndex:barIndex] categoryTitle]);
}
else {
NSLog(#"Not found");
}
Not sure that I understand the question but something like this might work (assuming the Mutable Array contains objects of Class "Category"):
int indx;
bool chk;
for (Category *aCategory in theArray)
{
chk = ([[aCategory category_title] isEqualToString:#"valOfCategoryTitle"])
if ( chk )
indx = [theArray indexOfObject:aCategory];
}
Try this code much more simpler:-
int f = [yourArray indexOfObject:#"yourString"];
I'm sure this is really basic but I can't see what I'm doing wrong. Can someone help me understand where I'm going wrong please? I'm working in xcode. I'm trying to make different parts of my view appear depending on values saved in a property list. If the value assigned to a particular UITextField is equal to zero then I want to hide that UITextField. I'm trying to do this like this. gross is the name of a UITextField:
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
gross.text = [array objectAtIndex:7];
if ([array objectAtIndex:7 == 0]) {
gross.hidden = YES;
}
else {
gross.hidden = NO;
}
[array release];
I think the problem is something to do with how I've wrote the if/else statement. I know this is really basic but I don't quite understand where I'm going wrong. So Your help is much appreciated.
Code should read:
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
gross.text = [array objectAtIndex:7];
if ([[array objectAtIndex:7] isEqualToString:#"0"]) {
gross.hidden = YES;
} else {
gross.hidden = NO;
}
[array release];
This assumes that the object at index 7 of your array exists and is a string. If it's actually an NSNumber, then you should instead use the conditional
if ([[array objectAtIndex:7] intValue] == 0) {
Note the above line works for a string where the text contains an int, such as #"0" or #"7".
if ([[array objectAtIndex:7] intValue] == 0)
First mistake is position of closing ]. And second one is you probably have NSString in array, as you have assigned that in text property. So you need to convert it to int by using intValue.
If your array contains nsstring then your condition should look like:
if ([[array objectAtIndex:7] intValue] == 0) {
...
or
if ([[array objectAtIndex:7] isEqualToString:#"0"]) {
1st condition will work also if your array contains NSNumbers (not likely in your case as you assign array elements to text property), but will fail if string is not a valid number - in that case intValue will return 0 as well.
2nd condition will work fine if you're sure that your elements are strings and you want to compare exactly with #"0".
Your condition is equivalent to
if ([array objectAtIndex:0])
because == operator has greater priority and evaluates to 0. Comparing array's element to 0 directly also does not make sense as NSArray cannot contain nil objects anyway
It might be easier to get the length of the array first and make sure that it has enough elements and then start accessing the elements themselves.
how do I set the value of an NSNumber variable (without creating a new object) in objective-c?
Background
I'm using Core Data and have a managed object that has an NSNumber (dynamic property)
passing (by reference) this to another method which will update it
not sure how to update it? if I allocate it another new NSNumber things don't work, which I guess makes sense it's then got a pointer to a different object not the core data object (I guess)
An NSNumber object isn't mutable. This means that the only way to change a property containing a NSNumber is to give it a new NSNumber. To do what you want, you have three options:
1. Pass the Core Data object to the method and have it directly set the property.
- (void)updateNumberOf:(MyCoreDataObject *)theObject {
NSNumber *newNumber = ...; // create new number
theObject.number = newNumber;
}
Called as [self updateNumberOf:theCoreDataObject];
2. Have the update method return a new NSNumber and update it in the caller.
- (NSNumber *)updateNumber:(NSNumber *)oldNumber {
NSNumber *newNumber = ...; // create new number
return newNumber;
}
Called using:
NSNumber *theNumber = theCoreDataObject.number;
theNumber = [self updateNumber:theNumber];
theCoreDataObject.number = theNumber;
3. Pass a pointer to a number variable and update it in the caller (I would only suggest this over option 2 if you need to return something else).
- (void)updateNumber:(NSNumber **)numberPointer {
if(!numberPointer) return; // or possibly throw an error
NSNumber *oldNumber = *numberPointer;
NSNumber *newNumber = ...; // create new number
*numberPointer = newNumber;
}
Called using:
NSNumber *theNumber = theCoreDataObject.number;
[self updateNumber:&theNumber];
theCoreDataObject.number = theNumber;
I did not bother with memory management in any of these examples. Make sure you release/autorelease objects appropriately.
4. (from Greg's comment) Similar to option 1, but passes the key to the update method to be more portable.
- (void)updateNumberOf:(id)theObject forKey:(NSString *)key {
NSNumber *oldNumber = [theObject valueForKey:key];
NSNumber *newNumber = ...; // create new number
[theObject setValue:newNumber forKey:key];
}
Called as [self updateNumberOf:theCoreDataObject forKey:#"number"];
I am trying to detect if an array isn't empty in order to be able to do a certain call.
I tried using if (![array ==nil]) however that doesn't compile.
I'm sure there is a really easy explanation to this.
Update
If array is empty I want to do this:
array = [[NSMutableArray alloc]init];
If it has an object I want to do this:
array = [[userDefaults arrayForKey:#"MyFavorites"] mutableCopy];
If you declared it but did not assign anything to it at all:
NSMutableArray *array;
Then the array will be nil, meaning it isn't there at all so you can't say if it's empty or not, so you can't check anything.
If you did assign something to it, and you want to find out if the existing array is empty or not, that would depend on how you created it first.
If the array was assigned from some convenience method, it's autoreleased, so just do this:
if ([array count] == 0) {
array = [[NSMutableArray alloc] init];
} else {
array = [[userDefaults arrayForKey:#"MyFavorites"] mutableCopy];
}
If the array was assigned from an init or copy method, or it was retained previously, store the count in a temporary variable, release the array and use the temporary variable to decide what to do:
NSInteger count = [array count];
[array release];
if (count == 0) {
array = [[NSMutableArray alloc] init];
} else {
array = [[userDefaults arrayForKey:#"MyFavorites"] mutableCopy];
}
In your case I'd always use without differentation
array = [[userDefaults arrayForKey:#"MyFavorites"] mutableCopy];
and set the default value in the user defaults to an empty array right away at program start before accessing the defaults (from Apple's example):
+ (void)initialize{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary
dictionaryWithObject:[NSArray array] forKey:#"MyFavorites"];
[defaults registerDefaults:appDefaults];
}
See Apple's doc on this.
Supposing you are talking about NSArray, if myArray has not been properly alloced+initialized (what you are trying to check) its reference will be nil, so you can do:
if(myArray) //or even if(myArray != nil) since myArray will be a pointer
{
//properly inizialized
}
else
{
//not properly inited
}
If it's been inited on the other hand, you can test its emptiness by checking the count property which returns the number of elements it contains
if([myArray > 0])
//there is at least one element
}
else
{
//no elements
}
you can use count function of NSArray. it will work on NSMutableArray too....
syntext will be,
int ct=[array count];
ct will have number of items in array.
if it us empty it will be Zero