用 Drawrect 绘图

Posted

技术标签:

【中文标题】用 Drawrect 绘图【英文标题】:Drawing with Drawrect 【发布时间】:2013-09-03 08:56:00 【问题描述】:

亲爱的objectiveC大师们, 我是一名新手苹果程序员,由于我目前正在攻读数学教育硕士学位,我想写一篇关于制作基于数学教育的应用程序的论文..

现在,我正在尝试制作一个 iPad 应用程序,它可以绘制正弦函数,然后转换正弦函数。我通过覆盖自定义 uiview 类中的 drawrect 函数来绘制正弦图并将其加载到 uiview 对象。正弦函数很好地绘制在上下文上,以及在不同上下文上绘制的网格和轴。

我放置了几个滑块,然后计划使用滑块来更改我用于绘图的 uiview 类中的变量。现在问题来了,我意识到我无法从自定义 uiview 类访问 viewcontroller 中的变量,并且我怀疑我在编写整个程序时可能错误地使用了错误的范例。

有人可以帮我解决这里的困惑吗?它不必在确切的代码中,但更多的是关于我应该如何在视图对象上绘制和重绘正弦函数同时通过滑块更改正弦函数的变量的大图。

感谢您的热心帮助 :) 来自印度尼西亚的 Chandra。

【问题讨论】:

你好 Pii,还有一些未解决的问题吗? 【参考方案1】:

有两种方法可以解决这个问题:

    除了让 UIView 从 UIViewController 询问值外,您还可以在其中一个滑块发生变化时将值推送到 UIVIew。这样 UIView 会做它应该做的事情:绘制 ViewController 要求他做的事情。 想想你在 UIView 中实现并从 UIViewController 调用的像 redrawUsingNewValues: 这样的函数。

    使用委托。如果你真的希望 UIView 处于控制之中,你可以使用委托给它一个指向 UIViewController 的指针。这样 UIView 不拥有 UIViewController,但你可以得到你想要的值。 关于委托的介绍可以在这里找到:Delegation and the Cocoa Frameworks

祝你的计划好运!

【讨论】:

Jacco.. 谢谢你的回答.. 除了释放键盘,我没有使用委托,大声笑.. 我想我需要让位一段时间来研究更多关于那么委托事项..这是“正确”的方式吗?或者如果我只是推迟探索委托事项并像您在#1中所说的那样推动该价值,会更容易吗? ios 高度基于 MVC(模型-视图-控制器)。在这种情况下,这意味着您希望 viewCONTROLLER 控制视图(名称中有什么;))我建议让视图尽可能愚蠢(仅显示内容)并让 ViewController 控制其他所有内容。这意味着选项#1是要走的路。 1. 在你的 UIView 上创建你需要的变量作为公共属性 2. 填写你的 drawrect 函数以使用这些变量 3. 当滑块改变时,在 ViewController 中改变你的 UIView 的变量 4. 调用 [yourView drawrect] 来重绘 完全正确!我仍然很难应用 MVC 模型,因为我只想做所有事情,甚至不考虑每个类的作用.. 你的智慧给了我洞察力!大声笑...非常感谢:)【参考方案2】:
    UIViewController 中的方法应该能够识别滑块值何时发生变化 相同的方法应该触发 UIViewController 中的另一个方法来更新/重新计算正弦函数值(例如创建一个值数组) 在更新方法结束时,必要的值通过从 UIViewController 到 UIView 的出口传输到 UIView(UIView 是 UIViewController 的属性) UIView 在 draw rect 中绘制新的正弦函数

编辑 1: 你的 ViewController.h:

#import <UIKit/UIKit.h>
@class YourGraphUIView; // that's you view where you draw

@interface ResultViewController: UIViewController

@property (weak, nonatomic) IBOutlet UISlider *valueFromSlider; //bound to your UISlider
@property (weak) IBOutlet YourGraphUIView *yourGraphUIView; //bound to your costumUIView
@property (nonatomic, retain) NSNumber *graphValue;

- (IBAction)takeSliderValue:(id)sender; //bound to your UISlider

@end

你的 ViewController.m:

#import "ResultViewController.h"
#import "YourGraphUIView.h"

@interface ResultViewController ()

@end

@implementation ResultViewController
@synthesize yourGraphUIView, valueFromSlider, graphValue;

- (IBAction)takeSliderValue:(UISlider *)sender

graphValue = [NSNumber numberWithDouble:[(double)sender.value]]; //takes value from UISlider
yourGraphUIView.graphValue = graphValue; //gives the value to the yourGraphUIView
[self.yourGraphUIView setNeedsDisplay] //<--- important to redraw UIView after changes

end

你的 YourGraphUIView.h:

#import <UIKit/UIKit.h>

@interface YourGraphUIView : UIView

@property(nonatomic, retain)NSNumber *graphValue;

- (void)drawRect:(CGRect)dirtyRect;

@end

你的 YourGraphUIView.m:

#import "YourGraphUIView.h"

@implementation YoutGraphUIView

@synthesize graphValue;

//... init, draw rect with using the graphValue for calculating and updating the graph

end;

我希望这会有所帮助。您应该看看如何构建 GUI 以及如何连接 UIView。您还需要为 ViewController 和 YourGraphUIView 设置自定义类。祝你好运!

【讨论】:

感谢您的回答,JFS!我不确定我是否抓住了你的想法。只是我对这个 Xcode 的东西还是很陌生,而且我还没有清楚地知道我应该如何真正工作。我不想要养成打补丁来弥补程序漏洞的坏习惯。有很多教程和书籍要学习,但我迫不及待地想先完成所有这些材料。希望你明白我的意思.. 哇!感谢您为我写下来..我明白您传递属性的想法..我已经尝试过了,我收到一条错误消息,说即使我已经导入了 UI,Xcode 也找不到该对象上的属性自定义类并合成属性..知道出了什么问题吗?另一个问题是关于您创建的 NSNumber 对象,它是否必须是一个对象,以便它可以在其属性上保留保留以通过类传递?我试图传递 CGpoint 属性但我不能,我认为这是因为它不是一个对象?原谅我乱七八糟的脑袋,呵呵.. 没有代码很难判断问题出在哪里。您是否将 UIView 绑定到 ViewController 并将自定义类设置为 UIView 和 UIViewController?该值不必是一个对象,它也可以是一个原始值。但请注意,CGPoint 不仅仅是一个 var The data structure CGPoint represents a point in a two-dimensional coordinate system. 是的,所有连接似乎都正常,感谢您提醒有关 CGPoint.. 很好,我会尝试找出问题所在.. 非常感谢 Buddy :) 我错过了一个重要部分。为了更新视图,您需要在 takeSliderValue 方法中设置以下内容:[self.yourGraphUIView setNeedsDisplay]

以上是关于用 Drawrect 绘图的主要内容,如果未能解决你的问题,请参考以下文章

iOS重绘机制drawRect

覆盖绘图应用程序的drawRect

调整 UIView 的大小,但 drawRect 完成的绘图也会改变大小

基准 UIView drawRect: 方法

使用drawRect延迟加载UIView:绘图

iOS drawRect的作用和调用机制