Skip to content

Instantly share code, notes, and snippets.

@wotjd
Created May 14, 2020 04:26
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wotjd/00a4aeb4961f1e32b74a5d7918a3a034 to your computer and use it in GitHub Desktop.
Save wotjd/00a4aeb4961f1e32b74a5d7918a3a034 to your computer and use it in GitHub Desktop.
resolve sizeThatFits not working on Xcode Preview using UIView
import SwiftUI
// https://medium.com/@lyeskinnikitaalexandrovich/mastering-xcode-previews-with-snapkit-uikit-aa82a146059a
enum DebugPreviewLayout {
case fitWidth(CGFloat)
case fitHeight(CGFloat)
case `default`
}
final class DebugPreviewLayoutView: UIView {
private let childView: UIView
private let previewLayout: DebugPreviewLayout
private var childIntrinsicContentSize: CGSize? = nil
override var intrinsicContentSize: CGSize {
self.childIntrinsicContentSize ?? super.intrinsicContentSize
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(previewLayout: DebugPreviewLayout, view: UIView) {
self.childView = view
self.previewLayout = previewLayout
super.init(frame: .zero)
self.configureUI()
self.childIntrinsicContentSize = self.calculateChildSize()
}
override func invalidateIntrinsicContentSize() {
self.childIntrinsicContentSize = self.calculateChildSize()
}
private func configureUI() {
self.addSubview(self.childView)
self.translatesAutoresizingMaskIntoConstraints = false
self.childView.translatesAutoresizingMaskIntoConstraints = false
self.childView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}
private func calculateChildSize() -> CGSize {
var width = CGFloat.greatestFiniteMagnitude
var height = CGFloat.greatestFiniteMagnitude
var horizontalFittingPriority = UILayoutPriority.fittingSizeLevel
var verticalFittingPriority = UILayoutPriority.fittingSizeLevel
switch previewLayout {
case let .fitHeight(value):
height = value
verticalFittingPriority = .required
case let .fitWidth(value):
width = value
horizontalFittingPriority = .required
default:
break
}
return self.childView.systemLayoutSizeFitting(
CGSize(width: width, height: height),
withHorizontalFittingPriority: horizontalFittingPriority,
verticalFittingPriority: verticalFittingPriority
)
}
}
struct DebugPreviewView<T: UIView>: UIViewRepresentable {
private let previewLayout: DebugPreviewLayout
private let viewBuilder: () -> T
init(
previewLayout: DebugPreviewLayout = .default,
_ builder: @escaping () -> T
) {
self.previewLayout = previewLayout
self.viewBuilder = builder
}
// MARK: - UIViewRepresentable
func makeUIView(context: Context) -> UIView {
DebugPreviewLayoutView(
previewLayout: self.previewLayout,
view: self.viewBuilder()
).then {
$0.invalidateIntrinsicContentSize()
}
}
func updateUIView(_ view: UIView, context: Context) {
view.setContentHuggingPriority(.defaultHigh, for: .vertical)
view.setContentHuggingPriority(.defaultHigh, for: .horizontal)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment