问题描述
在SwiftUI中,我尝试给自定义的TabView分页指示器添加stroke描边效果,因为如果不添加描边效果的话,白色的圆圈不会显示。

当我给Circle()添加stroke时,发现Xcode预览存在报错。
Circle()
.fill(index == selectedIndex ? Color.white : Color.gray)
.stroke(Color.gray, lineWidth: 1) // 这行是问题关键
.frame(width: 8, height: 8)

经过排查了解到,报错是因为错误使用了.fill()和.stroke()的组合方式,这就会导致Swift内部构建出错误或异常复杂的视图结构,从而让Xcode编译器严重卡顿甚至崩溃(尤其是在循环中频繁使用)。
问题主要的原因:fill(…) 和 stroke(…) 是用于 Shape(如 Circle())的修饰器,只能用其一,不能同时链式使用。
Circle()
.fill(...)
.stroke(...)
这个写法会构造出一个非法的视图层次结构:对一个已经“填充后(.fill())的视图”再添加描边(.stroke()),这是不合法的。
解决方案
使用overlay设置边框:
Circle()
.fill(index == selectedIndex ? Color.gray : Color.white)
.frame(width: 8, height: 8)
.overlay(
Circle()
.stroke(Color.gray, lineWidth: 1)
)
或者使用.background()和.stroke()分开写:
Circle()
.stroke(Color.gray, lineWidth: 1)
.background(
Circle().fill(index == selectedIndex ? Color.gray : Color.white)
)
.frame(width: 8, height: 8)
通过这两种方案,就可以实现填充和描边统一使用。

相关文章
SwiftUI绘制边框stroke和strokeBorder:https://fangjunyu.com/2024/12/15/swiftui%e7%bb%98%e5%88%b6%e8%be%b9%e6%a1%86stroke%e5%92%8cstrokeborder/