Как заставить UIAnimation выполнять по одному (повторять цикл), а не выполнять все сразу? - PullRequest
0 голосов
/ 26 сентября 2019

В настоящее время я создаю контроллер представления для приложения, которое помогает визуализировать алгоритм Bubble Sort.Однако, когда пользователь нажимает кнопку сортировки, а не перестановки, происходящие один за другим (давая пользователю некоторое время, чтобы увидеть, как работает алгоритм), числа сортируются сразу, и все они сразу попадают на свои места.Я хочу, чтобы UIAnimation перебирала цикл for и имела элементы подкачки один за другим, а не все сразу.

Я уже пытался передать задержку в качестве параметра UIView.одушевленный метод.Все, что он делает, это приостанавливает указанное количество времени, прежде чем сортировать их все сразу (что мне не нужно).

//IBOutlets for the images (containing numbers) and the sort button
@IBOutlet weak var sortButton: UIButton!

@IBOutlet weak var firstImage: UIImageView!
@IBOutlet weak var secondImage: UIImageView!
@IBOutlet weak var thirdImage: UIImageView!
@IBOutlet weak var fourthImage: UIImageView!
@IBOutlet weak var fifthImage: UIImageView!
@IBOutlet weak var sixthImage: UIImageView!
@IBOutlet weak var seventhImage: UIImageView!
@IBOutlet weak var eighthImage: UIImageView!
@IBOutlet weak var ninthImage: UIImageView!
@IBOutlet weak var tenthImage: UIImageView!


//Create an array of UIImageViews
var elements : [UIImageView] = [UIImageView]()
var numberArray : [Int] = [Int]()

//Function when the view loads
override func viewDidLoad() {

    super.viewDidLoad()

    //Add the UIImageViews to the array
    elements += [firstImage, secondImage, thirdImage, fourthImage, fifthImage, sixthImage, seventhImage, eighthImage, ninthImage, tenthImage]

    //Create a variable that will indicate whether there is a duplicate number in the array
    var duplicate = true;

    //Assign each element in the array a random number between 1 and 10
    for index in elements {
        //Repeat-while loop to avoid duplicate numbers in the array
        repeat {
            //Create a random number
            let randNumber = Int.random(in: 1 ... 10)
            //Display the appropriate numbered image
            index.image = UIImage(named: "\(randNumber)")
            //Check to see if the number is already a duplicate
            if numberArray.contains(randNumber) {
                duplicate = true
            } else {
                duplicate = false
                //Add the number to the list of used numbers in the array
                numberArray.append(randNumber)
            }
        } while duplicate == true
    }
} //End of viewDidLoad




@IBAction func sortButtonPressed(_ sender: Any) {

    //Bubble Sort algorithm
    for i in (0..<elements.count) {
        for j in (1..<elements.count) {
            if numberArray[j]<numberArray[j-1] {

                let temp = numberArray[j-1]
                numberArray[j-1] = numberArray[j]
                numberArray[j] = temp

                let tempElement = elements[j-1]
                elements[j-1] = elements[j]
                elements[j] = tempElement

                //Swap the corresponding UIImageViews on screen
                let tempView : CGRect = elements[j-1].frame

                UIView.animate(withDuration: 0.75, delay: 0, animations: {
                    self.elements[j-1].frame = CGRect(x: self.elements[j].frame.minX, y: self.elements[j].frame.minY, width: tempView.width, height: tempView.height)
                    self.elements[j].frame = CGRect(x: tempView.minX, y: tempView.minY, width: self.elements[j].frame.width, height: self.elements[j].frame.width)
                    self.view.layoutIfNeeded()
                })
            }
        }
    }
}

Кто-нибудь знает, как сделать обмен изображениями (анимации) один за другим (за каждую итерацию) а не все сразу?(Область фокуса находится внизу функции sortButtonPressed ...) Любая помощь будет принята с благодарностью.Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 26 сентября 2019

Чтобы сделать что-то подобное вручную, вам нужно будет запустить новую анимацию по окончании текущей.Есть несколько способов сделать это, но один из них - упаковать все данные, необходимые для вашей анимации, в класс, а затем создать массив таких классов.Затем вы можете создать один метод, который вызывается рекурсивно.Примерно так:

- (void)performAllAnimations:(NSArray *)allAnimations
{
    NSMutableArray *duplicate = [allAnimations mutableCopy];
    AnimationDescription *currentAnimation = duplicate.firstObject;
    [duplicate removeObjectAtIndex:0];

    [UIView animateWithDuration:currentAnimation.duration animations:^{
        // Use currentAnimation to do the animation
    } completion:^(BOOL finished) {
        if(duplicate.count > 0) [self performAllAnimations:duplicate];
    }];
}

Вам не всегда нужен AnimationDescription в качестве пользовательского класса.В вашем случае может быть достаточно просто использовать массив индексов.Например, вы можете сделать:

- (void)performAllAnimations:(NSArray *)allAnimations
{
    NSMutableArray *duplicate = [allAnimations mutableCopy];
    int currentAnimationIndex = [duplicate.firstObject integerValue];
    [duplicate removeObjectAtIndex:0];

    [UIView animateWithDuration:0.3 animations:^{
        // Use currentAnimation to do the animation
    } completion:^(BOOL finished) {
        if(duplicate.count > 0) [self performAllAnimations:duplicate];
    }];
}

Затем вы можете сделать что-то вроде:

NSMutableArray *indexArray = [[NSMutableArray alloc] init];
for(int i=0; i<10; i++) {
    [indexArray addObject:@(i)];
}
[self performAllAnimations: indexArray];

Естественно используя свои собственные данные.

Другой подход заключается в использовании задержки,В некоторых случаях это может быть лучше, поскольку у вас больше контроля над началом следующей анимации.Смотрите следующий пример:

- (void)performAllAnimations:(NSArray *)allAnimations withAnimationExecution:(void (^)(id animationObject, int index))execution
{
    NSTimeInterval duration = 0.3;

    for(int i=0; i<allAnimations.count; i++) {
        [UIView animateWithDuration:duration delay:(duration*0.5)*i options:UIViewAnimationOptionCurveEaseInOut animations:^{
            execution(allAnimations[i], i);
        } completion:^(BOOL finished) {

        }];
    }
}

- (void)testAnimation
{
    NSMutableArray *views = [[NSMutableArray alloc] init];
    for(int i=0; i<10; i++) {
        UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 50.0, 100.0, 100.0)];
        [self.view addSubview:aView];
        aView.backgroundColor = [UIColor blackColor];
        aView.layer.borderWidth = 2.0;
        aView.layer.borderColor = [UIColor yellowColor].CGColor;
        [views addObject:aView];
    }
    [self performAllAnimations:views withAnimationExecution:^(id animationObject, int index) {
        UIView *view = animationObject;
        view.frame = CGRectMake(75.0*index, 100.0, 100.0, 100.0);
    }];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...