2016-04-08 19 views
0

私はUIViewクラスを私のアプリに置いています。これは折れ線グラフを描いています。そこでは、私はそうのように私のgraphPoints変数を割り当てる:私は何をしたいか1つのクラスの引数をUIViewクラスに渡すにはどうすればいいですか? Swift

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

は、別のクラスからIntの配列を渡すと、これらの変数を割り当てることですが、私はそれを行う方法がわからないです。最初はすべてのコードをfuncに入れ、パラメータとしてarray [Int]を入れて別のクラスから呼び出しましたが、グラフ全体をプロットしませんでした。私はこれをどのようにして行うのですか?私は配列を渡す

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に基づいています。ここ

は私のUIVIewGraphPlotterクラスコードです。これらの2つの変数の配列を更新するジョブを作成し、次に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() } } 

注意をあなたは、一般的にそれが持つデータの不在を処理したいので、私は、それらのoptionalsを作りましたnilダミー値ではなく値です。あなたがラインを描き始める前に、これはあなたが、検出し、これらのnil値を処理するための実装を微調整するだろうと、しかし、想定しない例えば、私はこのクラス全体がIBDesignableであることがわかり、

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

んが、その場合、あなたはおそらく、サンプルデータを提供していprepareForInterfaceBuilderたい:

override func prepareForInterfaceBuilder() { 
    super.prepareForInterfaceBuilder() 

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

第二に、あなたの他のクラスは、このカスタムビューへの参照を持っている必要があります。

  • この「その他」のクラスはビューコントローラであり、あなたはIB経由でカスタムビューを追加した場合、あなただけのこのビューコントローラにカスタムビューの@IBOutletを追加します。このカスタムビューをプログラムで追加した場合は、そのビューをビュー階層に追加した後、そのプロパティを参照するだけで済みます。この「その他」のクラスはビューコントローラ以外の何か(あるとの議論で、それが聞こえる場合

    graphView.graphPoints = ... 
    graphView.graphPoints2 = ... 
    
  • :しかし、しかし、あなたはそのビューへの参照を追加し、graphViewを言って、あなただけのこれらのプロパティを設定したいです問題のクラスが非同期DropBox APIを処理するためのコントローラである場合)、そのクラスにView Controller(したがってカスタムビュー)を参照するメカニズムを与える必要もあります。これを達成するには、「完了ハンドラパターン」パターンまたは「代理プロトコル」パターンのいずれかを実装します。

+0

あなたの提案をありがとう。だから私はあなたを正しく理解すれば、私はこの 'GraphController()。graphView.graphPoints = newarray'を別のコントローラで実行できるはずですか? – user3395936

+0

申し訳ありませんが、私は愚かに聞こえませんが、私はここで私を完全に失ってしまいました。私は 'GraphPlotter()'を呼び出して、既存の 'GraphPlotter' VCを呼び出していると思いました。私はあなたの例をsegueで理解していますが、 'GraphPlotter.graphPoints'を実行すれば' GraphPlotter' VCのインスタンスが作成され、エラーが表示されますか?また、私は質問を編集しました。私は 'GraphPlotter' VCを呼び出す' DBController'クラス関数のスニペットを追加し、 'Int'の配列を渡しました。 – user3395936

+0

これはおそらく私のコードのギャップを示していますが、実際には2つの間には関係はありません(またはごくわずかです)。基本的に 'DBController'はDropboxフォルダからfieをダウンロードします。Dropboxフォルダにはカンマで区切られた1行の数字だけがあります。その後、ファイルからのテキストを 'Int'の配列に変換する' dosmth'メソッドを呼び出し、そこから 'GraphPlotter'を呼び出して、' graphPoints'に新しい配列を割り当てたいと思います。これを行うのが正しい方法であるかどうかはわかりませんが、スウィフトのノブであることは私にとって意味がありました。 – user3395936