Вызов setNeedsDisplay не приводит к немедленному перерисовке представления, он просто помечает представление как грязное, что приведет к его перерисовке на следующем цикле рисования.
Я думаю, что будет трудно добиться быстрой и плавной анимации с помощью метода setNeedsDisplay.
Вы пробовали вместо этого использовать базовую анимацию?
Последнее замечание: если вы используете setNeedsDisplay, всегда вызывайте его из основного потока.