我是 iOS 开发的初学者。除了实际绘制 x 与 y 图之外,我已经在 iTunes U 上完成了 2016 年斯坦福 CS193P iOS 开发类(class)的作业 3(图形计算器)的所有内容(手势、 View Controller 、 View 、segues 等)。我对将代码放在哪里以及如何执行此操作感到很困惑;以及 drawRect 将从哪里获取 y 值。我已经在互联网上搜索了很长时间的解决方案。我假设图形 View Controller 的模型是 CalculatorBrain 或者可能是大脑的程序,但我不太确定 View 将如何从 drawRect 函数与该 Controller 通信以获得 y 值点 x。如果你能让我走上正轨,那将非常有帮助。我将在下面粘贴我的图形 View Controller 和图形 View 代码。提前致谢。
//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
}
}
}
最佳答案
更新的答案 - 使用函数指针
上一个答案是使用数据源来实现的一种方法。它是仿照 UITableViewController
的方式建模的获取其数据。
通读作业,教授似乎希望您改用可选的函数指针。
执行以下操作:
在
GraphingView
中创建一个可选变量保存一个函数指针:var computeYForX: ((Double) -> Double)?
申请
didSet
到那个变量并让它调用self.setNeedsDisplay()
当它被设置。这将告诉 iOSdrawRect
需要调用。在您的计算器中绘制时,设置
computeYForX
GraphingView
的属性(property)到(Double) -> Double
在你的GraphViewController
中发挥作用.如果您想删除该功能(例如,当有人重置计算器时),请将该属性设置为nil
.在
drawRect
, 检查以确保computeYForX
不是nil
在使用它绘制函数之前。使用guard
或if let
在使用之前安全地解包函数。
上一个答案 - 使用数据源
您需要向您的 GraphingView
添加一个数据源 .首先定义一个名为GraphDataSource
的协议(protocol):
protocol GraphDataSource: class {
func computeYforX(x: Double) -> Double
}
添加 dataSource
属性(property)给GraphingView
:
class GraphingView: UIView {
weak var dataSource: GraphDataSource?
有你的GraphViewController
通过添加 GraphDataSource
来实现该协议(protocol)到 class
定义行,通过实现 computeYForX()
,并将自己设置为 dataSource
在didSet
对于 graphView
:
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
, 调用 computeYForX()
在 dataSource
上当你需要一个 y 值时:
let y = dataSource?.computeYForX(x)
关于ios - 在 Stanford CS193P 作业 3 (2016) 上绘制 x 与 y 图时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38952544/