You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Symbol协议绘制问题:Oval返回UIBezierPath而非Path的解决

解决SwiftUI中Symbol协议Oval实现的类型不匹配问题

你定义了继承自Shape的Symbol协议,要求drawing方法返回SwiftUI的Path类型,Rectangle和Diamond都正常实现,但Oval里用UIBezierPath创建图形导致类型不匹配,以下是可行的解决办法:

方法1:将UIBezierPath转换为SwiftUI Path

SwiftUI的Path支持直接通过UIBezierPath实例初始化,你可以先创建UIBezierPath,再转成Path,同时把椭圆移动到指定的center位置:

struct Oval: Symbol {
    var numberOfSymbols: SetGame.Card.Number
    
    func drawing(_ path: Path, center: CGPoint, width: CGFloat, height: CGFloat) -> Path {
        // 创建基于原点的椭圆UIBezierPath
        let bezierPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: width, height: height))
        // 转换为SwiftUI Path
        var ovalPath = Path(bezierPath.cgPath)
        // 将路径偏移到目标center位置
        ovalPath = ovalPath.offsetBy(dx: center.x - width/2, dy: center.y - height/2)
        // 合并传入的原始路径
        var combinedPath = path
        combinedPath.addPath(ovalPath)
        return combinedPath
    }
}

方法2:直接用SwiftUI Path创建椭圆(更推荐)

没必要依赖UIKit的UIBezierPath,SwiftUI的Path本身提供了创建椭圆的方法,直接用addEllipse(in:)更贴合SwiftUI生态:

struct Oval: Symbol {
    var numberOfSymbols: SetGame.Card.Number
    
    func drawing(_ path: Path, center: CGPoint, width: CGFloat, height: CGFloat) -> Path {
        var combinedPath = path
        // 计算基于center居中的椭圆矩形范围
        let ovalRect = CGRect(
            x: center.x - width/2,
            y: center.y - height/2,
            width: width,
            height: height
        )
        combinedPath.addEllipse(in: ovalRect)
        return combinedPath
    }
}

关于你考虑的函数重载

其实完全没必要用函数重载,协议明确要求drawing方法返回Path,重载会增加不必要的复杂度,上面两种方法都能直接满足协议要求,代码更简洁易懂。

内容的提问来源于stack exchange,提问作者cs-moushuai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:05:26