2016-08-15 64 views
1

上繪製x vs y圖時遇到了麻煩我是iOS開發的初學者。除了實際繪製x vs y圖之外,我已在iTunes U(手勢,視圖控制器,視圖,賽格等)上完成2016年斯坦福大學CS193P iOS開發課程的作業3(繪圖計算器)的所有工作。我對於在哪裏以及如何讓我的代碼執行此操作感到困惑;以及drawRect將從中獲取y值的位置。我已經在互聯網上搜索了一個適合年齡的解決方案我假設圖形視圖控制器的模型是CalculatorBrain或可能是大腦程序,但我不太確定視圖如何從drawRect函數與此控制器交談以獲取y值一個點x。如果你能把我放在正確的軌道上,這將是非常有益的。我將在下面粘貼我的圖形視圖控制器和圖形視圖代碼。提前致謝。在斯坦福CS193P任務3(2016)

//GraphViewController 

import UIKit 

class GraphViewController: UIViewController { 

    private var brain = CalculatorBrain() 

    var program: [AnyObject]? 

    @IBOutlet weak var graphView: GraphingView! { 
     didSet { 
      graphView.addGestureRecognizer(UIPinchGestureRecognizer(target: graphView, action: #selector (GraphingView.changeScale(_:)))) 
      graphView.addGestureRecognizer(UIPanGestureRecognizer(target: graphView, action: #selector(GraphingView.panView(_:)))) 
      graphView.addGestureRecognizer(UITapGestureRecognizer(target: graphView, action: #selector(GraphingView.doubleTapOrigin(_:)))) 
     } 
    } 
} 




//GraphingView 
import UIKit 

@IBDesignable 
class GraphingView: UIView { 

    @IBInspectable var scale: CGFloat = 50 { didSet { setNeedsDisplay() } } 
    @IBInspectable var linewidth: CGFloat = 2 { didSet { setNeedsDisplay() } } 
    var origin: CGPoint! { didSet { setNeedsDisplay() } } 

    /* Gesture Code 

    func changeScale (recognizer: UIPinchGestureRecognizer) { 
     switch recognizer.state { 
     case .Changed,.Ended: 
      scale *= recognizer.scale 
      recognizer.scale = 1.0 
     default: 
      break 
     } 
    } 

    func panView (recognizer: UIPanGestureRecognizer) { 
     switch recognizer.state { 
     case .Changed,.Ended: 
      origin.x += recognizer.translationInView(self).x 
      origin.y += recognizer.translationInView(self).y 
      recognizer.setTranslation(CGPoint(x:0,y:0), inView: self) 
     default: 
      break 
     } 
    } 

    func doubleTapOrigin (recognizer: UITapGestureRecognizer) { 
     recognizer.numberOfTapsRequired = 2 
     switch recognizer.state { 
     case .Ended : 
      origin = CGPoint(x: recognizer.locationInView(self).x, y:recognizer.locationInView(self).y) 
     default: break 
     } 
    } 
    */ 

    var axesDrawer = AxesDrawer() 

    override func drawRect(rect: CGRect) { 

     if origin == nil { 
      origin = CGPoint(x: bounds.midX, y: bounds.midY) 
     } 
     axesDrawer.drawAxesInRect(rect, origin: origin, pointsPerUnit: scale) 

     var pixelX = 0 

     while pixelX <= bounds.maxX { 

      //do some code to get value of y for current x from the brain in the view controller and plot it with UIBezierPath 

      pixelX += 1/contentScaleFactor 
     } 

    } 

} 

回答

1

更新答案 - 使用函數指針

以前的答案是使用數據源做到這一點的方法之一。它是按照UITableViewController獲取其數據的方式建模的。

雖然通過賦值讀取,但教授似乎希望您使用可選的函數指針。

執行以下操作:

  1. 創建於GraphingView一個可選的變量來保存一個函數指針:

    var computeYForX: ((Double) -> Double)? 
    
  2. 應用didSet該變量,並調用它self.setNeedsDisplay()當它被設置。這會告訴iOS需要調用drawRect

  3. 在當是時候提醒你的計算器,你GraphViewControllerGraphingViewcomputeYForX屬性設置爲(Double) -> Double功能。如果要刪除該功能(例如,某人重置計算器時),請將該屬性設置爲nil

  4. drawRect,檢查以確保computeYForX不是nil之前使用它來繪製功能。在使用之前使用guardif let安全地解開功能。

以前的答案 - 使用DataSource

你需要一個數據源添加到您的GraphingView。首先定義一個協議稱爲GraphDataSource

protocol GraphDataSource: class { 
    func computeYforX(x: Double) -> Double 
} 

一個dataSource屬性添加到GraphingView

class GraphingView: UIView { 
    weak var dataSource: GraphDataSource? 

有你GraphViewController加入GraphDataSourceclass定義行,通過實施computeYForX()執行該協議,並通過在didSet設置本身作爲dataSourcegraphView

class GraphViewController: UIViewController, GraphDataSource { 

    private var brain = CalculatorBrain() 

    var program: [AnyObject]? 

    @IBOutlet weak var graphView: GraphingView! { 
     didSet { 
      graphView.dataSource = self 
      graphView.addGestureRecognizer(UIPinchGestureRecognizer(target: graphView, action: #selector (GraphingView.changeScale(_:)))) 
      graphView.addGestureRecognizer(UIPanGestureRecognizer(target: graphView, action: #selector(GraphingView.panView(_:)))) 
      graphView.addGestureRecognizer(UITapGestureRecognizer(target: graphView, action: #selector(GraphingView.doubleTapOrigin(_:)))) 
     } 
    } 

    func computeYForX(x: Double) -> Double { 
     // call the brain to calculate y and return it 
    } 
} 

然後在drawRect,呼籲dataSourcecomputeYForX()當你需要一個Y值:

let y = dataSource?.computeYForX(x) 
+0

非常感謝您的幫助。這是唯一的方法嗎?它沒有在任務中說出任何關於協議的內容(並且根據我所理解的講師在講授關於協議之前發佈的任務)。我認爲這就是讓我困惑的原因。 –

+0

我用另一種方式更新了答案,以更好地符合教授的意圖。 – vacawama

+0

非常感謝! –

-1

我使用的現有功能的計算器的大腦。具體來說,大腦裏面,我創建了由基於程序計算的公共方法,存儲通過屬性列表類型轉換的任何對象(我們做的是,在保存/恢復部分)。所有的命令都在那裏 - 我只是將它打包在一個方法中。我使用這種方法的很多東西 - 所以我從不重寫代碼來評估一系列操作數。

在公共接口,這僅僅是一個函數,是腦的任何實例訪問。特別是在準備圖表視圖時,我將圖表視圖控制器指向了這個函數。當時我也通過了大腦中存在的程序,以便可以繪製出在計算器中有效的任何表達式。後者是我的目標,因爲它是有道理的。我想避免重寫解釋操作數的函數。

圖表視圖需要的功能(可以是腦或任何其他規範)並是爲了繪製表達式需要一個「方案」。所以這是一個普通的類,需要一個特定的形式來描述操作。我認爲這是一個完美的「合法」解決方案。

的drawRect則使用的功能和程序來繪製曲線。