菜鸟教程小白 发表于 2022-12-11 19:33:02

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


                                            <p><p>我正在使用 Daniel Gindi 的图表库(iOS 图表),为了简单起见,我使用自定义 UIView 来存储图 TableView (作为 ChartViewBase)。我有一个 ViewController 类的类层次结构,其中叶类具有对 UIView 的引用,其中包含 ChartViewBase。问题是图表拒绝显示,我得到的只是图表应该在的黑色矩形。我想代码可能是最有用的,所以这里什么都没有:<br/>
通用 UIView 图表持有类:</p>

<pre><code>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(&#34;GenericChartView&#34;, owner: self, options: nil)
    self.addSubview(self.view)
    chart.delegate = self
}
override init(frame: CGRect)
{
    super.init(frame: frame)
    Bundle.main.loadNibNamed(&#34;GenericChartView&#34;, 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

}
}
</code></pre>

<p>现在是基本图 TableViewController :</p>

<pre><code>class ChartViewControllerBase: UIViewController
{

var myColors : = []
//var bounds : CGRect!
override func viewDidLoad() {
    super.viewDidLoad()
    let sessionCount = ShareData.sharedInstance.currentSessionNumber
    //NotificationCenter.default.addObserver(self, selector: &#34;rotated&#34;, 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 = &#34;Session &#34; + &#34;\(sessionCount)&#34; + &#34; Results - &#34; + myName

      myChartView.setHeader(header: myTitle)
    }

    //chartOriginalBounds = chart.bounds
    if let resultChoice = ShareData.sharedInstance.sessionDataObjectContainer]?.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() -&gt; GenericChartView
{
    return GenericChartView(frame: self.view.bounds)
}

func getChartObject() -&gt; ChartViewBase
{
    return ChartViewBase()
}

func makeChart(resultChoice: chartData)
{

}

func getColors(value: Double)
{

}

func getChartDataEntry(xval: Double, yval: Double) -&gt; ChartDataEntry
{
    return ChartDataEntry(x: xval, y: yval)
}
}
</code></pre>

<p>现在 LineAndBarChart 代码:</p>

<pre><code>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() -&gt; ChartViewBase
{
    return ChartViewBase()
}
var yAxis: YAxis!

func setYAxisFormatter() {

}

func createSet(myEntries: )
{

}



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(&lt;#T##keyedValues: ###&gt;)
    yAxis = chart.leftAxis
    chart.rightAxis.enabled = false
    chart.legend.enabled = true
    yAxis.granularity = 1.0
    yAxis.drawGridLinesEnabled = false
    var counter = 1.0
    var myEntries : = []

    var myXValues : = []


    if !resultChoice.plotPoints.isEmpty
    {
      for var item in resultChoice.plotPoints
      {
            let timeString : String =
                {
                  let formatter = DateFormatter()
                  formatter.dateFormat = &#34;h:mm a&#34;
                  formatter.amSymbol = &#34;AM&#34;
                  formatter.pmSymbol = &#34;PM&#34;
                  return formatter.string(from: item.xValue)
            }()
            myXValues.append(timeString)
            /*if(item.showXValue)
             {
             myXValues.append(timeString)
             }
             else
             {
             myXValues.append(&#34;&#34;)
             }*/
            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:

init(values: ) {
    self.mValues = values;
}


func stringForValue( _ value: Double, axis: AxisBase?) -&gt; String
{
    // &#34;value&#34; represents the position of the label on the axis (x or y)
    let myVal: Int = Int(value)
    if (myVal &lt; mValues.count)
    {
      return mValues;
    }
    else
    {
      return &#34;ERROR&#34;
    }
}
}
</code></pre>

<p>然后是条形图基础代码:</p>

<pre><code>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: )
{
    let chart = getChartObject() as! BarChartView
    let mySet = BarChartDataSet(values: myEntries, label: &#34;Values&#34;)
    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) -&gt; ChartDataEntry
{
    return BarChartDataEntry(x: xval, y: yval)
}
}
</code></pre>

<p>最后,叶(最派生类)代码:</p>

<pre><code>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() -&gt; GenericChartView
{
    return chartView
}

override func getChartObject() -&gt; 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: &#34;Line Chart&#34;, style: UIAlertActionStyle.default)
    { (alertAction: UIAlertAction!) -&gt; Void in
      self.navigationController?.popViewController(animated: false)
       let viewControllerStoryboardId = &#34;LineChartDisplayViewController&#34;
      let storyboardName = &#34;Main&#34;
      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?) -&gt; String {
    var returnVal = &#34;\(Int(value))&#34;

    return returnVal
}
}
</code></pre>

<p>我确实有几个问题。你是让 UIView 成为 ChartViewDelegate,还是应该是持有持有图表对象的 UIView 的 ViewController ?我错过了什么明显的东西吗?我以前使用过自定义 UIView,所以我知道该代码是正确的(除了该类是否应该是 ChartViewDelegate 之外,即我不知道)。是的,我确实需要所有这些类(class),因为我将来会有很多很多图表类型。无论如何,任何关于我可以做些什么来显示图表的建议都会很棒。</p>

<p>谢谢,<br/>
肖恩</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我也在使用 Charts 库。我不确定我是否完全理解您的限制,但我能够在自定义 UIView 中包含图表。我有其他方法(未显示)将实际数据从 ViewController 传递给标签和图表。 </p>

<p>我是这样做的:</p>

<pre><code>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(&#34;init(coder:) has not been implemented&#34;)
}

// MARK: - Setup Methods

func setupLabels() {
    let lbls =
    for lbl in lbls {
      lbl.label.font = UIFont.preferredFont(forTextStyle: .title3)
      lbl.translatesAutoresizingMaskIntoConstraints = false
      lbl.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }
    let pies =
    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 = [&#34;Jan&#34;, &#34;Feb&#34;, &#34;Mar&#34;, &#34;Apr&#34;, &#34;May&#34;, &#34;Jun&#34;]
    let unitsSold =

    setChart(dataPoints: months, values: unitsSold)
}

func setChart(dataPoints: , values: ) {

    var dataEntries: = []

    for i in 0..&lt;dataPoints.count {
      let dataEntry = ChartDataEntry(x: values, y: Double(i))
      dataEntries.append(dataEntry)
    }

    let set = PieChartDataSet(values: dataEntries, label: &#34;Results&#34;)
    set.drawIconsEnabled = false
    set.sliceSpace = 2


    set.colors = ChartColorTemplates.joyful()
      + ChartColorTemplates.colorful()
      + ChartColorTemplates.liberty()
      + ChartColorTemplates.pastel()
      +

    let data = PieChartData(dataSet: set)
    let pies =
    for pie in pies {
      pie.data = data
    }

}



func setupStack(){
    setupFake()
    setupLabels()
    let dashStack = UIStackView(arrangedSubviews: )
    dashStack.axis = .horizontal
    dashStack.distribution = .fillEqually
    dashStack.alignment = .center
    dashStack.spacing = 0
    dashStack.translatesAutoresizingMaskIntoConstraints = false


    let stackView = UIStackView(arrangedSubviews: )
    stackView.axis = .vertical
    stackView.distribution = .fill
    stackView.alignment = .fill
    stackView.spacing = 0
    stackView.translatesAutoresizingMaskIntoConstraints = false

    self.addSubview(stackView)
    //autolayout the stack view
    stackView.spanSuperView()
}
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 无法让图表对象在自定义 UIView 中工作,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/43554368/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/43554368/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 无法让图表对象在自定义 UIView 中工作