in iOS16, UIHostingConfiguration was newly introduced.
I tired to using it but meet a problems of margin. I did not configure margin but that struct default values have a margin. (not sure, but depend on size...)
so I add like this.
UIHostingConfiguration {
ContentView()
}
.margin(.all, 0)
this code works well.
but I want to make a new init or new struct for removing
.margin(.all, 0)
< --- this line.
I tired like bottom
extension UIHostingConfiguration {
static func noMargin<Content: View>(content: @ViewBuilder () -> Content) -> UIHostingConfiguration {
return UIHostingConfiguration(content: content)
.margins(.all, 0)
}
}
but it comes out error like this.
Cannot convert value of type '() -> Content' to expected argument type '() -> Content'
please tell me is there any good idea.
Notice that UIHostingConfiguration
has two generic type parameters - Content
and Background
The initialiser of UIHostingConfiguration
you are using requires that Background
is EmptyView
, i.e. the initialiser creates a configuration with no background. The background can be set later with the background
modifier.
If you call this initialiser without specifying type parameters, you are implicitly using Self.Content
and Self.Background
, and since you did not constrain Self.Background
, it could be any View
. For example, if I did:
UIHostingConfiguration<Text, Rectangle>.noMargins { ... }
then Self.Background
would be Rectangle
!
You can constrain Self.Background
to fix this issue:
extension UIHostingConfiguration where Background == EmptyView
The consequence of implicitly using Self.Content
is that Self.Content
could be different from the Content
type parameter of the noMargins
method, which is why you get the seemingly nonsense "cannot convert from () -> Content
to () -> Content
" error. It's actually saying "cannot convert from () -> Content
to () -> Self.Content
".
To fix this, simply remove the Content
type parameter from noMargins
. Then the content
view builder parameter would be of type () -> Self.Content
.
extension UIHostingConfiguration where Background == EmptyView {
static func noMargin(@ViewBuilder content: () -> Content) -> UIHostingConfiguration {
return UIHostingConfiguration<Content, EmptyView>(content: content)
.margins(.all, 0)
}
}
Note that explicitly specifying the initialiser's type arguments also works, but then the caller of noMargins
would also need to specify the type arguments of UIHostingConfiguration
, since there is no other way to infer what Content
and Background
should be on the caller's side.
extension UIHostingConfiguration {
static func noMargin<Content: View>(@ViewBuilder content: () -> Content) -> UIHostingConfiguration<Content, EmptyView> {
return UIHostingConfiguration<Content, EmptyView>(content: content)
.margins(.all, 0)
}
}
Caller:
// Caller needs to put two random views as the type parameter. Anything will work.
UIHostingConfiguration<Text, Spacer>.noMargin {
...
}