Error: index 1 beyond bounds for empty array - objective-c

I have created an NSMutableArray to store some character there. When I'am adding some character there it gives me an error. Here my code:
#property(strong,nonatomic) NSMutableArray *actions; < ViewController.h
#synthesize actions; < ViewController.m
actions = [[NSMutableArray alloc]init];
switch ([sender tag]) {
case 0:
currentLabel = water;
[actions insertObject:#"0" atIndex:i];
i++;
break;
case 1:
currentLabel = coke;
[actions insertObject:#"1" atIndex:i];
i++;
break;
case 2:
currentLabel = fanta;
[actions insertObject:#"2" atIndex:i];
i++;
break;
}

Use [actions addObject:#"X"] instead. If the array does not have elements, you can't insert object at index 1.

Related

Don't work subtraction/multiplication/division but work addition

Hello!
In my calculator program don't work subtraction/multiplication/division methods but work addition method.
Addition method:
-(IBAction) clickPlus
{
[self processOp: '+'];
}
Subtraction method:
-(IBAction) clickMinus
{
[self processOp: '-'];
}
Process method:
-(void) processOp: (char) theOp
{
NSString *opStr;
op = theOp;
switch (theOp) {
case '+':
opStr = #" + ";
break;
case '-':
opStr = #" – ";
break;
case '*':
opStr = #" * ";
break;
case '/':
opStr = #" ÷ ";
break;
}
[self storeFracPart];
firstOperand = NO;
isNumerator = YES;
[displayString appendString: opStr];
display.text = displayString;
}
In that method 'op' variable is used: "clickEquals"
-(IBAction) clickEquals
{
if ( firstOperand == NO )
{
[self storeFracPart];
[myCalculator performOperation: op];
[displayString appendString: #" = "];
[displayString appendString: [myCalculator.accumulator
convertToString]];
display.text = displayString;
currentNumber = 0;
isNumerator = YES;
firstOperand = YES;
[displayString setString: #""];
}
}
Why do you think that 'op' collect garbage?
If you need more code just let me know.
What is op in clickEquals? Is it supposed to be a class ivar? If so processOp is wrong as it's using a local variable called op and is therefore never assigning the ivar.
You should learn to debug this kind of problems yourself. It's not too hard. If you step through the code execution line by line in the debugger and watch what changes when you should be able to find this sort of problems.

How to paste [array count] to case:

I have switch. One of the cases must be a count of array:
int count = [array count];
switch (someValue) {
case 0:
[self foo];
break;
case count:
[self bar];
break;
default:
break;
}
But compiler tolds:
Expression is not an integer constant expression
How to make const int from [array count]?
As the error suggests, the cases must all be constants. You'll need an if statement to check the dynamic case:
int count = [array count];
switch (someValue) {
case 0:
[self foo];
break;
default:
if (someValue == count)
[self bar];
break;
}
if(some value == 0) {
[self foo];
} else if (someValue == [array count]) {
[self bar]
}

NSMutableArray removeAllObjects issue

I'm facing a problem with NSMutableArray that give me a Exc_Bad_Access without a reason.
I have a UITableView that contain around 700 records, i wanna to activate a filter process to it, i'm using the following method to filter the content of the UITableView:
- (void) filterTableContentWith:(int)_minValue andWith:(int)_maxValue {
[tableContent removeAllObjects];
tableContent = [[NSMutableArray alloc] initWithArray:originalTableContent copyItems:YES];
if (_minValue == 0 && _maxValue == 0) {
NSLog(#"This is mean that no filter is activate here");
} else {
for (int x = ([tableContent count] - 1); x >= 0; x--) {
if ([[[tableContent objectAtIndex:x] objectForKey:#"price"] intValue] < _minValue && [[[tableContent objectAtIndex:x] objectForKey:#"price"] intValue] > _maxValue) {
[tableContent removeObjectAtIndex:x];
}
}
}
NSLog(#"tableContent count = %#",[tableContent count]);
[self.tableView reloadData];
}
When i'm calling this method, it gives me Exc_Bad_Access on NSLog(#"tableContent count ...
I think that [tableContent removeAllObjects]; is releasing the array, but it's unreasonable.
Any help will be appreciated.
count returns an int, so change your NSLog to:
NSLog(#"tableContent count = %d",[tableContent count]);
and you'll be fine.
In addition to change your NSLog for count with %d, I think the following codes are better than removing contents within your loop:
...
} else {
NSPredicate* predicate = [NSPredicate predicateWithFormat:
#"price < %d AND price > %d", _minValue, _maxValue];
NSArray* array = [tableContent filteredArrayUsingPredicate:predicate];
tableContent = array;
}
...

How to move an item on NSMutableArray?

I want to move a string item to the top of the list.
NSMutableArray animal = "cat", "lion", "dog", "tiger";
How do I move dog to top of the list?
You would remove the item and insert it at the correct space:
id tmp=[[animals objectAtIndex:2] retain];
[animals removeObjectAtIndex:2];
[animals insertObject:tmp atIndex:0];
[tmp release];
You have to retain the object or when you tell the array to remove it, it will release the object.
If you don't know the index you could do something like this:
NSMutableArray* animals = [NSMutableArray arrayWithObjects:#"cat", #"lion", #"dog", #"tiger",nil];
for (NSString* obj in [[animals copy] autorelease]) {
if ([obj isEqualToString:#"dog"]) {
NSString* tmp = [obj retain];
[animals removeObject:tmp];
[animals insertObject:tmp atIndex:0];
break;
}
}
This method will go over all your list and search for "dog" and if it finds it will remove it from the original list and move it to index 0.
I would like to point out an inefficiency in your method. By removing/inserting an object from a NSMutableArray you potentially affect every row after the deletion/insertion. I say ‘potentially’ because it’s not clear what internal method Apple uses to maintain their mutable arrays. However, assuming it’s a simple c-array, then every row after that deletion/insertion index will be need to be moved down/up. In a very large array, this could be inefficient if the items moved are at the beginning. However, replacing items in an array are not inefficient at all. Thus the following is a category on NSMutableArray (note this code is under ARC, so no memory management):
- (void) moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex{
if (fromIndex == toIndex) return;
if (fromIndex >= self.count) return; //there is no object to move, return
if (toIndex >= self.count) toIndex = self.count - 1; //toIndex too large, assume a move to end
id movingObject = [self objectAtIndex:fromIndex];
if (fromIndex < toIndex){
for (int i = fromIndex; i <= toIndex; i++){
[self replaceObjectAtIndex:i withObject:(i == toIndex) ? movingObject : [self objectAtIndex:i + 1]];
}
} else {
id cObject;
id prevObject;
for (int i = toIndex; i <= fromIndex; i++){
cObject = [self objectAtIndex:i];
[self replaceObjectAtIndex:i withObject:(i == toIndex) ? movingObject : prevObject];
prevObject = cObject;
}
}
}
Also, a small bonus to further increase functionality, if you're performing operations on the items moved (like updating a db or something), the following code has been very useful to me:
- (void) moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex withBlock:(void (^)(id, NSUInteger))block{
if (fromIndex == toIndex) return;
if (fromIndex >= self.count) return; //there is no object to move, return
if (toIndex >= self.count) toIndex = self.count - 1; //toIndex too large, assume a move to end
id movingObject = [self objectAtIndex:fromIndex];
id replacementObject;
if (fromIndex < toIndex){
for (int i = fromIndex; i <= toIndex; i++){
replacementObject = (i == toIndex) ? movingObject : [self objectAtIndex:i + 1];
[self replaceObjectAtIndex:i withObject:replacementObject];
if (block) block(replacementObject, i);
}
} else {
id cObject;
id prevObject;
for (int i = toIndex; i <= fromIndex; i++){
cObject = [self objectAtIndex:i];
replacementObject = (i == toIndex) ? movingObject : prevObject;
[self replaceObjectAtIndex:i withObject:replacementObject];
prevObject = cObject;
if (block) block(replacementObject, i);
}
}
}
You can remove an existing element, e.g dog and then reinsert it at the beginning of the array.
NSMutableArray *animals = [NSMutableArray arrayWithObjects:#"cat", #"lion", #"dog", #"tiger",nil];
NSString *dog = #"dog";
// Check to see if dog is in animals
if ( [animals containsObject:dog] ) {
// Remove dog from animals and reinsert
// at the beginning of animals
[animals removeObject:dog];
[animals insertObject:dog atIndex:0];
}

Problem with the duplicate values picking from Address book in Iphone sdk

Here I had a problem that I am adding contact from the address book and checking it whether it is already in the favourites list or not.If not I am adding the contact to favourite list.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
ContactDTO* dtoObject = [[ContactDTO alloc] init];
ABRecordID personId = ABRecordGetRecordID(person);
NSString* personIdStr = [NSString stringWithFormat:#"%d", personId];
dtoObject.contactId = personIdStr;
NSString *lastNameString, *firstNameString;
firstNameString = [self getValueForProperty:kABPersonFirstNameProperty forContact:personIdStr];
lastNameString = [self getValueForProperty:kABPersonLastNameProperty forContact:personIdStr];
dtoObject.firstName = firstNameString;
dtoObject.lastName = lastNameString;
printf("\n *****************firstNameString %s",[firstNameString UTF8String]);
//ABMultiValueRef emailMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonEmailProperty) autorelease];
ABMultiValueRef phoneMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonPhoneProperty) autorelease];
if (ABMultiValueGetCount(phoneMultiValue) > 0)
{
ABMultiValueRef phoneMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonPhoneProperty) autorelease];
NSString* curentTypeLabel =[(NSString *)ABMultiValueCopyLabelAtIndex(phoneMultiValue,identifier) autorelease];
curentTypeLabel = [curentTypeLabel stringByReplacingOccurrencesOfString:#"_$!<" withString:#""];
curentTypeLabel = [curentTypeLabel stringByReplacingOccurrencesOfString:#">!$_" withString:#""];
dtoObject.numberType = curentTypeLabel;
NSString* currentPhone = [(NSString *)ABMultiValueCopyValueAtIndex(phoneMultiValue,identifier) autorelease];
dtoObject.mobNumber = currentPhone;
FavoritesAppDelegate* appDelegate = (FavoritesAppDelegate*) [[UIApplication sharedApplication] delegate];
if ([favoritesArray count] > 0)
{
for (int i=0; i< [favoritesArray count]; i++)
{
ContactDTO* dtoObject1 = [favoritesArray objectAtIndex:i];
printf("\n dtoObject1.contactId value = %s, Main value = %s",[dtoObject.firstName UTF8String],[dtoObject1.firstName UTF8String]);
printf("\n dtoObject1.mobNumber value = %s, Main mobNumber value = %s",[dtoObject1.mobNumber UTF8String],[dtoObject.mobNumber UTF8String]);
if ([dtoObject.firstName isEqualToString:dtoObject1.firstName])
{
printf("\n inside if....");
}
else
{
[appDelegate addContactToFavorites:dtoObject];
break;
printf("\n inside else....");
}
}
}
else
{
[appDelegate addContactToFavorites:dtoObject];
}
[self dismissModalViewControllerAnimated:YES];
}
/*else if(ABMultiValueGetCount(emailMultiValue) > 0)
{
NSString* currentEmail =(NSString *)ABMultiValueCopyValueAtIndex(emailMultiValue,identifier);
printf("\n *************currentEmail** %s",[currentEmail UTF8String]);
[self emailBtnAction:currentEmail];
}*/
[dtoObject release];
return NO;
}
For that the code I written was shown as above.
Eventhough I am getting the duplicate values the condition is failed and duplicate values are added.
Can anyone give suggestions to get rid of this?
Anyone's help will be much appreciated.
Thanks to all,
Monish.
You are adding to favorites array if the new contact doesn't match ONE of the existing items in the favorites array. But the new contact could be in the favorites array further along in the array. You need to check if the new contact doesn't match ALL of the existing favorites.
Also, shouldn't the match condition be more than just checking first names?
Something like this:
BOOL contactAlreadyExists = NO;
for (int i=0; i< [favoritesArray count]; i++)
{
ContactDTO* dtoObject1 = [favoritesArray objectAtIndex:i];
if ([dtoObject.firstName isEqualToString:dtoObject1.firstName])
{
contactAlreadyExists = YES;
break;
}
}
if (!contactAlreadyExists)
{
[appDelegate addContactToFavorites:dtoObject];
}