【发布时间】:2017-04-22 01:50:26
【问题描述】:
我正在使用 Daniel Gindi 的图表库(iOS 图表),为了简单起见,我使用自定义 UIView 来存储图表视图(作为 ChartViewBase)。我有一个视图控制器类的类层次结构,其中叶类具有对 UIView 的引用,其中包含 ChartViewBase。问题是图表拒绝显示,我得到的只是图表应该在的黑色矩形。我想代码可能是最有用的,所以这里什么都没有:
通用 UIView 图表持有类:
import UIKit
import Charts
protocol GenericChartViewDelegate: class {
func backButtonTapped()
func switchChartButtonTapped()
func finalizeResultsButtonTapped()
}
class GenericChartView: UIView, ChartViewDelegate
{
@IBOutlet weak var headerDisplay: UIButton!
@IBOutlet var view: UIView!
weak var delegate: GenericChartViewDelegate?
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
Bundle.main.loadNibNamed("GenericChartView", owner: self, options: nil)
self.addSubview(self.view)
chart.delegate = self
}
override init(frame: CGRect)
{
super.init(frame: frame)
Bundle.main.loadNibNamed("GenericChartView", owner: self, options: nil)
self.addSubview(self.view)
chart.delegate = self
}
@IBOutlet var chart: ChartViewBase!
@IBAction func BackButton(_ sender: UIButton) {
delegate?.backButtonTapped()
}
@IBAction func SwitchChartButton(_ sender: UIButton) {
delegate?.switchChartButtonTapped()
}
@IBAction func FinalizeResultsButton(_ sender: UIButton) {
delegate?.finalizeResultsButtonTapped()
}
func setHeader(header: String)
{
headerDisplay.setTitle(header, for: UIControlState.normal)
headerDisplay.layer.cornerRadius = MyVariables.borderCurvature
headerDisplay.titleLabel?.adjustsFontSizeToFitWidth = true
}
}
现在是基本图表视图控制器:
class ChartViewControllerBase: UIViewController
{
var myColors : [NSUIColor] = []
//var bounds : CGRect!
override func viewDidLoad() {
super.viewDidLoad()
let sessionCount = ShareData.sharedInstance.currentSessionNumber
//NotificationCenter.default.addObserver(self, selector: "rotated", name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
createChart()
var myBase = getChartObject()
var myChartView = getChartDisplayView()
setDelegate()
if let myName = ShareData.sharedInstance.currentAccount.name {//sessionName.characters.last!
let myTitle = "Session " + "\(sessionCount)" + " Results - " + myName
myChartView.setHeader(header: myTitle)
}
//chartOriginalBounds = chart.bounds
if let resultChoice = ShareData.sharedInstance.sessionDataObjectContainer[ShareData.sharedInstance.currentAccountSessionNames[sessionCount - 1]]?.chartInfo
{
makeChart(resultChoice: resultChoice)
}
// Do any additional setup after loading the view.
}
func setDelegate()
{
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createChart()
{
}
func getChartDisplayView() -> GenericChartView
{
return GenericChartView(frame: self.view.bounds)
}
func getChartObject() -> ChartViewBase
{
return ChartViewBase()
}
func makeChart(resultChoice: chartData)
{
}
func getColors(value: Double)
{
}
func getChartDataEntry(xval: Double, yval: Double) -> ChartDataEntry
{
return ChartDataEntry(x: xval, y: yval)
}
}
现在 LineAndBarChart 代码:
class LineAndBarChartViewControllerBase: ChartViewControllerBase {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func getChartObject() -> ChartViewBase
{
return ChartViewBase()
}
var yAxis: YAxis!
func setYAxisFormatter() {
}
func createSet(myEntries: [ChartDataEntry])
{
}
override func makeChart(resultChoice: chartData)
{
let chart = getChartObject() as! BarLineChartViewBase
chart.chartDescription?.enabled = false
chart.drawGridBackgroundEnabled = false
chart.dragEnabled = true
chart.setScaleEnabled(true)
chart.pinchZoomEnabled = true
let xAxis = chart.xAxis
xAxis.labelPosition = XAxis.LabelPosition.bottom
chart.rightAxis.enabled = false
xAxis.drawGridLinesEnabled = false
xAxis.drawAxisLineEnabled = true
xAxis.granularity = 1.0
//xAxis.setValuesForKeys(<#T##keyedValues: [String : Any]##[String : Any]#>)
yAxis = chart.leftAxis
chart.rightAxis.enabled = false
chart.legend.enabled = true
yAxis.granularity = 1.0
yAxis.drawGridLinesEnabled = false
var counter = 1.0
var myEntries : [ChartDataEntry] = []
var myXValues : [String] = []
if !resultChoice.plotPoints.isEmpty
{
for var item in resultChoice.plotPoints
{
let timeString : String =
{
let formatter = DateFormatter()
formatter.dateFormat = "h:mm a"
formatter.amSymbol = "AM"
formatter.pmSymbol = "PM"
return formatter.string(from: item.xValue)
}()
myXValues.append(timeString)
/*if(item.showXValue)
{
myXValues.append(timeString)
}
else
{
myXValues.append("")
}*/
let myEntry = getChartDataEntry(xval: counter, yval: Double(item.yValue))
getColors(value: myEntry.y)
counter += 1
myEntries.append(myEntry)
}
let myFormatter = MyXAxisValueFormatter(values: myXValues)
xAxis.valueFormatter = myFormatter
setYAxisFormatter()
createSet(myEntries: myEntries)
}
}
}
class MyXAxisValueFormatter: NSObject, IAxisValueFormatter {
var mValues: [String]
init(values: [String]) {
self.mValues = values;
}
func stringForValue( _ value: Double, axis: AxisBase?) -> String
{
// "value" represents the position of the label on the axis (x or y)
let myVal: Int = Int(value)
if (myVal < mValues.count)
{
return mValues[myVal];
}
else
{
return "ERROR"
}
}
}
然后是条形图基础代码:
class BarChartViewControllerBase: LineAndBarChartViewControllerBase {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func createChart()
{
var myChart = getChartDisplayView()
myChart.chart = BarChartView(frame: myChart.chart.contentRect)
}
override func createSet(myEntries: [ChartDataEntry])
{
let chart = getChartObject() as! BarChartView
let mySet = BarChartDataSet(values: myEntries, label: "Values")
mySet.colors = myColors
mySet.valueColors = myColors
setValueFormatter(set: mySet)
let myBarChartData = BarChartData(dataSet: mySet)
myBarChartData.barWidth = 0.8
chart.data = myBarChartData
}
func setValueFormatter(set: BarChartDataSet)
{
}
override func getChartDataEntry(xval: Double, yval: Double) -> ChartDataEntry
{
return BarChartDataEntry(x: xval, y: yval)
}
}
最后,叶(最派生类)代码:
class DerivedClassChartViewController: BarChartViewControllerBase, GenericChartViewDelegate
{
@IBOutlet weak var chartView: GenericChartView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func getChartDisplayView() -> GenericChartView
{
return chartView
}
override func getChartObject() -> ChartViewBase
{
return chartView.chart
}
override func getColors(value: Double)
{
if (value == 0.0)
{
myColors.append(UIColor.black)
}
else if (value == 1.0)
{
myColors.append(MyVariables.colorOne)
}
else if (value == 2.0)
{
myColors.append(MyVariables.colorTwo)
}
else if (value == 3.0)
{
myColors.append(MyVariables.colorThree)
}
else if (value == 4.0)
{
myColors.append(MyVariables.colorFour)
}
else if (value == 5.0)
{
myColors.append(MyVariables.colorFive)
}
}
func backButtonTapped()
{
self.navigationController?.popViewController(animated: false)
}
func switchChartButtonTapped()
{
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
let goToLineChartAction = UIAlertAction(title: "Line Chart", style: UIAlertActionStyle.default)
{ (alertAction: UIAlertAction!) -> Void in
self.navigationController?.popViewController(animated: false)
let viewControllerStoryboardId = "LineChartDisplayViewController"
let storyboardName = "Main"
let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
let viewController = storyboard.instantiateViewController(withIdentifier: viewControllerStoryboardId)
self.navigationController?.pushViewController(viewController, animated: false)
}
alertController.addAction(goToLineChartAction)
alertController.view.tintColor = UIColor.black
present(alertController, animated: true, completion: nil)
let presentationController = alertController.popoverPresentationController
presentationController?.sourceView = self.view
presentationController?.sourceRect = CGRect(x: 330, y: 210, width: 330, height: 210)
}
func finalizeResultsButtonTapped()
{
}
override func setDelegate()
{
chartView.delegate = self
}
override func setValueFormatter(set: BarChartDataSet)
{
set.valueFormatter = DerivedClassNumberFormatter()
}
}
class DerivedClassNumberFormatter: NSObject, IValueFormatter {
func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String {
var returnVal = "\(Int(value))"
return returnVal
}
}
我确实有几个问题。你是让 UIView 成为 ChartViewDelegate,还是应该是持有持有图表对象的 UIView 的视图控制器?我错过了什么明显的东西吗?我以前使用过自定义 UIView,所以我知道该代码是正确的(除了该类是否应该是 ChartViewDelegate 之外,即我不知道)。是的,我确实需要所有这些课程,因为我将来会有很多很多图表类型。无论如何,任何关于我可以做些什么来显示图表的建议都会很棒。
谢谢,
肖恩
【问题讨论】:
-
嗨,肖恩。我有same problem。你解决了吗?请帮帮我好吗?
-
在不知道您的代码与我的代码有多接近的情况下,我不知道此解决方案是否适合您,但我所做的是我将 GenericChartView 设为抽象类并将变量设置为 BarChartView 或 LineChartView派生类,而不是在视图控制器中进行。这有意义吗?这意味着添加两个或三个新类(取决于您的代码代表多少图表类型),它们仅用于根据需要构建 BarChartView、LineChartView 或 PieChartView。希望这对您有所帮助,因为如果我没记错的话,它确实解决了我的问题。
标签: ios swift3 charts uiview ios-charts