Я подозреваю, что знаю, что не так, но не знаю, как «исправить» это, в зависимости от того, насколько «правильным» вы хотите быть. Происходит все просто - Objective C не вызывает функции, он передает сообщения. Когда вы делаете [self StrikeFrog], сообщение помещается в очередь для выполнения, как только очередь может быть очищена; вы, вероятно, получаете все сообщения в конце, потому что StrikeFrog не вызывается перед сном - он вызывается всякий раз, когда поток очереди разблокируется. Например, в однопоточном приложении чистый эффект будет состоять в том, что он будет спать в течение (colorChoices.count) секунд, а затем выполнит все события StrikeFrog после выхода из цикла for, поскольку это первый раз, когда очередь событий может отправлять ваши события. Другими словами, все «вызовы функций» в Obj C являются асинхронными, независимо от того, сколько потоков используется.
Я бы предложил перейти на более низкий уровень с C или на более высокий уровень с CoreAnimation. Если ни один из этих способов вам не подходит, вы можете попробовать NSObject executeSelector: withObject: afterDelay: , чтобы поставить в очередь целую группу событий, каждое из которых выполняется после некоторой задержки. У этого метода есть много проблем, с которыми вам придется разобраться, поэтому будьте осторожны.