ios - 在 Stanford CS193P 作业 3 (2016) 上绘制 x 与 y 图时遇到问题

标签 ios swift xcode cs193p

我是 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 的方式建模的获取其数据。

通读作业,教授似乎希望您改用可选的函数指针。

执行以下操作:

  1. GraphingView 中创建一个可选变量保存一个函数指针:

    var computeYForX: ((Double) -> Double)?
    
  2. 申请 didSet到那个变量并让它调用self.setNeedsDisplay()当它被设置。这将告诉 iOS drawRect需要调用。

  3. 在您的计算器中绘制时,设置 computeYForX GraphingView 的属性(property)到 (Double) -> Double在你的 GraphViewController 中发挥作用.如果您想删除该功能(例如,当有人重置计算器时),请将该属性设置为 nil .

  4. drawRect , 检查以确保 computeYForX不是 nil在使用它绘制函数之前。使用 guardif 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() ,并将自己设置为 dataSourcedidSet对于 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/

相关文章:

ios - 推送过渡期间重叠 View

objective-c - Swift 函数包含在 Objective-C 类中不可用的参数

ios - 通过带有开发 SSL 证书的 xcode 在设备中推送通知测试

objective-c - 无法运行首选项 Pane 应用程序

ios - 如何解码包含日期信息的 JSON?

iphone - 按两个相关属性对核心数据实体进行排序

ios - 界面生成器中的 "Builds for"选项

iOS:从背景图像中检索矩形图像

ios - 尝试在不创建 Storyboard的情况下以编程方式将 Controller 文件添加到导航 Controller 时出错

ios - 为什么我的 UISwipeGestureRecognizer 出现这个错误?