1

I want to make an animal blink the eyes with different delays Int.random(in: 1..<9)

The problem is:

There are solutions for UIView animations and async thread delays... But is there any method for UIImage.animatedImage to make a delay between the blinks?

If there are no methods at all - how can I solve my issue?

The code:

File for all animations:

 import SwiftUI
  struct AnimalAnimation: UIViewRepresentable {
    @Binding var animalImages: [UIImage?]
    @Binding var size: CGRect

    func makeUIView(context: Self.Context) -> UIView {

        let someView = UIView(frame: CGRect(x: size.minX, y: size.minY , width: size.width, height: size.height))
        let someImage = UIImageView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let animated = UIImage.animatedImage(with: animalImages as! [UIImage], duration: 0.9)!

        someImage.clipsToBounds = true
        someImage.autoresizesSubviews = true
        someImage.contentMode = UIView.ContentMode.scaleAspectFit
        someImage.image = animated
        someView.addSubview(someImage)
        return someView
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<AnimalAnimation>) {
    }
  }

I'm using this in ContentView's body

            VStack {
                    AnimalAnimation(animalImages: $animal1Array, size: $animal1Size)
            }

The images:

animalImages = [UIImage(named: "eyes-open"),UIImage(named: "eyes-closed")]
2
  • And where are the blinks? It is not clear in-between what the delay is expected. Commented May 21, 2020 at 16:54
  • @Asperi, animalImages = [UIImage(named: "eyes-open"),UIImage(named: "eyes-closed")] Commented May 21, 2020 at 17:33

2 Answers 2

3

Here is SwiftUI only variant. Tested with Xcode 11.4 / iOS 13.4. (Sizes/frames if needed can be configured, for demo it does not matter)

demo

struct EyesBlinkView: View {

    enum EyesState: String {
        case open = "eyes-open"
        case closed = "eyes-closed"
    }

    @State private var eyesState = EyesState.open
    var body: some View {
        Image(eyesState.rawValue).resizable().scaledToFit()
            .onAppear { self.blink() }
    }

    private func blink() {
        self.eyesState = .closed
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
            self.eyesState = .open

            DispatchQueue.main.asyncAfter(deadline: 
                  DispatchTime.now().advanced(by: .seconds(Int.random(in: 1..<9)))) {
                self.blink()
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

@Aspari, Perfect enough) What if we have 7-10 idle objects for eyes? Wouldn't it harm our memory?
@Oleksandr, hmmm... hard to say... the size of this struct value is 16 bytes ))... one cool guy said one day that 64kB memory should be enough for any program - your 10 values would satisfy that. I think so. 8^)
0

why don't you just add the same image again in the array so it "looks like" a delay?

1 Comment

It's not a machinegun ))) It is idle objects. They have to blink the eyes once per 1-9 seconds. If I put one more image - they will clip just more often. If to make a huge "duration" - it won't be blinking at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.