我正在使用 Daniel Gindi 的图表库(iOS 图表),为了简单起见,我使用自定义 UIView 来存储图 TableView (作为 ChartViewBase)。我有一个 View Controller 类的类层次结构,其中叶类具有对 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
}
}
现在是基本图 TableView Controller :
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 = "M"
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 的 View Controller ?我错过了什么明显的东西吗?我以前使用过自定义 UIView,所以我知道该代码是正确的(除了该类是否应该是 ChartViewDelegate 之外,即我不知道)。是的,我确实需要所有这些类(class),因为我将来会有很多很多图表类型。无论如何,任何关于我可以做些什么来显示图表的建议都会很棒。
谢谢,
肖恩
Best Answer-推荐答案 strong>
我也在使用 Charts 库。我不确定我是否完全理解您的限制,但我能够在自定义 UIView 中包含图表。我有其他方法(未显示)将实际数据从 View Controller 传递给标签和图表。
我是这样做的:
import UIKit
import Charts
class MyHeader: UIView, ChartViewDelegate {
// My Header is the top view of the ViewController
// It gives summary information for the user
// MARK: - Properties
var firstLabel = LabelView()
var secondLabel = LabelView()
var firstPie = PieChartView()
var secondPie = PieChartView()
var thirdPie = PieChartView()
let nformatter = NumberFormatter()
// MARK: - LifeCycle
override func awakeFromNib() {
super.awakeFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.white.withAlphaComponent(0.5)
setupStack()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder has not been implemented")
}
// MARK: - Setup Methods
func setupLabels() {
let lbls = [firstLabel, secondLabel]
for lbl in lbls {
lbl.label.font = UIFont.preferredFont(forTextStyle: .title3)
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
let pies = [firstPie, secondPie, thirdPie]
for pie in pies {
pie.translatesAutoresizingMaskIntoConstraints = false
pie.heightAnchor.constraint(equalToConstant: 100).isActive = true
pie.spanSuperView() // spanSuperView is a UIView extension that I use
pie.delegate = self as ChartViewDelegate
// entry label styling
pie.entryLabelColor = .white
pie.entryLabelFont = .systemFont(ofSize: 12, weight: .light)
pie.animate(xAxisDuration: 1.4, easingOption: .easeOutBack)
}
}
func setupFake() {
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0]
setChart(dataPoints: months, values: unitsSold)
}
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(x: values[i], y: Double(i))
dataEntries.append(dataEntry)
}
let set = PieChartDataSet(values: dataEntries, label: "Results")
set.drawIconsEnabled = false
set.sliceSpace = 2
set.colors = ChartColorTemplates.joyful()
+ ChartColorTemplates.colorful()
+ ChartColorTemplates.liberty()
+ ChartColorTemplates.pastel()
+ [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)]
let data = PieChartData(dataSet: set)
let pies = [firstPie, secondPie, thirdPie]
for pie in pies {
pie.data = data
}
}
func setupStack(){
setupFake()
setupLabels()
let dashStack = UIStackView(arrangedSubviews: [firstPie, secondPie, thirdPie])
dashStack.axis = .horizontal
dashStack.distribution = .fillEqually
dashStack.alignment = .center
dashStack.spacing = 0
dashStack.translatesAutoresizingMaskIntoConstraints = false
let stackView = UIStackView(arrangedSubviews: [firstLabel, secondLabel, dashStack])
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
stackView.spacing = 0
stackView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(stackView)
//autolayout the stack view
stackView.spanSuperView()
}
}
关于ios - 无法让图表对象在自定义 UIView 中工作,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/43554368/
|