Swift에서 애니메이션을 연속으로 실행하는 이야기
UIView
애니메이션도 보통 연속으로 실행해야 한다면completion
의 회호지옥아, 회호지옥을 하지 않는 연속 실행 애니메이션을 실행해 봤다.방법은 매우 간단하다. 애니메이션 블록을 하나씩 꺼내서 애니메이션이 끝난 후에 자신의 API를 호출하기만 하면 된다.결과는 다음과 같은 Playground 실행 가능한 소스 코드로 작성할 수 있습니다.
Playground.swift
let base = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
base.backgroundColor = .white
PlaygroundPage.current.liveView = base
let view = UIView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
view.backgroundColor = .blue
base.addSubview(view)
// アニメーションブロック
UIView.animate(eachBlockDuration: 1, eachBlockDelay: 0, eachBlockOptions: .curveEaseInOut, animationBlocks:
{ view.frame.origin = .zero },
{ view.frame.size.width = 400 },
{ view.frame.size.height = 400 }
) { (finished) in
print(finished)
}
플레이그라운드 콘서트에서 이걸 보면 이런 느낌이에요.그렇다면 이
animate(eachBlock...)
의 실현은 바로 이런 느낌이다.UIView.swift
private extension ArraySlice {
var startItem: Element {
return self[self.startIndex]
}
}
extension UIView {
private typealias `Self` = UIView
private static func animate(eachBlockDuration duration: TimeInterval, eachBlockDelay delay: TimeInterval, eachBlockOptions options: UIViewAnimationOptions, animationArraySlice: ArraySlice<() -> Void>, completion: ((_ finished: Bool) -> Void)?) {
let animation = animationArraySlice.startItem
UIView.animate(withDuration: duration, delay: delay, options: options, animations: animation) { (finished) in
let remainedAnimations = animationArraySlice.dropFirst()
if remainedAnimations.isEmpty {
completion?(finished)
} else {
Self.animate(eachBlockDuration: duration, eachBlockDelay: delay, eachBlockOptions: options, animationArraySlice: remainedAnimations, completion: completion)
}
}
}
public static func animate(eachBlockDuration duration: TimeInterval, eachBlockDelay delay: TimeInterval = 0, eachBlockOptions options: UIViewAnimationOptions = .curveEaseInOut, animationBlocks: (() -> Void)..., completion: ((_ finished: Bool) -> Void)? = nil) {
let isFinished = animationBlocks.isEmpty
guard isFinished == false else {
completion?(isFinished)
return
}
let animationArraySlice = ArraySlice(animationBlocks)
Self.animate(eachBlockDuration: duration, eachBlockDelay: delay, eachBlockOptions: options, animationArraySlice: animationArraySlice, completion: completion)
}
}
두 가지 아주 비슷한 방법이 있는데 하나는 public
, 하나는 private
이다. 그런데 왜 두 가지가 있을까? 가변 길이 파라미터를 다른 함수에 직접 전달할 수 없기 때문이다.실행 효율성이나 프로그램 내부의 용이성Array
보다는 ArraySlice
높기 때문에(재생성 기간.dropFirst()
없이 그렇게 사용) 매개변수를 ArraySlice<() -> Void>
형으로 설정하는 방법을 준비했습니다.그러나ArraySlice
의 경우 사용하는 쪽으로서 가변 길이 파라미터에 비해 역시 미묘한 군배가 비교적 낮고 사용하는 쪽은 가변 길이 파라미터, 내부는ArraySlice
로 구분하여 사용한다.또한 public
측에서 매개 변수의 길이가 1 이상이어야 한다면first?
도 자화자찬할 필요가 없다.마지막으로 private
방법ArraySlice
을 비워 두면 전달된 애니메이션 블록을 하나씩 실행할 수 있습니다.편리한 방법˘ω˘)한동안홍보:올해야말로!그래서 저는 iOSDC에 상담을 많이 신청했습니다!관심 있는 이야기가 있으면 RT 꼭 해주세요!
유행의 이니셜
ADDD(API-Design-Driven Development)
AVAudioEngine의 오디오 반복 재생 사용
Swift4.0 대처하려면 참담할 것 같아요.
책임 범위를 의식한 이야기
UIView 속성 및 방법
Reference
이 문제에 관하여(Swift에서 애니메이션을 연속으로 실행하는 이야기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/lovee/items/460cbb02a345e0ff7910텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)