如何使我的SwiftUI包装器在所有iOS版本上都尊重UIView的大小?

huangapple go评论42阅读模式
英文:

How can I make my SwiftUI wrapper respect UIView size across all iOS versions?

问题

我目前正在开发一个用于包装 UIViewUIViewControllerSwiftUI包装器,我的目标是使该包装器尊重UIView的大小和约束

到目前为止,我已成功实现了UIViewRepresentable协议的sizeThatFits方法,并且它按预期工作。以下是我当前的大小计算实现:

func sizeThatFits(_ width: CGFloat?, _ height: CGFloat?) -> CGSize? {
	let intrinsicContentSize = self.intrinsicContentSize
	let targetSize = CGSize(
		width: width ?? intrinsicContentSize.width,
		height: height ?? intrinsicContentSize.height
	)
	guard targetSize.width != UIView.noIntrinsicMetric, targetSize.height != UIView.noIntrinsicMetric else {
		return nil
	}
	let horizontalPriority: UILayoutPriority = width == nil ? .defaultLow : .defaultHigh
	let verticalPriority: UILayoutPriority = height == nil ? .defaultLow : .defaultHigh
	return systemLayoutSizeFitting(
		targetSize,
		withHorizontalFittingPriority: horizontalPriority,
		verticalFittingPriority: verticalPriority
	)
}

然而,此方法仅在iOS 16及更高版本中可用。我的目标是在所有iOS版本上提供相同的功能。

对于如何实现这一目标的任何建议或想法,我将不胜感激。谢谢!我尝试过各种约束、内容压缩/拉伸优先级和类似问题答案中建议的fixedSize,但尚未取得令人满意的结果。

英文:

I'm currently working on a SwiftUI wrapper for UIView and UIViewController, and my aim is to make this wrapper respect the size of the UIView and constraints.

For now, I have successfully implemented the sizeThatFits method from the UIViewRepresentable protocol, and it's working as expected. Here's my current implementation of size calculating:

func sizeThatFits(_ width: CGFloat?, _ height: CGFloat?) -> CGSize? {
	let intrinsicContentSize = self.intrinsicContentSize
	let targetSize = CGSize(
		width: width ?? intrinsicContentSize.width,
		height: height ?? intrinsicContentSize.height
	)
	guard targetSize.width != UIView.noIntrinsicMetric, targetSize.height != UIView.noIntrinsicMetric else {
		return nil
	}
	let horizontalPriority: UILayoutPriority = width == nil ? .defaultLow : .defaultHigh
	let verticalPriority: UILayoutPriority = height == nil ? .defaultLow : .defaultHigh
	return systemLayoutSizeFitting(
		targetSize,
		withHorizontalFittingPriority: horizontalPriority,
		verticalFittingPriority: verticalPriority
	)
}

However, this method is only available from iOS 16 onwards. My goal is to provide the same functionality across all iOS versions.

Any suggestions or ideas on how to accomplish this would be greatly appreciated. Thank you!

I have experimented with various constraints, content compression/hugging priorities and fixedSize as suggested in answers to similar questions here, but I have yet to achieve satisfying results.

答案1

得分: 0

经过大量实验,我发现在计算视图大小时,SwiftUI 只参考 intrinsicContentSize 属性,而这个属性本身不考虑所需的大小(例如,对于 UILabel,它仅取决于文本),因此没有简单的方法可以正确调整视图的大小以满足所需大小,同时考虑其内容和约束。\

因此,答案是没有继承和覆盖 intrinsicContentSize 是不可能的。

P.S. 我成功找到了一些 技巧,并通过视图包装器在 这里 获得了所需的结果。\

我无法在此提供详细的代码示例,因为它非常庞大(包含多个类和结构体)。

英文:

After a lot of experimentation, I found out that when calculating the size of a view, SwiftUI only refers to intrinsicContentSize property, which in turn does not take into account the desired size (for example, for a UILabel it depends only on the text), so there is no easy way to correctly adjust the size of the view to the desired one, taking into account its content and constraints.
So the answer is it's not possible without inheritance and overriding intrinsicContentSize.

P.S. I managed to find some hacks and got the desired result with view wrappers here.
I can't provide a detailed code example here as it is quite large (multiple classes and structs).

huangapple
  • 本文由 发表于 2023年5月29日 17:05:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355993.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定