2016-04-08 67 views
0

我有一個UIView類在我的應用程序繪製線圖。在那裏,我給你我的graphPoints變量,像這樣:如何將參數從一個類傳遞到UIView類? Swift

var graphPoints:[Int] = [1,2,3,5,7,9] 
var graphPoints2:[Int] = [1,2,3,5,7,9] 

我想要做的是從另一個類合格Int數組,並分配這些變量,但我不知道該怎麼做。最初我把我所有的代碼放在一個funcarray [Int]作爲參數,並從另一個類中調用它,但它完全停止繪製圖。我該怎麼做呢?

這裏是我UIVIewGraphPlotter類代碼:

import UIKit 

@IBDesignable class GraphPlotter: UIView { 

var graphPoints:[Int] = [1,2,3,5,7,9] 
var graphPoints2:[Int] = [1,2,3,5,7,9] 

//1 - the properties for the gradient 
var startColor: UIColor = UIColor.redColor() 
var endColor: UIColor = UIColor.greenColor() 

override func drawRect(rect: CGRect) { 

    let width = rect.width 
    let height = rect.height 

    //set up background clipping area 
    let path = UIBezierPath(roundedRect: rect, 
     byRoundingCorners: UIRectCorner.AllCorners, 
     cornerRadii: CGSize(width: 8.0, height: 8.0)) 
    path.addClip() 

    //2 - get the current context 
    let context = UIGraphicsGetCurrentContext() 
    let colors = [startColor.CGColor, endColor.CGColor] 

    //3 - set up the color space 
    let colorSpace = CGColorSpaceCreateDeviceRGB() 

    //4 - set up the color stops 
    let colorLocations:[CGFloat] = [0.0, 1.0] 

    //5 - create the gradient 
    let gradient = CGGradientCreateWithColors(colorSpace, 
     colors, 
     colorLocations) 

    //6 - draw the gradient 
    var startPoint = CGPoint.zero 
    var endPoint = CGPoint(x:0, y:self.bounds.height) 
    CGContextDrawLinearGradient(context, 
     gradient, 
     startPoint, 
     endPoint, 
     []) 

    //calculate the x point 

    let margin:CGFloat = 40.0 
    let columnXPoint = { (column:Int) -> CGFloat in 
     //Calculate gap between points 
     let spacer = (width - margin*2 - 4)/
      CGFloat((self.graphPoints.count - 1)) 
     var x:CGFloat = CGFloat(column) * spacer 
     x += margin + 2 
     return x 
    } 

    // calculate the y point 

    let topBorder:CGFloat = 60 
    let bottomBorder:CGFloat = 50 
    let graphHeight = height - topBorder - bottomBorder 
    let maxValue = graphPoints2.maxElement()! 
    let columnYPoint = { (graphPoint2:Int) -> CGFloat in 
     var y:CGFloat = CGFloat(graphPoint2)/
      CGFloat(maxValue) * graphHeight 
     y = graphHeight + topBorder - y // Flip the graph 
     return y 
    } 

    // draw the line graph 

    UIColor.flatTealColor().setFill() 
    UIColor.flatTealColor().setStroke() 

    //set up the points line 
    let graphPath = UIBezierPath() 
    //go to start of line 
    graphPath.moveToPoint(CGPoint(x:columnXPoint(0), 
     y:columnYPoint(graphPoints2[0]))) 

    //add points for each item in the graphPoints array 
    //at the correct (x, y) for the point 
    for i in 1..<graphPoints.count { 
     let nextPoint = CGPoint(x:columnXPoint(i), 
      y:columnYPoint(graphPoints2[i])) 
     graphPath.addLineToPoint(nextPoint) 

    } 

    //Create the clipping path for the graph gradient 

    //1 - save the state of the context (commented out for now) 
    CGContextSaveGState(context) 

    //2 - make a copy of the path 
    let clippingPath = graphPath.copy() as! UIBezierPath 

    //3 - add lines to the copied path to complete the clip area 
    clippingPath.addLineToPoint(CGPoint(
     x: columnXPoint(graphPoints.count - 1), 
     y:height)) 
    clippingPath.addLineToPoint(CGPoint(
     x:columnXPoint(0), 
     y:height)) 
    clippingPath.closePath() 

    //4 - add the clipping path to the context 
    clippingPath.addClip() 

    let highestYPoint = columnYPoint(maxValue) 
    startPoint = CGPoint(x:margin, y: highestYPoint) 
    endPoint = CGPoint(x:margin, y:self.bounds.height) 

    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, []) 
    CGContextRestoreGState(context) 

    //draw the line on top of the clipped gradient 
    graphPath.lineWidth = 2.0 
    graphPath.stroke() 

    //Draw the circles on top of graph stroke 
    for i in 0..<graphPoints.count { 
     var point = CGPoint(x:columnXPoint(i), y:columnYPoint(graphPoints2[i])) 
     point.x -= 5.0/2 
     point.y -= 5.0/2 


     let circle = UIBezierPath(ovalInRect: 
      CGRect(origin: point, 
       size: CGSize(width: 5.0, height: 5.0))) 
     circle.fill() 
     let label = UILabel(frame: CGRectMake(0, 0, 200, 21)) 
     label.center = CGPointMake(160, 284) 
     label.textAlignment = NSTextAlignment.Center 
     //   label.text = "I'am a test label" 
     self.addSubview(label) 
    } 



    //Draw horizontal graph lines on the top of everything 
    let linePath = UIBezierPath() 

    //top line 
    linePath.moveToPoint(CGPoint(x:margin, y: topBorder)) 
    linePath.addLineToPoint(CGPoint(x: width - margin, 
     y:topBorder)) 

    //center line 
    linePath.moveToPoint(CGPoint(x:margin, 
     y: graphHeight/2 + topBorder)) 
    linePath.addLineToPoint(CGPoint(x:width - margin, 
     y:graphHeight/2 + topBorder)) 

    //bottom line 
    linePath.moveToPoint(CGPoint(x:margin, 
     y:height - bottomBorder)) 
    linePath.addLineToPoint(CGPoint(x:width - margin, 
     y:height - bottomBorder)) 
    let color = UIColor.flatTealColor() 
    color.setStroke() 

    linePath.lineWidth = 1.0 
    linePath.stroke() 

} 

} 

DBController,FUNC dosmth在那裏我將數組:

func dosmth(metadata: DBMetadata!) { 

    let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] 

    let localFilePath = (documentsDirectoryPath as NSString).stringByAppendingPathComponent(metadata.filename) 

    var newarray = [Int]() 


    do{ 

     let data = try String(contentsOfFile: localFilePath as String, 
           encoding: NSASCIIStringEncoding) 
     print(data) 

     newarray = data.characters.split(){$0 == ","}.map{ 
      Int(String.init($0).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()))!} 


     print(newarray) 


    } 
    catch let error { print(error) } 

    //Probably wrong 
    GraphPlotter().graphPoints = newarray 
    GraphPlotter().graphPoints2 = newarray 

} 
+1

與手頭上的問題無關,我建議不要爲'x'和'y'值分隔數組。我有一個元組數組(例如'[(Int,Int)]')或'CGPoint'值(例如'[CGPoint]')。這樣你就可以確保一致的x和y值。 – Rob

回答

0

所以你drawRect方法是基於兩個變量graphPointsgraphPoints2。創建一個方法,其任務是更新這兩個變量的數組,然後調用setNeedsDisplay - 這將繼續重繪視圖。

func plotGraphPoints(gpArray1 : [Int], andMorePoints gpArray2: [Int]) { 

     print("Old Values", self.graphPoints) 
     self.graphPoints = gpArray1 
     self.graphPoints2 = gpArray2 
     print("New values", self.graphPoints) 

     self.setNeedsDisplay() 
    } 
+0

謝謝你的建議:)我只是有點不確定它是如何工作的,我的意思是我複製並粘貼你的代碼,並從另一個控制器調用該函數,但它沒有區別,即我傳遞了這個數組''[10,2,8 ,4,6,9,3]'這兩個參數,但它仍然繪製這些數字'[1,2,3,5,7,9]'。我是否需要將我的'graphPoints'變量分配給其他的東西呢? – user3395936

+0

你將不得不調試。當你調用方法時,你是否看到單個語句和'drawRect'方法被執行? –

+0

是的,它執行'drawrect',但是用我在'GraphPlotter'類中默認設置的點。而且你個人的語句是什麼意思? – user3395936

0

首先,我要設置這些讓任何更新將重繪的觀點:

var graphPoints:[Int]? { didSet { setNeedsDisplay() } } 
var graphPoints2:[Int]? { didSet { setNeedsDisplay() } } 

注意,我做了這些自選項目,因爲你通常希望它處理的數據缺失與nil值而不是虛擬值。這不承擔,雖然,你會調整你實現檢測和處理這些nil值,例如,你開始繪製線之前,做一個

guard graphPoints != nil && graphPoints2 != nil else { return } 

但是,我注意到,這整個類是IBDesignable,在這種情況下,你可能要一個prepareForInterfaceBuilder提供樣本數據:

override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 

    graphPoints = [1,2,3,5,7,9] 
    graphPoints2 = [1,2,3,5,7,9] 
} 

其次,你的其他類需要有這種自定義視圖的參考。

  • 如果這個「其他」類視圖控制器和您通過IB添加的自定義視圖,你只需添加一個@IBOutlet自定義視圖這個視圖控制器。如果以編程方式添加了此自定義視圖,那麼在將其添加到視圖層次結構後,您只需在某個屬性中保留對該視圖的引用即可。但是,無論你添加到該視圖的引用,說graphView,你只設置這些屬性:

    graphView.graphPoints = ... 
    graphView.graphPoints2 = ... 
    
  • 如果這個「其他」類是其他東西比一個視圖控制器(和討論,聽起來像所討論的類是處理異步DropBox API的控制器),您還需要爲該類提供一些引用視圖控制器(以及自定義視圖)的機制。您可以通過執行「完成處理程序模式」或「委託協議」模式來完成此任務。

+0

謝謝你的建議。所以如果我正確地理解了你,那麼我應該可以在另一個控制器中執行此操作'GraphController().graphView.graphPoints = newarray'? – user3395936

+0

對不起,我不想聽起來愚蠢,但你完全失去了我在這裏..我想通過調用'GraphPlotter()'我打電話給現有的'GraphPlotter' VC?我用segue理解你的例子,但是我猜如果我只是做'GraphPlotter.graphPoints',那麼它會創建'GraphPlotter' VC的一個實例並且會給我一個錯誤?另外我編輯了這個問題,我從我的'DBController'類函數中添加了一個片段,我想從中調用我的'GraphPlotter' VC並傳遞'Int'數組。 – user3395936

+0

也許這顯示了我的代碼中的空白,但實際上兩者之間沒有關係(或者可能很少)。基本上,'DBController'負責從一個Dropbox文件夾中下載一個文件,文件夾中只有一個數字,用逗號分隔。之後,我調用dosmth方法將文件中的文本轉換爲Int數組,然後從中調用GraphPlotter並將新數組分配給graphPoints。不太確定這是否是一種正確的方式,但是在Swift中是一個noob,這對我來說是有意義的。 – user3395936

相關問題