I am encountering the following strange behaviour in SwiftUI. Assume these definitions:
Should not all three methods behave equivalently? I know that internally they return different view types, but that shouldn't make a difference for the user, shouldn't it? In particular, consider the following situation:
This behaves as expected, when for example running this on MacCatalyst and resizing the window with just a YellowBoard in it, the board adapts to the sizes. But when using fitCardAspectRatio2 or fitCardAspectRatio3 instead in the definition of YellowCard, the board will not adapt its size but just keep its initial size.
That surely is a bug? Or is this behaviour somehow to be expected?
Code Block Swift import SwiftUI let cardAspectRatio : CGSize? = CGSize(width: 63, height: 88) extension View { @ViewBuilder func fitCardAspectRatio1() -> some View { let ratio = cardAspectRatio! self.aspectRatio(ratio, contentMode: .fit) } @ViewBuilder func fitCardAspectRatio2() -> some View { if let ratio = cardAspectRatio { self.aspectRatio(ratio, contentMode: .fit) } else { fatalError() } } func fitCardAspectRatio3() -> some View { let ratio = cardAspectRatio! return AnyView(self.aspectRatio(ratio, contentMode: .fit)) } }
Should not all three methods behave equivalently? I know that internally they return different view types, but that shouldn't make a difference for the user, shouldn't it? In particular, consider the following situation:
Code Block struct YellowCard : View { @ViewBuilder var body : some View { Color.yellow.border(Color.blue).fitCardAspectRatio1() } } struct YellowBoard : View { private func cardView(size: CGSize) -> some View { return YellowCard().frame(width: size.width, height: size.height) } private func computeDimensions(_ size : CGSize) -> (card : CGSize, size : CGSize) { let ratio = aspectRatio() let factor = min(size.width / ratio.width, size.height / ratio.height) let size = CGSize(width: factor * ratio.width, height: factor * ratio.height) let cardWidth = size.width / 3 let cardHeight = size.height / 2 let card = CGSize(width: cardWidth, height: cardHeight) return (card: card, size: size) } var body : some View { GeometryReader { geom in let dims = computeDimensions(geom.size) VStack(spacing: 0) { HStack(spacing: 0) { ForEach(0 ..< 3) { _ in cardView(size: dims.card) } } HStack(spacing: 0) { ForEach(3 ..< 5) { _ in cardView(size: dims.card) } } } }.aspectRatio(aspectRatio(), contentMode: .fit) } func aspectRatio() -> CGSize { let card = cardAspectRatio! let width = 3 * card.width let height = 2 * card.height return CGSize(width: width, height: height) } }
This behaves as expected, when for example running this on MacCatalyst and resizing the window with just a YellowBoard in it, the board adapts to the sizes. But when using fitCardAspectRatio2 or fitCardAspectRatio3 instead in the definition of YellowCard, the board will not adapt its size but just keep its initial size.
That surely is a bug? Or is this behaviour somehow to be expected?