Monday, June 17, 2013

NSIndexSet indexPassingTest example in Objective C (iOS).


NSIndexSet indexPassingTest

Returns the index of the first object that passes the predicate Block test.

- (NSUInteger)indexPassingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate

Parameters of [NSIndexSet indexPassingTest]
predicate
The Block to apply to elements in the set.
The Block takes two arguments:
idx
The index of the object.
stop
A reference to a Boolean value. The block can set the value to YES to stop further processing of the set. The stop argument is an out-only argument. You should only ever set this Boolean to YES within the Block.
The Block returns a Boolean value that indicates whether obj passed the test.

Return Value of [NSIndexSet indexPassingTest]
The index of the first object that passes the predicate test.

NSIndexSet indexPassingTest example.
- (NSUInteger)indexForImageGivenIndexSet:(NSIndexSet*)indexSet             // Set of indexes you want to select from
                         prizeImageIndex:(NSUInteger)prizeIndex      // The prize index
                        probabilityScale:(CGFloat)probabilityScale   // The scale for the prize (8.0 for 8x less than the others)
{
    // If invalid, return what was given
    if (![indexSet containsIndex:prizeIndex]) {
        return prizeIndex;
    }

    // Calculate our probabilities
    // For a set of 4, with a scale of 8 on the prize, our probabilities would be
    // 0.04 (prize), 0.32, 0.32, 0.32
    double prizeProbability = (1.0 / indexSet.count) * (1.0 / probabilityScale);

    double val = (double)arc4random() / RAND_MAX;

    if (val < prizeProbability) {
        return prizeIndex;
    }
    else {
        // Select from the others in range equally
        NSMutableIndexSet* newSet = [[NSMutableIndexSet alloc] initWithIndexSet:indexSet];
        [newSet removeIndex:prizeIndex];

        NSInteger selectedPosition = arc4random() % newSet.count;
        __block NSInteger count = 0;
        return [newSet indexPassingTest:^BOOL(NSUInteger idx, BOOL *stop) {
            if (count == selectedPosition) {
                *stop = YES;
                return YES;
            }
            else {
                count++;
                return NO;
            }
        }];
    }
}

End of NSIndexSet indexPassingTest example article.