Skip to content

Commit

Permalink
Fixed Swizzling crash(Juanpe#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin5566.huang committed Sep 11, 2024
1 parent 30c92f0 commit 50ce477
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ enum ViewAssociatedKeys {
static var skeletonCornerRadius = "skeletonCornerRadius"
static var disabledWhenSkeletonIsActive = "disabledWhenSkeletonIsActive"
static var delayedShowSkeletonWorkItem = "delayedShowSkeletonWorkItem"

static var isPerformingSwizzleLayoutSubviews = "isPerformingSwizzleLayoutSubviews"
static var isPerformingSwizzleTraitCollectionDidChange = "isPerformingSwizzleTraitCollectionDidChange"
}
// codebeat:enable[TOO_MANY_IVARS]

Expand Down Expand Up @@ -91,4 +92,14 @@ extension UIView {
get { return ao_get(pkey: &ViewAssociatedKeys.skeletonCornerRadius) as? Float ?? SkeletonViewAppearance.shared.skeletonCornerRadius }
set { ao_set(newValue, pkey: &ViewAssociatedKeys.skeletonCornerRadius) }
}

var _isPerformingSwizzleLayoutSubviews: Bool {
get { return ao_get(pkey: &ViewAssociatedKeys.isPerformingSwizzleLayoutSubviews) as? Bool ?? false }
set { ao_set(newValue, pkey: &ViewAssociatedKeys.isPerformingSwizzleLayoutSubviews) }
}

var _isPerformingSwizzleTraitCollectionDidChange: Bool {
get { return ao_get(pkey: &ViewAssociatedKeys.isPerformingSwizzleTraitCollectionDidChange) as? Bool ?? false }
set { ao_set(newValue, pkey: &ViewAssociatedKeys.isPerformingSwizzleTraitCollectionDidChange) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,65 @@ import UIKit
extension UIView {

@objc func skeletonLayoutSubviews() {
guard Thread.isMainThread else { return }
skeletonLayoutSubviews()
// Use flag to prevent recursive calls
if _isPerformingSwizzleLayoutSubviews || !Thread.isMainThread { return }

_isPerformingSwizzleLayoutSubviews = true
defer { _isPerformingSwizzleLayoutSubviews = false }

self.skeletonLayoutSubviews()

guard sk.isSkeletonActive else { return }
layoutSkeletonIfNeeded()
}

@objc func skeletonTraitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
skeletonTraitCollectionDidChange(previousTraitCollection)
// Use flag to prevent recursive calls
if _isPerformingSwizzleTraitCollectionDidChange { return }

_isPerformingSwizzleTraitCollectionDidChange = true
defer { _isPerformingSwizzleTraitCollectionDidChange = false }

self.skeletonTraitCollectionDidChange(previousTraitCollection)

guard isSkeletonable, sk.isSkeletonActive, let config = _currentSkeletonConfig else { return }
updateSkeleton(skeletonConfig: config)
}

func swizzleLayoutSubviews() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
DispatchQueue.once(token: "UIView.SkeletonView.swizzleLayoutSubviews") {
swizzle(selector: #selector(UIView.layoutSubviews),
with: #selector(UIView.skeletonLayoutSubviews),
inClass: UIView.self,
usingClass: UIView.self)
self.layoutSkeletonIfNeeded()
}
DispatchQueue.once(token: "UIView.SkeletonView.swizzleLayoutSubviews") {
swizzle(selector: #selector(UIView.layoutSubviews),
with: #selector(UIView.skeletonLayoutSubviews),
inClass: UIView.self,
usingClass: UIView.self)
self.layoutSkeletonIfNeeded()
}
}

func unSwizzleLayoutSubviews() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
DispatchQueue.removeOnce(token: "UIView.SkeletonView.swizzleLayoutSubviews") {
swizzle(selector: #selector(UIView.skeletonLayoutSubviews),
with: #selector(UIView.layoutSubviews),
inClass: UIView.self,
usingClass: UIView.self)
}
DispatchQueue.removeOnce(token: "UIView.SkeletonView.swizzleLayoutSubviews") {
swizzle(selector: #selector(UIView.skeletonLayoutSubviews),
with: #selector(UIView.layoutSubviews),
inClass: UIView.self,
usingClass: UIView.self)
}
}

func swizzleTraitCollectionDidChange() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
DispatchQueue.once(token: "UIView.SkeletonView.swizzleTraitCollectionDidChange") {
swizzle(selector: #selector(UIView.traitCollectionDidChange(_:)),
with: #selector(UIView.skeletonTraitCollectionDidChange(_:)),
inClass: UIView.self,
usingClass: UIView.self)
}
DispatchQueue.once(token: "UIView.SkeletonView.swizzleTraitCollectionDidChange") {
swizzle(selector: #selector(UIView.traitCollectionDidChange(_:)),
with: #selector(UIView.skeletonTraitCollectionDidChange(_:)),
inClass: UIView.self,
usingClass: UIView.self)
}
}

func unSwizzleTraitCollectionDidChange() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
DispatchQueue.removeOnce(token: "UIView.SkeletonView.swizzleTraitCollectionDidChange") {
swizzle(selector: #selector(UIView.skeletonTraitCollectionDidChange(_:)),
with: #selector(UIView.traitCollectionDidChange(_:)),
inClass: UIView.self,
usingClass: UIView.self)
}
DispatchQueue.removeOnce(token: "UIView.SkeletonView.swizzleTraitCollectionDidChange") {
swizzle(selector: #selector(UIView.skeletonTraitCollectionDidChange(_:)),
with: #selector(UIView.traitCollectionDidChange(_:)),
inClass: UIView.self,
usingClass: UIView.self)
}
}

}

0 comments on commit 50ce477

Please sign in to comment.