• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 无法让图表对象在自定义 UIView 中工作

[复制链接]
菜鸟教程小白 发表于 2022-12-11 19:33:02 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在使用 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-推荐答案


我也在使用 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/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap