assume that i have two sequential methods, methodA and methodB (methodB is called at the end of methodA) and i need to finish completely with the process of methodA before starting methodB :
-(void)methodA {
//do some very heavy computation here
[self methodB];
}
-(void)methodB {
//this method performs some animation
}
methodA requires alot of processing power and takes time to finish while methodB has animations. The animations are starting laggy at first and im guessing this has to do with the overhead of method A. So how can i make the second method start only after the first has finished completely?
this is the actual code:
the code is very messy and unorganized. there is alot of code that has been commented out so please ingore that. I test some things sometimes and then comment them out incase i need them later.
here is what is happening: it starts with (void)checkMoves method. This method calls either one of two similar methods which are
-(void)getMovesForJourney:(int)journey withRolls:(NSArray *)rolls or
-(void) getEntryMovesForJourney:(int)journey withRolls:(NSArray *)rolls
these methods are wrappers for a long recursive process (which is most probably where the multithreading is happening).
at the end of (void)checkMoves another method -(void)analyseMoves is called. This is also a heavy process.
and finally, at the end of -(void)analyseMoves the animation method -(void)move: is called. this last method is starting with a lag.
finally at the end of -(void)move: the process will start again until no more ‘moves’ are available.
the methods below are not in order so please refer to the description above to know whats going on.
-(void) checkMoves {
GameScene *game = [GameScene sharedGameScene];
CCLOG(@"start");
for (Stone *stone in stones) {
if (!stone.onBoard) {
if ([game EntryAvailable]) {
[self getEntryMovesForJourney:stone.journey withRolls:[game rollsAsIntegers]];
}
}
else {
[self getMovesForJourney:stone.journey withRolls:[game rollsAsIntegers]];
}
}
CCLOG(@"finish");
[self analyseMoves];
}
-(NSMutableArray *) otherPlayerLocations {
GameScene *game = [GameScene sharedGameScene];
Board *board = [game board];
Player *otherPlayer = [game playerOne];
NSMutableArray *locations = [[[NSMutableArray alloc] init] autorelease];
for (Stone *stone in otherPlayer.stones) {
if (stone.journey < 77) {
int location;
if (stone.onBoard)
location = [[board tileForATag:[self convertJourneyToTileTag:stone.journey]] bTag];
else
location = 0;
[locations addObject:[NSNumber numberWithInt:location]];
}
}
return locations;
}
-(void) analyseMoves {
if (moves.count > 0) {
NSMutableArray *killMoves = [[[NSMutableArray alloc] init] autorelease];
NSMutableArray *safeMoves = [[[NSMutableArray alloc] init] autorelease];
int mostThreatened;
float highestThreat = -1.0;
float lowestThreat = 100.0;
AIMove *safestMove;
//get kill and safe moves in seperate arrays
for (AIMove *move in moves) {
if (move.moveType == killMoveType)
[killMoves addObject:move];
else if (move.moveType == safeMoveType)
[safeMoves addObject:move];
// get highest threatened stone
//if (move.potThreat > highestThreat) {
// mostThreatened = move.journey;
// highestThreat = move.potThreat;
if (move.initThreat < lowestThreat) {
lowestThreat = move.initThreat;
safestMove = [move copy];
CCLOG(@"safest move assigned");
}
//}
}
//MOVE SELECTION:
//___________________________________
//choose best kill move
int killJourney;
if (killMoves.count > 0) {
//leave one move in killMoves with highest journey
killJourney = [[killMoves objectAtIndex:0] tileTag];
for (AIMove *killMove in killMoves) {
if (killMove.tileTag < killJourney)
[killMoves removeObject:killMove];
else
killJourney = killMove.tileTag;
}
}
//select correct move
if (killMoves.count > 0) {
[self move:[killMoves objectAtIndex:0]];
CCLOG(@"Kill move chosen");
}
else {
CCLOG(@"this is called!!!!");
CCLOG(@"safest move with initThreat: %i, potThreat: %i",safestMove.journey, safestMove.tileTag);
[self move:safestMove];
CCLOG(@"Success");
}
/*
else if (safeMoves.count > 0) {
[self move:[safeMoves objectAtIndex:0]];
CCLOG(@"safe move chosen");
}
else {
//temp random move generation
randomMove = CCRANDOM_0_1()*[moves count];
AIMove *move = [moves objectAtIndex:randomMove];
[self move:move];
CCLOG(@"Random move chosen");
}
*/
}
}
-(void) assignThreatLevel:(AIMove *)move {
NSArray *otherPlayerStones = [self otherPlayerLocations];
NSMutableArray *initThreats = [[NSMutableArray alloc] init];
NSMutableArray *potThreats = [[NSMutableArray alloc] initWithCapacity:4];
for (NSNumber *location in otherPlayerStones) {
//get threat levels for potential moves
if (move.tileTag > [location intValue]) {
int dif = move.tileTag - [location intValue];
CCLOG(@"dif: %i",dif);
//threat level conditions:
// 1 >> 5 = 70% of journey
// 6 >> 9 = 40% of journey
// 10 & 11 = 50% of journey
// 12 >> 24 = 20% of journey
// 25 && 26 = 50% of journey
// 27+ = 20% of journey
if (move.tileTag < 9) {
[initThreats addObject:[NSNumber numberWithFloat:0.0f]];
}
else if (dif >= 1 && dif <= 5) {
[initThreats addObject:[NSNumber numberWithFloat:k1to5]];
}
else if (dif >= 6 && dif <= 9) {
[initThreats addObject:[NSNumber numberWithFloat:k6to9]];
}
else if (dif == 10 || dif == 11) {
[initThreats addObject:[NSNumber numberWithFloat:k10to11]];
}
else if (dif >= 12 && dif <= 24) {
[initThreats addObject:[NSNumber numberWithFloat:k12to24]];
}
else if (dif == 25 || dif == 26) {
[initThreats addObject:[NSNumber numberWithFloat:k25to26]];
}
else if (dif > 26) {
[initThreats addObject:[NSNumber numberWithFloat:k27plus]];
}
//-------------------------------------
}
//get Threat levels for current positions
if (move.tileTag > [location intValue]) {
int dif = move.tileTag - [location intValue];
//threat level conditions:
// 1 >> 5 = 70% of journey
// 6 >> 9 = 40% of journey
// 10 & 11 = 50% of journey
// 12 >> 24 = 20% of journey
// 25 && 26 = 50% of journey
// 27+ = 20% of journey
if (move.journey < 8 || move.journey > 75)
[potThreats addObject:[NSNumber numberWithFloat:0.0f]];
else if (dif >= 1 && dif <= 5)
[potThreats addObject:[NSNumber numberWithFloat:k1to5]];
else if (dif >= 6 && dif <= 9)
[potThreats addObject:[NSNumber numberWithFloat:k6to9]];
else if (dif == 10 || dif == 11)
[potThreats addObject:[NSNumber numberWithFloat:k10to11]];
else if (dif >= 12 && dif <= 24)
[potThreats addObject:[NSNumber numberWithFloat:k12to24]];
else if (dif == 25 || dif == 26)
[potThreats addObject:[NSNumber numberWithFloat:k25to26]];
else if (dif > 26)
[potThreats addObject:[NSNumber numberWithFloat:k27plus]];
//-------------------------------------
}
}
float initThreat = 0.0f;
float potThreat = 0.0f;
for (NSNumber *number in initThreats) {
if ([number floatValue] > initThreat)
initThreat = [number floatValue];
}
for (NSNumber *number in potThreats) {
if ([number floatValue] > potThreat)
potThreat = [number floatValue];
}
move.initThreat = initThreat;
move.potThreat = potThreat;
[initThreats release];
}
-(void) move:(AIMove *)move {
CCLOG(@"Moves count: %i",[moves count]);
if ([moves count] > 0) {
BOOL isOtherStoneOnPreviousTile = NO;
int total;
if (move.tileTag > 8)
total = move.tileTag - move.journey;
else if (move.tileTag < 9 && move.journey > 8)
total = ((9-move.tileTag)+75) - move.journey;
else if (move.tileTag < 9)
total = move.tileTag - move.journey;
CCLOG(@"Total: %i",total);
GameScene *game = [GameScene sharedGameScene];
Board *board = [game board];
BoardTile *tile = [[game board] tileForBTag:move.tileTag];
CCSequence *sequence;
NSMutableArray *actions = [[[NSMutableArray alloc] init] autorelease];
id delay = [CCDelayTime actionWithDuration:0.5];
[actions addObject:delay];
if (move.journey > 0) {
for (int i = 1; i < total+1; i++) {
if (move.journey+i < 76)
tile = [board tileForBTag:move.journey+i];
else
tile = [board tileForBTag:9-((move.journey+i)-75)];
id moveAction = [CCMoveTo actionWithDuration:0.2 position:tile.position];
[actions addObject:moveAction];
}
}
else {
id moveAction = [CCMoveTo actionWithDuration:0.2 position:tile.position];
[actions addObject:moveAction];
}
// id moveFunc = [CCCallFunc actionWithTarget:self selector:@selector(moveMotion)];
//id moveAction = [CCMoveTo actionWithDuration:0.3 position:tile.position];
id killFunc = [CCCallFuncND actionWithTarget:self selector:@selector(killStonesForTile:data:) data:tile];
//id callfunc = [CCCallFunc actionWithTarget:self selector:@selector(move)];
[actions addObject:killFunc];
//[actions addObject:callfunc];
sequence = [CCSequence actionMutableArray:actions];
[actions removeAllObjects];
CGPoint exitPos = ccp(exitPosition.x-(completeStones*30),exitPosition.y-(completeStones*30));
id move2 = [CCMoveTo actionWithDuration:0.2f position:exitPos];
id sequence2 = [CCSequence actions:move2, nil];
Stone *stone = [self getStoneForJourney:move.journey];
//-
//------------------------------------------
//clean tracks
for (Stone *stone in stones) {
if (stone.journey == (move.tileTag - move.journey))
isOtherStoneOnPreviousTile = YES;
}
if (!isOtherStoneOnPreviousTile) {
BoardTile *prevTile = [board tileForBTag:[self convertJourneyToTileTag:move.journey]];
prevTile.occupiedBy = 0;
}
//===========================================
//-------------------------------------------
//set stone status
if (move.tileTag < 9 && stone.crossedEntry)
stone.journey = (9 - move.tileTag) + 75;
else
stone.journey = move.tileTag;
stone.onBoard = YES;
tile.occupiedBy = player2;
if (stone.journey > 8 && !stone.crossedEntry)
stone.crossedEntry = YES;
//============================================
if (stone.journey < 84)
[stone runAction:sequence];
else {
[stone runAction:sequence2];
completeStones++;
stone.isJourneyComplete = YES;
}
CCLOG(@"Stone Journey:%i",stone.journey);
NSArray *rollTypesArray = [move rollTypes];
[self removeRollTypes:rollTypesArray];
[moves removeAllObjects];
[game updateRollResults];
[self updateMoveAvailability];
}
else {
GameScene *game = [GameScene sharedGameScene];
[moves removeAllObjects];
[game nextTurn];
[game updateRollResults];
}
}
-(Stone *)getStoneForJourney:(int)journey {
Stone *theStone;
for (Stone *stone in stones) {
if (stone.journey == journey)
theStone = stone;
}
return theStone;
}
-(void)dealloc {
[moves release];
[rollTypes release];
[results release];
[super dealloc];
}
-(void)killStonesForTile:(id)sender data:(BoardTile *)tile {
GameScene *game = [GameScene sharedGameScene];
int tileTag;
Player *otherPlayer;
if (playerNumber == player1) {
tileTag = tile.aTag;
otherPlayer = [game playerTwo];
}
else {
tileTag = tile.bTag;
otherPlayer = [game playerOne];
}
CCArray *currentStones = [otherPlayer stones];
for (Stone *stone in currentStones) {
if (!stone.isJourneyComplete) {
int journey = stone.journey;
if (tileTag == tile.aTag) {
if (journey > 0 && [self convertJourneyToTileTag:journey] == tile.bTag) {
CCLOG(@"blue stone killed");
[self returnStoneToOrigin:stone];
}
}
if (tileTag == tile.bTag) {
if (journey > 0 && [self convertJourneyToTileTag:journey] == tile.aTag) {
CCLOG(@"gold stone killed");
[self returnStoneToOrigin:stone];
}
}
}
}
}
-(void)removeRollTypes:(NSArray *)theRollTypes {
GameScene *game = [GameScene sharedGameScene];
NSMutableArray *rolls = [game rolls];
for (NSNumber *roll in theRollTypes) {
NSUInteger index = [rolls indexOfObject:[game convertIntToRoll:roll]];
CCLOG(@"rolltypes count: %i",[theRollTypes count]);
CCLOG(@"roll integer: %i",[roll intValue]);
[rolls removeObjectAtIndex:index];
}
}
#pragma mark -
#pragma mark enumerations
- (NSArray*)getSums:(NSArray*)numbers {
NSMutableArray *result = [self getSumsHelper:numbers startingFrom:0];
[result removeObjectAtIndex:0];
return result;
}
- (NSMutableArray*)getSumsHelper:(NSArray*)numbers startingFrom:(NSUInteger)index {
/* (1) */
if (index >= [numbers count])
return [NSMutableArray arrayWithObject:[NSNumber numberWithFloat:0]];
/* (2) Generate all the subsets where the `index`th element is not included */
NSMutableArray* result = [self getSumsHelper:numbers startingFrom:index+1];
// NSSortDescriptor *mySorter = [[NSSortDescriptor alloc] initWithKey:@"floatValue" ascending:YES];
// [result sortUsingDescriptors:[NSArray arrayWithObject:mySorter]];
/* (3) Add all the cases where the `index`th element is included */
NSUInteger i, n = [result count];
float element = [[numbers objectAtIndex:index] floatValue];
for (i = 0; i < n; i++) {
float element2 = [[result objectAtIndex:i] floatValue];
float sum = element+element2;
BOOL numberPresent = NO;
for (NSNumber *number in result) {
if ([number floatValue] == sum)
numberPresent = YES;
}
if (!numberPresent)
[result addObject:[NSNumber numberWithFloat:sum]];
}
return result;
}
-(NSArray *) getCombsforNumbers:(NSArray *)numbers withTarget:(int)target{
NSMutableArray *partial = [[NSMutableArray alloc] init];
[partial addObject:[NSNumber numberWithInt:0]];
[results removeAllObjects];
NSArray *result = [self getCombsHelper:numbers target:target partial:partial];
NSUInteger minCount = [[result objectAtIndex:0] count];
NSUInteger index = 0;
NSMutableArray *combArray = [result objectAtIndex:0];
for (NSMutableArray *array in result) {
if ([array count] < minCount) {
minCount = [array count];
index = [result indexOfObject:array];
combArray = array;
}
}
//remove number 0 from array
[combArray removeObject:[NSNumber numberWithInt:0]];
return combArray;
}
-(NSMutableArray *) getCombsHelper:(NSArray *)numbers target:(int)target partial:(NSMutableArray *)partial {
int s = 0;
for (NSNumber *number in partial) {
s += [number intValue];
}
if (s == target) {
[results addObject:partial];
}
if (s >= target) {
return results;
}
for (int i = 0; i < [numbers count]; i++) {
NSMutableArray *remaining = [[[NSMutableArray alloc] init] autorelease];
int n = [[numbers objectAtIndex:i] intValue];
for (int j = i+1; j<[numbers count]; j++) {
[remaining addObject:[numbers objectAtIndex:j]];
}
NSMutableArray *partialRec = [[[NSMutableArray alloc] init] autorelease];
[partialRec addObjectsFromArray:partial];
[partialRec addObject:[NSNumber numberWithInt:n]];
[self getCombsHelper:remaining target:target partial:partialRec];
}
return results;
}
-(void) getMovesForJourney:(int)journey withRolls:(NSArray *)rolls {
GameScene *game = [GameScene sharedGameScene];
Board *board = [game board];
NSArray *sums = [self getSums:rolls];
for (NSNumber *number in sums) {
if ([number intValue]+journey <= 84) {
BoardTile *tile = [board tileForBTag:[self convertJourneyToTileTag:journey+[number intValue]]];
if (tile.isSafeTile) {
if (tile.occupiedBy != player1) {
AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];
//Checking rolltypes, remove later
NSLog(@"%i = ",[number intValue]);
for (NSNumber *comb in theRollTypes) {
NSLog(@"%i",[comb intValue]);
}
NSLog(@"-----------");
//----------------------------------
move.moveType = safeMoveType;
move.initThreat = 0.0;
CCLOG(@"move initThreat: %f",move.initThreat);
[move setRollTypes:theRollTypes];
[moves addObject:move];
}
}
else {
AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];
//Checking rolltypes, remove later
NSLog(@"%i = ",[number intValue]);
for (NSNumber *comb in theRollTypes) {
NSLog(@"%i",[comb intValue]);
}
NSLog(@"-----------");
//-----------------------------------
[move setRollTypes:theRollTypes];
//assing threat level
[self assignThreatLevel:move];
CCLOG(@"move initThreat: %f",move.initThreat);
//check for kill move
NSArray *otherPlayerPositions = (NSArray *)[self otherPlayerLocations];
for (NSNumber *location in otherPlayerPositions) {
if (move.tileTag == [location intValue])
move.moveType = killMoveType;
}
[moves addObject:move];
}
}
//int i = [number intValue];
//NSArray *combs = [self getCombsforNumbers:numbers withTarget:i];
}
}
-(void) getEntryMovesForJourney:(int)journey withRolls:(NSArray *)rolls {
GameScene *game = [GameScene sharedGameScene];
Board *board = [game board];
NSArray *sums = [self getSums:rolls];
for (NSNumber *number in sums) {
if ([number intValue]+journey <= 84) {
BoardTile *tile = [board tileForBTag:[self convertJourneyToTileTag:journey+[number intValue]]];
if (tile.isSafeTile) {
if (tile.occupiedBy != player1) {
NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];
BOOL containsEntry = NO;
for (NSNumber *rollType in theRollTypes) {
if ([rollType intValue] == 1) {
containsEntry = YES;
}
}
if (containsEntry) {
AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
//Checking rolltypes, remove later
NSLog(@"%i = ",[number intValue]);
for (NSNumber *comb in theRollTypes) {
NSLog(@"%i",[comb intValue]);
}
NSLog(@"-----------");
move.moveType = safeMoveType;
move.initThreat = 0.0;
CCLOG(@"move initThreat: %f",move.initThreat);
[move setRollTypes:theRollTypes];
[moves addObject:move];
//----------------------------------
}
}
}
else {
NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];
BOOL containsEntry = NO;
for (NSNumber *rollType in theRollTypes) {
if ([rollType intValue] == 1) {
containsEntry = YES;
}
}
if (containsEntry) {
AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
[move setRollTypes:theRollTypes];
//check for kill move
NSArray *otherPlayerPositions = (NSArray *)[self otherPlayerLocations];
for (NSNumber *location in otherPlayerPositions) {
if (move.tileTag == [location intValue])
move.moveType = killMoveType;
}
//assing threat level
[self assignThreatLevel:move];
[moves addObject:move];
//Checking rolltypes, remove later
NSLog(@"%i = ",[number intValue]);
for (NSNumber *comb in theRollTypes) {
NSLog(@"%i",[comb intValue]);
}
NSLog(@"-----------");
CCLOG(@"move initThreat: %f",move.initThreat);
[move setRollTypes:theRollTypes];
[moves addObject:move];
//----------------------------------
}
}
}
}
}
Technically,
methodBis called aftermethodAis finished. InmethodAyou are apparently doing things that are backgrounded, meaning that the method finishes while some tasks are performed on another thread (or scheduled on the runloop). There’s nothing we can say about this unless you do share the inner workings ofmethodA.