为 UI 分派信号量
Dispatch Semaphore for UI
我想为 uiviews 的 alpha 设置动画,但我似乎做不到。它的行为很奇怪,并说错误 运行ning UI changes arent recommended to be 运行 on background thread,但我不知道如何在主线程上做到 运行 .有人可以帮我吗?我相信它会跳过第一个 UIView.animate 块并在没有任何动画的情况下执行第二个块。
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
let dispatchSemaphore = DispatchSemaphore(value: 0)
let dispatchQueue = DispatchQueue.global(qos: .background)
dispatchQueue.async {
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
print("1")
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 3, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 1, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
self.animateSemaphore()
}
}
}
您需要在主线程而不是后台队列中插入任何 ui/animate 相关代码
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 3, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 1, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
}
}
}
}
}
或使用 delay
而不是嵌套动画
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
print("1")
}
UIView.animate(withDuration: 0.5, delay: 8.5, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
}
UIView.animate(withDuration: 0.5, delay: 14, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
}
UIView.animate(withDuration: 0.5, delay: 15.5, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
}
}
您还可以创建用于创建动画的配置(可以在此处找到草稿)
https://gist.github.com/maximkrouk/76163b3f2775dafc73c5633d155368cb
并添加一些扁平化
public struct UIViewAnimation {
private init(
provider: UIViewAnimatiorProvider?,
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
self.provider = provider
self.animations = animations
self.completion = completion
}
public init(
config: UIViewAnimatiorProvider,
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
self.init(
provider: config,
animations: animations,
completion: completion
)
}
let provider: UIViewAnimatiorProvider?
let animations: () -> Void
let completion: ((Bool) -> Void)?
public func run() {
if let provider = provider {
provider.makeAnimator(
for: animations,
completion: completion ?? { _ in }
).animate()
} else {
animations()
completion?(true)
}
}
public func appendingCompletion(_ completion: @escaping (Bool) -> Void) -> UIViewAnimation {
UIViewAnimation(
provider: provider,
animations: animations,
completion: { isFinished in
self.completion?(isFinished)
completion(isFinished)
}
)
}
public static let empty: UIViewAnimation = .init(
provider: nil,
animations: {},
completion: nil
)
}
extension UIViewAnimation {
public static func sequence(_ animations: UIViewAnimation...) -> UIViewAnimation {
guard var animation = animations.last else { return .empty }
animations.dropLast().reversed().forEach { prevAnimation in
let animate = animation.run
animation = prevAnimation.appendingCompletion { _ in animate() }
}
return animation
}
}
并像
一样使用它
extension UIView {
func animateSemaphore() {
let initialBackground = backgroundColor
UIViewAnimation.sequence(
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .red
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .green
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .red
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .green
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = initialBackground
}
).run()
}
}
UIView().animateSemaphore()
我想为 uiviews 的 alpha 设置动画,但我似乎做不到。它的行为很奇怪,并说错误 运行ning UI changes arent recommended to be 运行 on background thread,但我不知道如何在主线程上做到 运行 .有人可以帮我吗?我相信它会跳过第一个 UIView.animate 块并在没有任何动画的情况下执行第二个块。
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
let dispatchSemaphore = DispatchSemaphore(value: 0)
let dispatchQueue = DispatchQueue.global(qos: .background)
dispatchQueue.async {
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
print("1")
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 3, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
UIView.animate(withDuration: 0.5, delay: 1, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
self.animateSemaphore()
}
}
}
您需要在主线程而不是后台队列中插入任何 ui/animate 相关代码
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 3, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
UIView.animate(withDuration: 0.5, delay: 1, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
}
}
}
}
}
或使用 delay
而不是嵌套动画
func animateSemaphore() {
circleRed.alpha = 0.2
circleOrange.alpha = 0.2
circleGreen.alpha = 1
UIView.animate(withDuration: 0.5, delay: 5, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
self.circleGreen.alpha = 0.2
} completion: { (_) in
print("1")
}
UIView.animate(withDuration: 0.5, delay: 8.5, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 1
} completion: { (_) in
}
UIView.animate(withDuration: 0.5, delay: 14, options: .curveEaseInOut) {
self.circleOrange.alpha = 1
} completion: { (_) in
}
UIView.animate(withDuration: 0.5, delay: 15.5, options: .curveEaseInOut) {
self.circleOrange.alpha = 0.2
self.circleRed.alpha = 0.2
self.circleGreen.alpha = 1
} completion: { (_) in
}
}
您还可以创建用于创建动画的配置(可以在此处找到草稿) https://gist.github.com/maximkrouk/76163b3f2775dafc73c5633d155368cb 并添加一些扁平化
public struct UIViewAnimation {
private init(
provider: UIViewAnimatiorProvider?,
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
self.provider = provider
self.animations = animations
self.completion = completion
}
public init(
config: UIViewAnimatiorProvider,
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
self.init(
provider: config,
animations: animations,
completion: completion
)
}
let provider: UIViewAnimatiorProvider?
let animations: () -> Void
let completion: ((Bool) -> Void)?
public func run() {
if let provider = provider {
provider.makeAnimator(
for: animations,
completion: completion ?? { _ in }
).animate()
} else {
animations()
completion?(true)
}
}
public func appendingCompletion(_ completion: @escaping (Bool) -> Void) -> UIViewAnimation {
UIViewAnimation(
provider: provider,
animations: animations,
completion: { isFinished in
self.completion?(isFinished)
completion(isFinished)
}
)
}
public static let empty: UIViewAnimation = .init(
provider: nil,
animations: {},
completion: nil
)
}
extension UIViewAnimation {
public static func sequence(_ animations: UIViewAnimation...) -> UIViewAnimation {
guard var animation = animations.last else { return .empty }
animations.dropLast().reversed().forEach { prevAnimation in
let animate = animation.run
animation = prevAnimation.appendingCompletion { _ in animate() }
}
return animation
}
}
并像
一样使用它extension UIView {
func animateSemaphore() {
let initialBackground = backgroundColor
UIViewAnimation.sequence(
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .red
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .green
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .red
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = .green
},
UIViewAnimation(config: .init(duration: 2)) {
self.backgroundColor = initialBackground
}
).run()
}
}
UIView().animateSemaphore()