Created
May 14, 2020 04:26
-
-
Save wotjd/00a4aeb4961f1e32b74a5d7918a3a034 to your computer and use it in GitHub Desktop.
resolve sizeThatFits not working on Xcode Preview using UIView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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