drawRect 如何请求/rcv 模型新计算的图像?
我的第一个应用程序在 iPhone/iPad 上运行,它使用 Core Graphics 和手势识别器(不是 OpenGL 或触摸事件)。应用程序、视图和控制器是使用 IB 设置的。它只是 ViewController 中的一个视图。我添加了 CG 调用来绘制到 CG 上下文中。手势被添加到视图中,但在视图控制器中处理。视图控制器使用访问器来更改确定视图中绘制内容的变量。计算(即模型)嵌入在视图中。该应用程序运行得很好,但我想添加一些功能,例如发送电子邮件和保存绘制的内容。 (我知道我需要其他图形上下文)。
传统观点告诉我,我需要使用 MVC 范例,这意味着将模型从视图中分解到它自己的对象中。所以,我重构了代码。我为模型手动添加了一个 NSObject,它很好地包含了数据和所需的方法。没有编译错误或警告。
现在,当触发视图的drawRect时,我想通过控制器从模型获取更新的图像。在我期望返回图像的关键位置,NULL 回来了。我可能只是没有正确的对象引用,但我太困惑了,无法拨开迷雾,而且我正在真空中工作,所以我正在寻求你的帮助。感谢您的阅读。
摘要和问题
视图控制器始终具有可以传递给模型的当前参数。 该模型可以在给定这些参数的情况下计算位图图像。 我很确定我已经有这么多了。
我的问题是(用各种不同的方式表达):
将图像从模型获取到视图的最佳方法是什么(通过控制器:^) View应该如何向视图控制器发送消息来发起请求?
模型如何将图像返回给控制器? 我假设我只是通过您推荐的任何链传递 CGContextRef 。
关于我:我是 OOP、Objective-C、Xcode 和 IB 的新手。我已经多次观看了斯坦福大学的大部分讲座,研究了戈德斯坦的《傻瓜书》,浏览了苹果文档。对于菜鸟来说,很难从这些来源中收集到适当水平的答案。我只是需要更多的“经验”。我很新手,我什至不知道如何引用视图控制器,除了在视图的接口定义中包含“myViewController *viewController”!我一直在 Stackoverflow 上谷歌搜索并阅读类似问题的答案。我不敢相信我还没有找到任何合适的东西。我希望有一两个实用的原则可以作为我的指导。
请指教。
这类似于 view-instance-drawrect 中对模型数据的引用,但没有得到令人满意的答复。
I have my first app running on iphone/ipad that uses Core Graphics and gesture recognizers (NOT OpenGL or touch events). The App, view, and controller were set up using IB. It's simply a View within a ViewController. I added CG calls to draw into a CG Context. The gestures are added to the view, but handled in the view controller. The view controller uses accessors to change variables that determine what is drawn in the view. The computation (ie model) is embedded in the view. The app works quite well, but I would like to add features, such as emailing and saving what has been drawn. (I know I'll need other graphics contexts).
Conventional wisdom tells me I need to use MVC paradigm, meaning to factor the model out of the view into its own object. So, I re-factored the code. I manually added an NSObject for the model, which nicely contains the data and needed methods. No compile errors or warnings.
Now, when the view's drawRect is triggered, I want to get an updated image from the model via the controller. At the key place where I expect the image to be returned, NULL comes back. I probably just don't have my object reference(s) correct, but I'm too confused to cut though the fog, and I'm working in a vaccum, so I am enlisting your help. Thanks for reading.
SUMMARY and QUESTION
The View Controller always has the current parameters that it can pass to the model.
The model can compute a bitmapped image given those parameters.
I'm pretty sure I have that much down.
My question is (phrased various different ways):
What is the best way to get the image FROM the model TO the view (via the controller :^)
How should the View send a message to the view controller to initiate the request?
How can the model return the image to the controller?
I assume I'd just pass a CGContextRef back through whatever chain you recommend.
About me: I am new to OOP, Objective-C, Xcode, and IB. I've watched most of the Stanford lectures several times, studied Goldstein's Dummies books, scoured Apple docs. It is hard for a noob to glean appropriate level answers from these sources. I just need more "experience". I'm so green, I'm not even sure how to refer to the view controller, other than to include "myViewController *viewController" in the view's interface definition! I have been googling and reading the answers to similar questions here on Stackoverflow. I can't beleeve I haven't found anything appropos. I hoping for a practical principle or two to serve as my guide.
Please advise.
This is similar to reference-to-model-data-in-a-view-instance-drawrect, which was not answered satifactorily.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果适合您,您可以尝试的一件事是使用 NSNotifications。
视图获取手势信息并将高级事件发送到控制器(通过直接消息传递)。控制器接收这些高级事件并对模型进行更改。模型使用这些更改,然后向任何关注更改的人发送 NSNotifications。
视图已经了解模型,因为这就是它获取数据显示的方式,因此视图将能够轻松订阅这些更改。模型并不真正了解视图,因此应该直接向其发送消息。然而,某个地方的某些东西对模型更改感兴趣,因此它使用 NSNotifications 来广播和发布该信息。这样,特别是对于复杂的模型和/或更简单的视图,视图仅订阅它们感兴趣的内容。您还可以轻松地让多个视图(或其他视图)同时侦听 NSNotifications。
另一个选项是键值编码/观察,iPhone 支持,但它不像 Mac 上的 Cocoa 那样根深蒂固。这会为您半自动处理大部分通知内容,因此您可能也需要考虑这一点。
One thing you can try if it suits you is to use NSNotifications.
The View gets the gesture information and sends high level events to the Controller (through direct messaging). The Controller takes those high level events and makes changes to the Model. The Model consumes those changes and then sends out NSNotifications to anyone concerned about the changes.
The View already knows about the Model, since that's how it gets its data to display, so the View will be able to subscribe to those changes readily. The Model doesn't really know about the View, so should have to send messages directly to it. However, something, somewhere, is interested in the Model changes, so it uses NSNotifications to broadcast and publish that information. This way, particularly with a complex model and/or simpler View, the Views subscribe only to what they are interested in. You can also easily have more than one View (or whatever) listening for NSNotifications at a time.
Another option is Key Value Coding/Observing, which iPhone supports, but it's not as ingrained as it is in Cocoa on the Mac. This handles much of Notification stuff semi-automatically for you, so you may want to consider that as well.
如果我理解正确的话,当模型中的图像发生变化时,视图需要获取新图像。正如威尔所说,您可以使用通知或键值观察。因为您的模型不必了解视图,并且视图不应该对模型有很强的引用。为此,将其添加到视图控制器中的 viewDidLoad 方法中:
然后在 uiview 子类中创建此方法:
最后在 drawRect: 方法中绘制图像。
If I understand you correctly the view needs to get a new image when the image in the model changes. As Will said you can use notifications or key-value observing. Since your model shouldn't have to know about the view and the view shouldn't have a strong reference to the model. to do so add this to the viewDidLoad method in your view controller:
then in your uiview subclass make this method:
and finally in your drawRect: method you should draw the image.
我如何设置视图之间的链接|控制器|模型:
视图|控制器 - 从视图控制器的 loadView 方法,我向视图发送了一条消息“hello:”,其中包含对“self”的引用。在(视图对象的)hello 方法中,我将指向视图控制器的指针存储在全局变量中以供以后使用。
控制器|模型 - 我让视图控制器分配/初始化模型对象的实例,并将指向该实例的指针保存在视图控制器的全局变量中。
我能够通过 vew 控制器来使用这两个指针作为从视图到模型的桥梁。我不知道我在哪些方面做得足够好,以至于不知道我是否可以完成与IB的这种联系。
回顾一下它是如何工作的
drawRect向视图控制器发送更新图像的请求/消息。
视图控制器可以按照自己的意愿行事,但由于它具有由手势处理程序调整的参数,因此它可以使用这些参数将特定请求传递给模型。
然后模型开始忙于 CG,使用 CGBitmapContextCreateImage (来自模型中的位图上下文)并返回 CGImageRef (到视图控制器)。然后视图控制器只返回与原始请求结果相同的 CGImageRef。然后,drawRect 执行 [[UIImage imageWithCGImage:modelImage] drawInRect:rect] 将图像放置在视图中。
可能的缺点,最终的想法
它/可能/更慢,但这可能只是偏执。模型通常绘制 8K 线或更多线来制作位图图像,但视图不必做那么多工作来复制结果像素。我应该使用 Instruments 来看看发生了什么。
我还担心图像质量。看起来还可以。我认为首先绘制到 CGbitmap 上下文中,然后经过 CGBitmapContextCreateImage,最后是上面的 UIImage imageWithCGImage 不会丢失任何东西。全部尺寸完全相同。
HOW I SET UP LINKAGE BETWEEN VIEW | CONTROLLER | MODEL:
view|controller - From the view controller's loadView method I sent a message "hello:" to the view, containing a reference to 'self'. In the hello method (of the view object), I stashed that pointer to the viewcontroller in a global variable for later use.
controller|model - I had the view controller alloc/init the instance of the model object and save the pointer to that in a global variable in the view controller.
I was able to use these two pointers as a bridge from the view to the model by going up and over through the vew controller. I don't know what I am doing well enough to know whther I could have accomplished this linkage with IB or not.
RECAP OF HOW IT WORKS
drawRect sends a request/message for an updated image to the viewcontroller.
The view controller can act however it wants, but since it has the parameters as adjusted by the gesture handlers, it can pass a specific request to the model with those parameters.
The model then gets busy with CG, uses CGBitmapContextCreateImage (from the bitmap context in the model) and returns a CGImageRef (to the view controller). Then the view controller just returns the same CGImageRef as the result of the original request. drawRect then does [[UIImage imageWithCGImage:modelImage] drawInRect:rect] to place the image in the view.
POSSIBLE DOWNSIDES, FINAL THOUGHTS
It /might/ slower but that may just be paranoia. The model typically draws 8K lines or more to make the bitmap image, but the view doesn't have to do that much work to copy the resulting pixels. I should use Instruments to see what's up.
Also I'm concerned about image quality. Seems OK. I don't think I lose anything by first drawing into a CGbitmap context, then going through CGBitmapContextCreateImage, then finally the UIImage imageWithCGImage as above. All same exact size.
首先,每当您的参数会导致数据发生变化时,您可能需要重新绘制。因此,当视图需要重绘时,不要请求新数据,而是让视图或视图控制器监视数据,以便在数据发生更改时视图将重绘。 drawRect 确实不应该请求数据,尤其是不间接地从视图控制器请求数据,这破坏了整个 MVC 设计,因为视图需要了解它的视图控制器(以便它可以请求数据)。其次,为了速度,使用 cgcontext 直接绘制图像:
CGContextDrawImage(GContextRef c, CGRect rect, CGImageRef image);
。First off you will probably need to redraw whenever your parameters would cause a change in the data. So instead of requesting new data when the view needs to redraw, have the view or view controller monitor the data so that if it changes the view will redraw. drawRect REALLY shoudn't be requesting data, especially not indirectly from the view controller, this breaks the whole MVC design because the view needs to know about it's view controller (so it can request the data). Secondly for speed use the cgcontext to draw the image directly:
CGContextDrawImage(GContextRef c, CGRect rect, CGImageRef image);
.