Хотите построить гистограмму с делегатом и источником данных с использованием протокола

#ios #swift #xcode

#iOS #swift #xcode

Вопрос:

Я пытаюсь создать одно представление гистограммы, чтобы создать делегат и источник данных для этого представления графика. Создание протокола для делегирования и источника данных для графика.

 protocol BarGraphDatasource{
    func grapgView(grapgView:BarGraph, numberOfItemsInGraph items:Int)->Int
    func grapgView(grapgView: BarGraph, didSelectItemAtIndex index: Int)
}
  

// Класс просмотра гистограммы выглядит следующим образом

 class BarGraph: UIScrollView {


    var  delegte: BarGraphDatasource! = nil{

        didSet{
            self.reloadGraph()
        }
    }

     var barWidth : CGFloat = 24 {

        didSet{
                self.reloadGraph()
        }
    }
    var minimumSpacing : CGFloat = 10 {

        didSet{
            self.reloadGraph()
        }
    }

    var numberOfItems : Int = 0 {
        didSet{
            self.reloadGraph()
        }
    }
     var barColor : UIColor = UIColor.lightGrayColor() {

        didSet{
            self.reloadGraph()
        }
    }



    init() {
        super.init(frame: CGRectZero)
        self.reloadGraph()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }
    func reloadGraph(){
        self.setContentSizeForGraph()
    }

    func setContentSizeForGraph() {

        if self.numberOfItems > 0 {
            self.contentSize = CGSizeMake((self.barWidth * CGFloat(self.numberOfItems)   self.minimumSpacing), self.frame.height);
            var xValue:CGFloat = 0
            for i in 1...self.numberOfItems {
                xValue = xValue   CGFloat(CGFloat(i)   self.minimumSpacing)
                print("xValue: (xValue)")
                let frame = CGRectMake(xValue, 0, self.barWidth, 50)
                let barView = UIView(frame: frame)
                barView.backgroundColor = self.barColor
                self.addSubview(barView)
            }
        }
    }
}
  

// Это мой класс ViewController

 class ViewController: UIViewController,BarGraphDatasource {

    @IBOutlet weak var grapView :  BarGraph?

    var arrayItems: NSArray = []

    override func viewDidLoad() {
        super.viewDidLoad()

        arrayItems = [1,2,3,4,5]
        grapView?.barWidth = 10;
        grapView?.delegte = self;

        grapView?.reloadGraph()
    }


    func grapgView(grapgView: BarGraph, numberOfItemsInGraph items: Int) -> Int {
        return arrayItems.count // how can i pass this value to the graph view from here       ******* 
    }  
    func grapgView(grapgView: BarGraph, didSelectItemAtIndex index: Int) {
        print(arrayItems[index]) // how can i call this method on click of bar view       ******* 
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}
  

// Здесь я не могу получить график и не вызываю методы протокола в классе ViewController

numberOfItemsInGraph когда мы устанавливаем это, я хочу передать это значение в гистограмму на графике

didSelectItemAtIndex как назначить действие выбранному элементу

Комментарии:

1. Вы говорите: «как я могу передать это значение в представление графика». Разве это не то, что return делает? Поскольку это метод делегирования, я бы ожидал, что он будет вызван из объекта, который ссылается на делегата.

Ответ №1:

Вам не нужно постоянно вызывать reloadGraph(). Когда вы назначаете делегирование, оно будет вызвано. И вы можете вызвать это явно позже.

2-й вы должны вызвать эти методы делегирования откуда-нибудь из класса BarGraph. Я изменил некоторые коды, пожалуйста, попробуйте это.

     import UIKit

protocol BarGraphDatasource{
    func grapgView(grapgView:BarGraph, numberOfItemsInGraph items:Int)->Int
    func grapgView(grapgView: BarGraph, didSelectItemAtIndex index: Int)
    func grapgView(grapgView: BarGraph, setHeightOfBarAtIndex index: Int)->CGFloat
}
// Bargraph View class is like below

class BarGraph: UIScrollView{


    var  delegte: BarGraphDatasource! = nil{

        didSet{
            self.reloadGraph()
        }
    }

    var barWidth : CGFloat = 24
    var minimumSpacing : CGFloat = 10
    var numberOfItems : Int = 0
    var barColor : UIColor = UIColor.lightGrayColor()
    var barViews : [UIButton] = []


    init() {
        super.init(frame: CGRectZero)
        self.reloadGraph()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }
    func reloadGraph(){
        numberOfItems = delegte!.grapgView(self, numberOfItemsInGraph: numberOfItems)
        self.setContentSizeForGraph()

    }

    func setContentSizeForGraph() {

        if self.numberOfItems > 0 {

            self.contentSize = CGSizeMake((self.barWidth * CGFloat(self.numberOfItems)   self.minimumSpacing), self.frame.height);
            var xValue:CGFloat = 0

            for i in 1...self.numberOfItems {
                xValue = xValue   CGFloat(CGFloat(i)   self.minimumSpacing   self.barWidth)
                print("xValue: (xValue)")
                let frame = CGRectMake(xValue, self.layer.frame.size.height-delegte.grapgView(self, setHeightOfBarAtIndex: i-1), self.barWidth, delegte.grapgView(self, setHeightOfBarAtIndex: i-1))
                let barView = UIButton(frame: frame)
                barView.backgroundColor = self.barColor
                barViews.append(barView)
                barView.addTarget(self, action: #selector(BarGraph.send_ButtonIndex(_:)), forControlEvents: UIControlEvents.TouchUpInside)
                self.addSubview(barView)
            }
        }
    }

    func send_ButtonIndex(barView : UIButton)
    {

        delegte!.grapgView(self, didSelectItemAtIndex: barViews.indexOf(barView)!)
    }

}
  

Это класс гистограммы с источником данных. Я реализовал один дополнительный метод делегирования для лучшего использования. И код Viewcontroller следующий.

     import UIKit

class ViewController: UIViewController,BarGraphDatasource {

    @IBOutlet weak var grapView :  BarGraph?

    var arrayItems: NSArray = []
    var heightOfBars: [CGFloat] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        arrayItems = [1,2,3,4,5]
        heightOfBars = [20,30,25,60,40]
        grapView?.barWidth = 20;
        grapView?.barColor = UIColor.brownColor()
        grapView?.minimumSpacing = 15;
        grapView?.delegte = self;
    }


    func grapgView(grapgView: BarGraph, numberOfItemsInGraph items: Int) -> Int {
        return arrayItems.count //pass this value to the graph view from here       *******
    }
    func grapgView(grapgView: BarGraph, didSelectItemAtIndex index: Int) {
        print(arrayItems[index]) //call this method on click of bar view       *******
    }

    func grapgView(grapgView: BarGraph, setHeightOfBarAtIndex index: Int) -> CGFloat
    {
        return heightOfBars[index]
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}
  

Комментарии:

1. Я использовал ваш код в своем проекте, но все еще не могу сгенерировать график. Вот ссылка на мое демонстрационное приложение dropbox.com/s/0eb8fri3miyqr45/HeaderContainer.zip?dl=0

2. @pretam Спасибо

3. var delegte: BarGraphDatasource! = nil{ didSet{ self.reloadGraph() } }

4. значение делегата равно нулю

5. Вы устанавливаете его из ViewController.swift. Тогда это не будет nill