braker1nine / braker1nine/KitUI
Crash when `.alpha(...)` is called after `.vibrancy(...)` / `.visualEffect(...)`
- Dominant language
- Swift
- Stars
- 4
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
`.vibrancy(...)` and `.visualEffect(...)` return a `UIVisualEffectView`. Calling `.alpha(...)` on that view — especially with a value from `SignalProducer.animated(...)` — causes an `EXC_BREAKPOINT` / `CFRetain` crash inside `CAAnimation_setter` → `-[CAAnimation setDelegate:]`.
This happens because `UIVisualEffectView` should never have its `alpha` animated or set to `< 1`. When `alpha` is changed inside a `UIView.animate` block, UIKit creates an implicit `opacity` `CAAnimation` for the visual effect view’s layer; setting that animation’s delegate can crash.
#### Reproducer pattern
```swift
Horizontal { ... }
.vibrancy(blurEffect: .systemUltraThinMaterial, style: .fill)
.alpha(someAnimatedProducer.mapIf(on: 0, off: 1.0))
```
`someAnimatedProducer.animated(...)` sends its values inside a `UIView.animate` block, which calls `setAlpha:` on the `UIVisualEffectView`.
#### Suggested fix
In `Sources/KitUI/Extensions/UIKit/UIView.swift`, make the `alpha` chainable redirect to the `UIVisualEffectView` content view when the receiver is a `UIVisualEffectView`:
```swift
@discardableResult
public func alpha(_ value: some SignalProducerConvertible) -> Self {
if let visualEffectView = self as? UIVisualEffectView {
visualEffectView.contentView.reactive.alpha <~ value.producer.map(\.cgFloat)
} else {
self.reactive.alpha <~ value.producer.map(\.cgFloat)
}
return self
}
```
This keeps `UIVisualEffectView.alpha` at `1.0` while the content view fades in/out normally.
Another option would be to change `vibrancy(...)` and `visualEffect(...)` to return `UIVisualEffectView` and add a `UIVisualEffectView`-specific `alpha` overload. The downside to that is if you have a `UIVisualEffectView` but have cast it to a `UIView`... you will use the `UIView` version and not set the alpha on the contentView
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in Sources/KitUI/Extensions/UIKit/UIView.swift and inspect the chainable alpha implementation, then compare it with the vibrancy and visualEffect entry points described in the issue. Done means UIVisualEffectView remains at alpha 1.0 while its content view fades without the reported EXC_BREAKPOINT or CFRetain crash.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100