I cant find this any where, I may be searching the wrong terms or words but I just need to know how to check if an array is a certain length:
if ([scores objectAtIndex:3]){
//code
}
This comes up with an error and crashes if the array isnt this long yet, but surly this should just check if there is an index, and if not move on??
How to I check this without the app crashing??
count method of NSArray returns the number of objects in the array. If [myArray count] returns n then valid indexes are 0 to n - 1. There is no automatic move on if the index is not valid. Before trying to access an index you need to make sure that the index is valid.
if ([scores count] >= 4) {
id obj = [scores objectAtIndex:3];
}
Related
I have an NSMutabaleArray and I want to check it whether it would be in sorted mode or not after insertion of any element. So what would be the fastest technique to do that.
You need one loop to traverse and check if array[i+1] is greater than array[i]th element, assuming array is sorted in ascending order. If this fails then its not sorted. This would be O(n).
By using Cocoa- library:
Typical answer would be to sort it again, if it is already sorted then that would be quick, not much of time and space complexity.Then compare the two arrays, if both matches then your array was sorted.
EDIT:
The above is an example for integers. If objects (Cocoa objects) are there, then you need to decide what kind of values you want to compare, if string then need to check NSOrderedDescending, NSOrderedSame , for NSDate isGreater etc.
I have done like this (as I have a String array)
for (int i = 1; i < array.count; i++)
if ([array[i - 1] compare:array[i]] != NSOrderedAscending)
return NO;
return YES;
So this code returns me a BOOL value when I call the function.
I am developing an iPad application and for this application I have one function as below :-
-(void)testcurrentest:(NSMutableDictionary *)keydictionary{
NSArray *allKeys = [keydictionary allKeys];
if ([allKeys count] > 0) {
for(int i = 0;i< allKeys.count;i++){
[_currenies removeAllObjects];
NSString *product = [NSString stringWithFormat:#"%#", [keydictionary objectForKey:allKeys[i]]];
int kl = [productPriceSeasonCode intValue];
for(int i =0;i<kl;i++){
[_currenies addObject:#"0"];
}
NSLog(#"................%#",_currenies);
[_currencydictionary1 setObject:_currenies forKey:allKeys[i]];
NSLog(#"full dictionary...%#",_currencydictionary1);
}
}
}
Here, NSLog print the currencies array based on the kl integer values but when I'm trying to set the NSMutableDictionary the currencies but mutable array always show the latest array values.
You are using the same array for all values, they should be unique objects if you don't want change of one value to affect the other values. Initialise _currenies on every loop step or use its deep copy when preparing a new object.
A bit of code:
[_currenies removeAllObjects]; // < The same array you've added to dict on previous loop steps
Creating a new array at each loop step would create a unique object for all key-value pair:
_currenies = [NSMutableArray array]; // < Note it is not retained, apply memory management depending on your project configuration
Your code is a garbled mess. As others have pointed out, you are using the same loop index, i, in 2 nested loops, making it very hard to tell your intent. Don't do that, ever. It's horrible programming style.
You are also creating a string "product" that you never use, and fetching the same integer value of productPriceSeasonCode on every pass through the outer loop. I suspect you meant to fetch a value that varies with each entry in your keydictionary.
Then, you have an array, _currenies, which you empty on each pass through your outer loop. You then add a number of "0" strings to it, set a key/value pair in your _currencydictionary1 dictionary to the contents of that array, and then repeat. Since you re-use your _currenies array each time, every key/value pair you create in your _currencydictionary1 dictionary points to the exact same array, which you keep changing. At the last iteration of your outer loop, all the entries in your _currencydictionary1 will point to your _currenies array, which will contain the last set of contents you put there.
Create a new array for each pass through your outer array, and add that newly created array to your _currencydictionary1. You want a unique array in each key/value pair of your _currencydictionary1.
In short, NSMutableDictionary is working just fine. It's your code that isn't working properly.
Not an answer but comments don't have formatting.
The question should provide more information on the input and desired output.
First simplify your code and it should be easier to find the error:
-(void)testcurrentest:(NSMutableDictionary *)keydictionary{
NSArray *allKeys = [keydictionary allKeys];
for(NSString *key in allKeys) {
[_currenies removeAllObjects];
int kl = [productPriceSeasonCode intValue];
for(int i =0; i<kl; i++){
[_currenies addObject:#"0"];
}
NSLog(#"................%#",_currenies);
_currencydictionary1[key] = _currenies;
NSLog(#"full dictionary...%#",_currencydictionary1);
}
}
Note: product was never used.
I have a MutableArray on this view called array and the object in question is detailItem, which has a property of rank (int). On this view, there's a text field displaying the rank and I want to be able to move the detailItem up and down the MutableArray by changing the rank.
So, for example let's say the detailItem has a rank of 3, which is index value of 2. If I change this in the text field to 3, I want the array to adjust and move it down one place. However, as I type in the value of rankField (the text field), it crashes the app since it automatically updates the value before I'm done editing. So, if I click on the text field and write 23 (planing on deleting the 2) or just press delete (now the value is nil) the app crashes with an uncaught exception.
Here's the code:
- (IBAction)rankFIeldTextChanged:(id)sender {
QueueMember *member = self.detailItem;
[self.array removeObjectAtIndex:self.detailItem.rank];
if (0<= [self.rankField.text intValue]<= self.array.count) {
[self.array insertObject:member atIndex:[self.rankField.text intValue]-1];
}
}
The if condition of making the text value in-between the array size and 0 seems to have no effect.
btw this is all in the detailsViewController which is connected to the main view controller via push segue. does it make more sense(or more better coding) to just set the new rank value in details and actually make the array changes in the mainviewcontroller.m?
The problem is that you are trying to do two boolean statements at once (which doesn't work). Change your if statement to something like:
if (0< [self.rankField.text intValue] && [self.rankField.text intValue] < self.array.count) {
//Insert your object here
}
else
{
//Add object here
}
Your current setup check to see if 0<= [self.rankField.text intValue], which will return true for all values greater than or equal to 0. Then it checks the result of that (YES:1, NO:0) if it's less than or equal to your array count. That will always return true if your array has anything in it. So basically your check will always return true.
Since it always returns true I could check for array object number 1000, your if statement says go for it, then I check and the array says "No way in heck!" and crashes your app.
EDIT: Updated my code snippet to take into account your array insertion line.
I'd just do this
- (IBAction)rankFIeldTextChanged:(id)sender {
QueueMember *member = self.detailItem;
[self.array removeObjectAtIndex:self.detailItem.rank];
if ((0<= [self.rankField.text intValue])&&([self.rankField.text intValue]<= self.array.count)) {
if (self.array.count >([self.rankField.text intValue]-1)){
[self.array insertObject:member atIndex:[self.rankField.text intValue]-1];
}
}
}
you are probably trying to insert at an index greater than the count of the array.
I am developing a game for iPhone in which I have 2 arrays.
One with the objects "living" in the game, and when these objects "die" they are placed in another array to be removed from the first one in the end of the first loop.
This is necessary because if the object dies in the loop and it is removed immediately from the first array, the index is lost and sometimes gives an invalid address access.
Then I have an NSMutableArray that contains objects to be removed from the living objects array.
In the array with objects to remove, I am constantly adding and removing items. Sometimes when I use objectAtIndex with the array with items to remove, it is retuning me other object.
For example in the first moment _enemiesToRemove has 2 objects:
([0]-> 0x0a8b5120, [1]->0x18f3a090)
for(int i = [_enemiesToRemove count] - 1; i >= 0 ; i--){
fish = [_enemiesToRemove objectAtIndex:i];
[self removeEnemy:fish];
}
and then
int i = [_enemiesToRemove count] - 1
gives i=1 but when it is doing
[_enemiesToRemove objectAtIndex:i]
it is returning me other object with address 0xbfffcd58 and it should be [1]->0x18f3a090
What is happening here, somebody knows? It is not happening always. It happens randomly.
Can't figure out whats causing the crash here. Im enumerating over a NSMutableArray and placing the indexes of certain objects into a mutable index set, then attempting to remove the corresponding objects from the array. here is my code
NSMutableIndexSet *itemsToRemove;
UIBarButtonItem *item;
NSUInteger index;
for (item in self.rightView.toolbarItems)
{
if (item.tag == MLPAD_RIGHT_VC_BACK_TO_CENTRAL_ITEM_TAG){
[itemsToRemove addIndex:index];
index ++;
}
}
[self.rightView.toolbarItems removeObjectsAtIndexes:itemsToRemove];
the last line is crashing and giving me an EX_BAD_ACCESS.
any ideas why?
thanks
You're not allocating/initializing itemsToRemove - if you're using ARC, it's initialized to nil, if not, it potentially contains garbage - neither one is acceptable if you want it to be passed as an argument later...
Neither do you initialize index to zero...
(Why am I suspecting that you're coming from a managed language?...)
Unrelated to the crash, but it's still a semantic error: you have to increment index even if the conition is not met:
for (item in self.rightView.toolbarItems)
{
if (item.tag == MLPAD_RIGHT_VC_BACK_TO_CENTRAL_ITEM_TAG) {
[itemsToRemove addIndex:index];
}
index ++;
}
Your primary problem is that itemsToRemove never gets initialized. You can't add an object to an NSMutableIndexSet that isn't really an NSMutableIndexSet - try setting itemsToRemove = [[NSMutableIndexSet alloc] init] or similar.
I also think where you have the statement index++ might be throwing some things off - if you only increment the index when you find an item you want to remove, you're effectively removing the first itemsToRemove.count items, instead of the actual items you want to get rid of. Think about incrementing the index unconditionally instead.
You have several issues. Not allocating itemsToRemove, not initilializing index (builtin stack variables are not auto-initialized) and not incrementing index on every loop iteration.
NSMutableIndexSet *itemsToRemove = [NSMutableIndexSet new];
NSUInteger index = 0;
for (UIBarButtonItem *item in self.rightView.toolbarItems)
{
if (item.tag == MLPAD_RIGHT_VC_BACK_TO_CENTRAL_ITEM_TAG){
[itemsToRemove addIndex:index];
}
++index;
}
[self.rightView.toolbarItems removeObjectsAtIndexes:itemsToRemove];
The index type of error can be minimized by using the block enumeration method, which passes in the current index.