swiftmacosanimationnsstackviewnsanimationcontext

Whats the best way in Swift to animate an array of NSViews to appear one after another in an NSStackView?


I'm able add a number of NSTextFields to an NSStackView using the following code:

optionsStackView.addView(newOption, in: .center)

The problem I'm encountering is getting each NSTextField (newOption) to appear one after another when the view appears - not all at once when using NSAnimationContext.runAnimationGroup { (context) in }

        let stackViewSubViews = optionsStackView?.arrangedSubviews.enumerated()
        stackViewSubViews!.forEach({ newOption in
            NSAnimationContext.runAnimationGroup { (context) in
                context.duration = 1
                newOption.element.animator().alphaValue = 1
            }
        })

I basically need to delay for a half a second each time the for loop runs to show one NSTextField after another for all the NSTextFields but I can't quite figure out how to do this. I looked at using DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) but can't quite figure out the code to make this work without everything appearing all at once...

I'm sure I'm missing something simple here.

Can anyone please help?


Solution

  • The simplest way to insert a delay during each iteration of a loop is to turn the loop into a recursion. I'll show you the general technique and you can adapt it to your use case:

    func slowly(from i:Int, to n:Int) {
        print(i)
        if i != n {
            DispatchQueue.main.asyncAfter(deadline:.now()+0.5) {
                slowly(from:i+1, to:n)
            }
        }
    }
    slowly(from:1, to:3)