ios break nested loop - objective-c

If I have a while loop with a for loop inside of the while loop, how can I break both loops?
I'm doing this because the extra 250ms I get from not completing these loops after I found what I want adds up to be valuable after a while.
pseudocode:
while(alwaysTrue) {
for(NSArray *arr in twoThousandItems) {
if(IFoundWhatIWasLookingFor) {
// assign some stuff here
// break everything, not just the for loop.
}
}
}

This is where goto is your friend. Yes, that goto.
while(alwaysTrue) {
for(NSArray *arr in twoThousandItems) {
if(IFoundWhatIWasLookingFor) {
// assign some stuff here
// break everything, not just the for loop.
goto BAIL;
}
}
}
BAIL:
NSLog(#"Freedom!");
The other option is to have short circuits in your loops.
while(alwaysTrue && !found) {
for(NSArray *arr in twoThousandItems) {
if(IFoundWhatIWasLookingFor) {
// assign some stuff here
// break everything, not just the for loop.
found = YES;
break;
}
}
}

This is one way. This is an applicable technique for other C variants, and other languages as well.
bool breakOuterLoop = false;
while(!breakOuterLoop)
{
for(NSArray *arr in twoThousandItems)
{
if(IFoundWhatIWasLookingFor)
{
// assign some stuff here
breakOuterLoop = true;
break;
}
}
}

Related

Recursive function with block in Objective C

I've got a function with completion block, and which in some cases calls itself recursively until has the expected result.
I'm getting errors in release, probably because it has different memory management in release.
Anyway I'm asking what should I do to make it work in release as in debug.
I've found some links about declaring a block variable weak, and another one strong, and then assign the block to both of them. However I'm in difficulty to understand well how to apply it to my code.
Here's the code:
-(void) getBitmapFromXObject: (OCPdfXObject *) xobj completion:(void(^)(NSData * data))completion{
__block BOOL hasAlreadyCompleted = false;
if (xobj.type == OCPdfXObjectType_Form) {
OCPdfXObjectForm * formxboj = (OCPdfXObjectForm *)xobj;
OCPdfDictionary * res = formxboj.resources.xObject;
if (res != nil) {
for (CBKeyValuePair * key in res) {
OCPdfXObject* childXObjc = [OCPdfXObject createFromObject:key.value];
if (!childXObjc) {
continue;
}
[self getBitmapFromXObject:childXObjc completion:^(NSData *data) {
if (data != nil) {
hasAlreadyCompleted = true;
}
}];
}
}
}
if (xobj.type == OCPdfXObjectType_Image) {
OCPdfImage* imagexobj = (OCPdfImage *)xobj;
if (imagexobj.colorSpace != OCPdfColorSpace_DeviceRGB) {
completion(nil);
hasAlreadyCompleted = true;
}
[self getBitmapFromImage:imagexobj withCompletion:^(NSData *data) {
NSData *uiImage = data;
completion(uiImage);
hasAlreadyCompleted = true;
}];
}
if (!hasAlreadyCompleted) {
completion(nil);
}
}

Is there a more efficient way to clean up my CCNodes?

Is there a more efficient way to clean up my CCNodes? I'm calling this function (and others like it for different game objects), on a timer.
- (void)pulseBullets:(NSMutableArray *)bs targets:(NSArray *)targets {
for (Bullet *b in bs) {
for (QuantumPilot *p in targets) {
if (p.active) {
[p processBullet:b];
if (!p.active) {
[self processKill:p];
}
}
}
}
NSMutableArray *bulletsToErase = [NSMutableArray array];
for (Bullet *b in bs) {
[b pulse];
if ([self bulletOutOfBounds:b]) {
[bulletsToErase addObject:b];
}
}
for (Bullet *b in bulletsToErase) {
[b removeFromParentAndCleanup:YES];
}
[bs removeObjectsInArray:bulletsToErase];
}
Ok, but i make no 'statement' on performance, you will have to measure that for yourself. If you iterate a mutable array in reverse order, it is safe to delete an object during the iteration, because the iterator will not be invalidated by the deletion. So you could get rid altogther of the bullets to erase array like so :
for (Bullet *b in [bs reverseObjectEnumerator]) { // *** do not change iteration order ***
for (QuantumPilot *p in targets) {
if (p.active) {
[p processBullet:b];
if (!p.active) {
[self processKill:p];
}
}
}
[b pulse];
if ([self bulletOutOfBounds:b]) {
[b removeFromParentAndCleanup:YES];
[bs removeObject:b];
}
}
this is simpler , but obfuscates the inherent risk of altering an array content during iteration. You make the call as to whether it is 'cleaner'. Also, maybe the 'cost' of reversing the iterator is higher that what you save, as i said you would have to measure it.

Efficient way of checking the content of every NSDictionary in NSArray

In my app I'me getting responses from the server and I have to check that I don't create duplicate objects in the NSArray which contains NSDictionaries. Now to check if the objects exists I do this:
for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){
NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];
if ([[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier]){
needToCheck = NO;
}
if (i == appDelegate.currentUser.userSiteDetailsArray.count - 1 && ![[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier] && needToCheck){
// It means it's the last object we've iterated through and needToCheck is still = YES;
//Doing stuff here
}
}
I set up a BOOL value because this iteration goes numerous times inside a method and I can't use return to stop it. I think there is a better way to perform this check and I would like to hear your suggestions about it.
BOOL needToCheck = YES;
for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){
NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];
if ([[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier]){
needToCheck = NO;
break;
}
}
if (needToCheck) {
//Doing stuff here
}
But, as others have said, you can maybe keep a "summary" in a separate NSSet that you check first, vs spinning through all the dictionaries.
NSDictionary *previousThing = nil;
for (NSDictionary *thing in appDelegate.currentUser.userSiteDetailsArray) {
if ([thing[#"webpropID"] isEqualToString:newWebPropertyIdentifier]) {
previousThing = thing;
break;
}
}
if (previousThing == nil) {
// no previous thing
} else {
// duplicate
}

How to break block loop in Objective - C?

I have these declarations in header file:
Note: I won't explain the whole code, I think it is easy to understand
typedef void (^loopCell)(id cell);
-(id)allCells:(loopCell)cell;
And allCells function implementation:
-(id)allCells:(loopCell)cell
{
for (AAFormSection *section in listSections)
{
for (id _cell in section.fields) {
cell(_cell);
}
}
return nil;
}
The usage of allCells function:
-(void)setFieldValue:(NSString *)value withID:(int)rowID
{
[self allCells:^(id cell) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
//return; Here I want to terminate loop
}
}
}];
}
My problem is, I can't terminate allCells loop in the middle (actually when I found object I need in the loop, I don't want iterate through other objects)
How can I stop allCells loop in the middle?
Look at the docs for NSArray enumerateObjectsUsingBlock:. They setup the block signature to take a BOOL pointer. Set the stop BOOL to YES to cause the iteration to stop.
typedef void (^loopCell)(id cell, BOOL *stop);
-(id)allCells:(loopCell)cell {
BOOL stop = NO;
for (AAFormSection *section in listSections) {
for (id _cell in section.fields) {
cell(_cell, &stop);
if (stop) {
break;
}
}
if (stop) {
break;
}
}
return nil;
}
-(void)setFieldValue:(NSString *)value withID:(int)rowID {
[self allCells:^(id cell, BOOL *stop) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
if (stop) {
*stop = YES;
}
}
}
}];
}
You can't break from setFieldValue, but you can from allCells.
It's up to the method you're using that calls the block — allCells in this case — to provide a mechanism for stopping the loop. Usually, it's a parameter to the block.
If allCells is yours and you don't mind modifying it, you modify the block signature to take a pointer to a BOOL, initialized to YES, and check if the block modified it to NO.
(Note: You can break from a for in loop.)

Problem with recursive objective-c void-method

thats my first question here and i hope someone can help me.
I´m new at the iPhone programming and want to try an easy app...
It´s an SudokuSolver which is working with an recursive Method. In JAVA this code is making no problems, but in Objective-C the code isn´t stopping when Sudoku is solved. It´s still trying to solve the Sudoku and stops later.
Anyone an idea?!
Here´s the code.
- (SudokuSolver *) initWithField: (int[9][9]) field {
self = [super init];
if(self) {
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
sudokuField[i][j] = field[i][j];
if (field[i][j]) {
sudokuFieldStatic[i][j] = 1;
} else {
sudokuFieldStatic[i][j] = 0;
}
}
}
}
return self;
}
- (void) solve {
[self solveFieldAtRow:0 andCol:0];
}
- (void) solveFieldAtRow: (int) row andCol: (int) col {
if (row > 8) {
return;
} else {
while (sudokuField[row][col] != 0) {
if (++col > 8) {
col = 0;
row++;
if (row > 8) {
return;
}
}
}
for (int num=1; num<10; num++) {
if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
sudokuField[row][col] = num;
[self showFieldInConsole:0];
if (col < 8) {
[self solveFieldAtRow:row andCol:col+1];
} else {
[self solveFieldAtRow:row+1 andCol:0];
}
}
}
sudokuField[row][col] = 0;
}
}
The code isn't stopping when the puzzle is solved because you don't check whether the puzzle is solved after the recursive call. So even if the recursive call found a solution, the code just continues on even after finding a solution until it has tried every possibility.
Since you say you have Java code that works, I suggest you compare the logic of the Java program versus this code. You'll probably find the Java code does include such a test.
Edit From your comment above, I see that you won't find such a test in your Java code, because there you are abusing exceptions to "return" from the recursion when a solution is found. The proper way is to have each recursive call return a true value if it found a solution and false if it didn't. And then each step should check if its child call succeeded, and itself return success if so. Something like this:
- (BOOL) solveFieldAtRow: (int) row andCol: (int) col {
if (row > 8) {
// reached the end, so it must have succeeded
return YES;
} else {
while (sudokuField[row][col] != 0) {
if (++col > 8) {
col = 0;
row++;
if (row > 8) {
// reached the end, so it must have succeeded
return YES;
}
}
}
for (int num=1; num<10; num++) {
if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
sudokuField[row][col] = num;
[self showFieldInConsole:0];
BOOL result;
if (col < 8) {
result = [self solveFieldAtRow:row andCol:col+1];
} else {
result = [self solveFieldAtRow:row+1 andCol:0];
}
if (result) {
// Our child call succeeded, so we pass that back up
// the stack.
return YES;
}
}
}
sudokuField[row][col] = 0;
// If we get here, we could not find a solution. Return failure
// back up the stack.
return NO;
}
}