问题
I'm currently in the development process of an application which needs to be able to grab two objects from an NSArray and then store it in another object.
I've currently got this fast enumeration loop going on,
NSUInteger count = 0;
NSUInteger i = count + 1;
for (id item in [section items]) {
item1 = [section.items objectAtIndex:count];
item2 = [section.items objectAtIndex:i];
count++;
}
Now, what I want to do is grab the object in the first position and store in item1, and then the second position will be stored in item2. The next time it goes through the loop, I want it to store the object in the third position in item1, and then the fourth position in item2 and so forth.
Has anyone ever tried to and achieved this?
EDIT
This is what I currently have, I thought it best that I explain what I'm doing a little deeper so here goes. Here's the code that I have first, and I'll explain afterwards.
MPSection *section = [self.sections objectAtIndex:indexPath.section];
NSArray *itemArray = [section items];
for (NSUInteger i = 0; (i + 1) < [section.items count]; i += 2) {
item1 = [itemArray objectAtIndex:i];
item2 = [itemArray objectAtIndex:i+1];
}
As you can see, this is running within (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
as I want to grab what would normally be displayed in the first and second row of a UITableView and put it into one cell which is divided into two subviews.
What I'm finding is, by using the above code, it definitely isn't doing that. Is there a simpler way that I can do this and if so, can someone please inform me about this. I really need to approach this with memory preservation and time consumption kept to a minimal as well.
回答1:
It would be good if you can preprocess this but if you can't do that for some reason then this is what you should do,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
MPSection * section = [self.sections objectAtIndex:section];
NSInteger count = [section.items count];
return ((count % 2 == 0)? count / 2 : (count / 2 + 1) );
}
And in tableView:cellForRowAtIndexPath:
method,
/* */
MPSection *section = [self.sections objectAtIndex:indexPath.section];
id item1 = [section.items objectAtIndex:(indexPath.row * 2)];
id item2 = ((indexPath.row * 2 + 1) < [section.items count])? [section.items objectAtIndex:(indexPath.row * 2 + 1)] : nil;
/* Use item1 & item2 to fill both the subviews */
Original Answer
Use the NSEnumerator
instance for this purpose
NSEnumerator *enumerator = [section.items objectEnumerator];
id item1, item2;
while ( (item1 = [enumerator nextObject]) && (item2 = [enumerator nextObject]) ) {
// Use item1 & item2
}
As such I think you must be getting index out of bounds error for the snippet you mentioned.
Overkill
There seems to be some question about performance so I tested the three suggested methods and timed them in a loop where I log them.
Enumerator, Fast Enumeration with Object Search, For Loop (50000 elements): 19.253626, 88.269961, 18.767572
Enumerator, Fast Enumeration with Object Search, For Loop (25000 elements): 9.164311, 25.105664, 8.777443
Enumerator, Fast Enumeration with Object Search, For Loop (10000 elements): 3.428265, 6.035876, 3.144609
Enumerator, Fast Enumeration with Object Search, For Loop (5000 elements): 2.010748, 2.548562, 1.980477
Enumerator, Fast Enumeration with Object Search, For Loop (1000 elements): 0.508310, 0.389402, 0.338096
Enumerator, Fast Enumeration with Object Search, For Loop (500 elements): 0.156880, 0.163541, 0.150585
Enumerator, Fast Enumeration with Object Search, For Loop (100 elements): 0.076625, 0.034531, 0.036576
Enumerator, Fast Enumeration with Object Search, For Loop (50 elements): 0.026115, 0.022686, 0.041745
From the looks of it, @Caleb's for
loop approach might be the best approach to take.
回答2:
If you're dead set on using fast enumeration here, you could set a flag that lets you skip each even iteration of the loop:
BOOL doThisOne = YES;
NSArray itemArray = [section itemArray];
for (id item in items) {
if (doThisOne) {
item1 = item;
item2 = [itemArray objectAtIndex:1+[itemArray indexOfObject:item]];
}
doThisOne = !doThisOne;
}
Note: The code above throws a range exception if the number of items in the array is odd. Some of the other answers avoid this, but I think the best answer is simply not to use fast enumeration here.
It'd be so much simpler to use an enumerator, or just use a regular old for loop:
NSEnumerator *e = [[section items] objectEnumerator];
while (item = [e nextObject]) {
item1 = item;
item2 = [e nextObject];
}
or:
NSArray *itemArray = [section items];
for (int i = 0; (i + 1) < [items count]; i += 2) {
item1 = [items objectAtIndex:i];
item2 = [items objectAtIndex:i+1];
}
回答3:
for(id item in array){
if([array indexOfObject:item] % 2 != 0){
item1 = item;
}else{
item2 = item;
}
}
回答4:
int numItems = [section.items count];
for(int i = 0; i < count; i++) {
item1 = [section.items objectAtIndex: i];
item2 = ((i + 1) < count)) ? [section.items objectAtIndex: (i + 1)] : nil;
}
来源:https://stackoverflow.com/questions/6482082/nsarray-loop-to-grab-objects