0

I have an NSArray with objects inside (CLLocation). I can have 50, 100, 300 or more objects inside. In fact, this array is used while the user walking and can follow a direction. But the user can start at the middle of my NSArray, you know what I mean ?

Well, I Have to loop all the time my array to know where my user is compare to the locations in my array.

My question is: Is it possible to use a thing like in Java with a "cursor" in a list, and simply call "Next object" to travel in my array instead of loop ?

Because I need that the user walk on all location of my array. Example:

  1. Count of my array: 100
  2. User start at location at index 34 (the nearest location found)
  3. The user must do 35, 36, 37... 100 AND 0,1,2,3 ... until 33.

Hope it's clear, I really don't know how to do this without using for loop...

Thank you for help and suggestions!

Regards, Lapinou.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Lapinou
  • 1,467
  • 2
  • 20
  • 39

5 Answers5

2

Is looks like you are want to use NSEnumerator

NSEnumerator Class Reference

NSArray *anArray = // ... ;
NSEnumerator *enumerator = [anArray objectEnumerator];
id object;

while ((object = [enumerator nextObject])) {
    // do something with object...
}
sage444
  • 5,661
  • 4
  • 33
  • 60
  • The problem with an enumerator is that it starts at the beginning and ends at the end. The OP wants to start at index `m` and end at `m-1`. – Caleb Mar 10 '14 at 16:11
  • 1
    @Caleb is not hard to make subarray with `subarrayWithRange:` and use enumerator with result array – sage444 Mar 10 '14 at 16:14
  • No, it's not hard, and it's also not hard to rearrange the array so that the items `0..m-1` are moved to the end and `m` becomes the beginning. But you haven't mentioned either of those possibilities in this answer. And how helpful is an enumerator, really, if you have to be concerned with enumerating two subarrays? – Caleb Mar 10 '14 at 16:19
  • Nevermind the previous; I didn't fully understand the wraparound. That, however, can be easily implemented with exactly what @caleb says: Create a new array that wraps the way you want (join the two subarrays). Again, this is the power of immutable arrays. – Rob Napier Mar 10 '14 at 16:23
2

Here's one way:

NSArray * arr = ... yourArray

int index = [arr indexOfObject:currentLocation];
index ++;
if (index == arr.count) index = 0;
id nextLocation = arr[index];

Another might be to create a global counter variable that stores the current position. If these needs to last after the user closes the app, you could write it to user defaults

Logan
  • 52,262
  • 20
  • 99
  • 128
2

try this:

@interface ArrayEnumerator : NSEnumerator
{
    NSArray* array;
    NSInteger index;
    NSInteger startIndex;
    BOOL over;
}

- (id)initWithArray:(NSArray*)anArray
            atIndex:(NSInteger)anIndex;
@end
@implementation ArrayEnumerator
- (id)initWithArray:(NSArray*)anArray
            atIndex:(NSInteger)anIndex
{
    if (self=[super init]) {
        array = anArray;
        index = anIndex;
        startIndex = anIndex;
        over = NO;
    }

    return self;
}

- (id)nextObject
{
    if (index == [array count]) {
        index = 0;
        over = YES;
    }

    if (over && index == startIndex)
        return nil;

    return array[index++];
}

- (NSArray*)allObjects
{
    return array;
}
@end

@implementation ViewController

- (void)viewDidLoad
{

    NSArray* array = @[@0,@1,@2,@3,@4,@5,@6,@7,@8,@9];
    id element;

    ArrayEnumerator* enumerator = [[ArrayEnumerator alloc] initWithArray:array atIndex:4];
    while (element = [enumerator nextObject])
        NSLog(@"%@", element);

}

@end
Michał Banasiak
  • 950
  • 6
  • 13
  • OK, this works but it's very odd. The value of index will always be wrong. i.e. if the index of the current place in the array is 5 then the value of index will be 6. etc... – Fogmeister Mar 10 '14 at 16:12
  • This is basically a reimplementation of `NSEnumerator`, but slower and less flexible. – Rob Napier Mar 10 '14 at 16:12
  • @RobNapier can you start an NSEnumerator at an arbitrary point in the array? – Fogmeister Mar 10 '14 at 16:14
  • You cam also iterate through it using for (id object in enumerator) - it is no odd then – Michał Banasiak Mar 10 '14 at 16:15
  • 1
    @Fogmeister, yes, by creating the enumerator on a `subarrayWithRange:`. That's the power of immutable arrays; these are cheap. – Rob Napier Mar 10 '14 at 16:17
  • I was missing the wrap-around comment. I still think it's better to create a new array out of two subarrays (so that you start at the front), but now I understand better the problem that's being solved. – Rob Napier Mar 10 '14 at 16:24
  • That said; this is starting to grow on me… – Rob Napier Mar 10 '14 at 16:27
1

You can access array elements by index:

CLLocation * myLocation = myArray[34];

(or)

int i = 34;

CLLocation * myLocation = myArray[i];
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
Owen Hartnett
  • 5,925
  • 2
  • 19
  • 35
  • Isn't the ability to access elements by index the defining quality of an array? I don't think this point is lost on the OP. Perhaps there's more that you meant to say? – Caleb Mar 10 '14 at 16:15
1

What is wrong with a for loop? An iterator is typically used on lists, because you can't access elements in a list by index. However you are working with an array, so you don't need an iterator, but rather some clever way of accessing the array in the desired order. Maybe this code can provide you with some ideas. This will run from 34 to 100, then start with 0 and go up to 33.

for (int i = 34; i < 134; i++)
{
    int ix = i % 100;
    id whatever = arr[ix];
}
Atomix
  • 13,427
  • 9
  • 38
  • 46