Core Plot饼图不显示问题排查(Xcode 9环境)
结合你的代码和Xcode 9(对应Swift 4.x)的环境,我整理了几个可能导致饼图不显示的原因和修复方案:
1. Swift版本兼容问题:废弃的C宏常量
在Swift 3及以后,苹果弃用了C语言的数学宏(比如M_PI_4),改用类型安全的Swift常量。你的代码里:
pieChart.startAngle = CGFloat(M_PI_4)
这行在Xcode 9中可能会导致编译警告甚至运行时计算错误,替换为Swift原生常量即可:
pieChart.startAngle = CGFloat.pi / 4
2. Core Data数据加载逻辑问题
你的categories属性的didSet里调用了CoreDataHelper.retrieveCategories(),但在viewDidLoad中又直接赋值self.categories = CoreDataHelper.retrieveCategories(),这会导致重复加载数据,甚至可能让categoryTotals计算错误。另外,如果所有categoryTotals的值都是0,你的代码会把切片填充设为黑色,且标签为空,饼图会和背景融合看起来像空白。
修复方案:
- 移除
categories的didSet逻辑,避免重复加载:
var categories = [Category]()
- 在
viewDidLoad中调整执行顺序并优化数据计算:
override func viewDidLoad() { super.viewDidLoad() // 注意:super调用必须放在最前面,原代码顺序错误会导致视图初始化异常 guard let collectionName = collection else { print("Collection name is nil") return } self.categories = CoreDataHelper.retrieveCategories() categoryTotals = categories.map { category in ExpensesAdditions().retrieveCategoryAnalysis(collectionName: collectionName, category: String(describing: category)) } print(categoryTotals) }
3. 视图生命周期方法的错误调用
你的viewDidAppear和viewWillAppear方法中,调用super时传入了固定的false,而不是参数animated:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(false) // 错误 }
应该改为:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) }
同理修复viewWillAppear方法,虽然这不一定直接导致饼图不显示,但会影响视图生命周期的正常执行。
4. 饼图标签格式化错误
你的dataLabel方法中,字符串格式化的写法有误:
let layer = CPTTextLayer(text: String(format: name, value))
这里name被当作格式字符串使用,会导致显示异常。正确的格式化方式应该是:
let layer = CPTTextLayer(text: String(format: "%@: %@", name, value))
这样才能正确显示分类名称和对应的金额。
5. 重复添加饼图的风险
viewDidLayoutSubviews会被多次调用(比如旋转屏幕、视图大小变化时),每次调用都会执行initPlot(),而configureChart()中会创建新的CPTPieChart并添加到graph上,这会导致多个饼图重叠,或者布局混乱。
修复方案:在initPlot()之前先移除graph上已有的饼图:
func initPlot() { // 先移除已有的饼图 hostView.hostedGraph?.plots.forEach { $0.removeFromSuperlayer() } configureHostView() configureGraph() configureChart() configureLegend() }
6. 确认Core Data数据是否有效
最后,检查categoryTotals的输出,如果所有值都是0,饼图会显示全黑的切片且无标签,看起来像空白。你可以在viewDidLoad中补充打印:
print("Categories count: \(categories.count)") print("Category totals: \(categoryTotals)")
如果数据为空或者全0,需要检查CoreDataHelper.retrieveCategories()和retrieveCategoryAnalysis的实现是否正确。
按照以上步骤修复后,应该能解决饼图不显示的问题。
内容的提问来源于stack exchange,提问作者Arnav GUPTA

