2011-01-23 99 views
0

我有我的第一個應用程序運行在iphone/ipad上,使用核心圖形和手勢識別器(不是OpenGL或觸摸事件)。應用程序,視圖和控制器是使用IB設置的。這只是ViewController中的一個視圖。我添加了CG調用來繪製到CG上下文中。手勢被添加到視圖中,但在視圖控制器中處理。視圖控制器使用訪問器來更改決定視圖中繪製內容的變量。計算(即模型)嵌入在視圖中。該應用程序工作得很好,但我想添加功能,例如發送電子郵件並保存已繪製的內容。 (我知道我需要其他圖形上下文)。如何繪製請求/ rcv模型新鮮計算的圖像?

傳統觀點告訴我需要使用MVC範式,這意味着將模型從視圖中分解到它自己的對象中。所以,我重新考慮了代碼。我爲模型手動添加了一個NSObject,它很好地包含了數據和所需的方法。沒有編譯錯誤或警告。

現在,當視圖的drawRect被觸發時,我想通過控制器從模型中獲取更新的圖像。在我期望圖像被返回的關鍵位置,NULL返回。我可能只是沒有我的對象引用是正確的,但我太困惑了,不能去掉霧,我正在一個真空中工作,所以我爭取你的幫助。謝謝閱讀。

內容和QUESTION

視圖控制器總是具有能夠傳遞到模型的當前參數。 該模型可以計算給定這些參數的位圖圖像。 我很確定我有那麼多。

我的問題是(措辭各種不同的方式):

什麼是讓從模型到視圖圖像(通過控制器:^)的最佳方式 查看該如何將消息發送到視圖控制器發起請求?

模型如何將圖像返回到控制器? 我想我只是通過一個CGContextRef通過你推薦的任何鏈。

關於我:我是OOP,Objective-C,Xcode和IB的新手。我幾次觀看了斯坦福大部分的講座,研究了Goldstein的傻瓜書籍,搜索了蘋果文檔。新手很難從這些來源收集適當的答案。我只需要更多的「經驗」。我很綠,我甚至不知道如何引用視圖控制器,除了在視圖的界面定義中包含「myViewController * viewController」!我一直在谷歌搜索和閱讀類似的問題在這裏Stackoverflow的答案。我不能beleeve我沒有找到任何appropos。我希望有一兩個實際的原則作爲我的指導。

請指教。

這與reference-to-model-data-in-a-view-instance-drawrect類似,沒有得到充分滿足。

+0

我再次更詳細地閱讀了您的問題,並且您說:「我假設我只是通過您推薦的任何鏈來傳遞CGContextRef。」不要這樣做,如果您發送圖像,請傳遞CGImageRef。如果您要發送點,請使用[NSValue valueWithCGPoint:]並將值存儲在數組中以傳遞給視圖。如果你需要繪製圖像和點列表等幾個不同的功能,你應該爲每一個創建一個不同的UIView子類,並使用你的視圖控制器在合適的時候切換它們。 – Rich 2011-01-24 15:41:07

+0

你不應該使用CGContext ref來傳遞數據的原因是因爲它是視圖體系結構的一部分,並且由於程序的不同部分沒有分開,所以這打破了MVC模式。實質上,模型,視圖和控制器都應該能夠單獨運行。唯一的例外是視圖控制器可以知道模型和視圖,但它仍然不應該與任何一個綁定得太緊密(也就是說,你只需要對零件進行小的修改(如果有的話)一組相關的類),使其在另一個應用程序中工作)。 – Rich 2011-01-24 15:47:12

+0

好的。我在原來的聲明中寫了錯誤的東西。我正試圖在MVC版本的程序中使用CGImageRef。也許我會稍後編輯它。我瞭解那裏的差異。這真的會被扭曲,將CGContextRef從視圖傳遞到模型(以某種方式),並要求模型進入該模型! :^)對不起,困惑。工作完成後我會回來的。謝謝。 – jem 2011-01-24 17:11:41

回答

0

有一件事你可以嘗試,如果它適合你是使用NSNotifications。

該視圖獲取手勢信息並向控制器發送高級事件(通過直接消息傳遞)。控制器接受這些高級別事件並對模型進行更改。該模型消耗這些變化,然後將NSNotifications發送給任何關心變化的人。

該視圖已經知道該模型,因爲這是它如何獲取其數據顯示,所以視圖將能夠容易地訂閱這些更改。該模型並不真正瞭解視圖,所以應該直接發送消息給它。然而,某處某處對模型更改感興趣,因此它使用NSNotifications來廣播和發佈該信息。這樣,特別是對於一個複雜的模型和/或更簡單的視圖,視圖只會訂閱他們感興趣的內容。您還可以輕鬆擁有多個視圖(或其他)一次偵聽NSNotifications。

另一種選擇是關鍵值編碼/觀察,其中iPhone支持,但因爲它是Cocoa在Mac上它不是根深蒂固。這會爲您自動處理大部分通知內容,因此您可能也會考慮這一點。

+0

謝謝你。這有助於完成我對MVC如何在實踐中工作的理解。在你的回答中,我想澄清一下,在應用程序的工作版本中,模型數學/邏輯嵌入在視圖中。在我的新「MVC」版本中,模型是分開的,而視圖和模型是彼此不知情的。與他們一起工作如此鬆散地結合起來會很好。我看到Rich也暗示了內存管理。我會嘗試一下,看看我能否檢查答案。我願意提供更多建議! – jem 2011-01-24 01:52:21

+0

視圖越通用,關於模型的「需要知道的」就越少。那裏的遊戲確保模型提供View可以實際使用的信息(即如果View需要數字,並且Model提供字符串,則需要某種中介)。 Mac TableView是非常通用的,但它也有一個Table特定的數據源,但是從那裏可以依靠KVO綁定列等。就個人而言,對於模型而言,視圖不可知是更重要的,而不是模型不可知的視圖。但通過協議總是存在中間地帶來減少耦合。 – 2011-01-24 02:40:20

0

如果我理解正確的觀點需要得到一個新的圖像時,模型中的更改的圖像。威爾說,你可以使用通知或鍵值觀察。既然你的模型不需要知道視圖,並且視圖不應該對模型有強烈的參考。在您的drawRect

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if ([keyPath isEqual:@"<replace this with the name of the image property in the model>"] { 
     // set an image property that has been added to the uiview 
     // the image property should be a weak reference ie. (nonatomic, assign) 
     self.image = [change valueForKey:NSKeyValueChangeNewKey]; 
     [self setNeedsDisplay]; 
    } 
} 

最後:這樣做,這在您的視圖控制器添加到viewDidLoad方法:

[model addObserver:self.view forKeyPath:@"<replace this with the name of the image property in the model>" options:NSKeyValueChangeNewKey context:NULL]; 

然後在UIView子類使用此法方法,你應該繪製圖像。

0

我怎麼之間架起VIEW聯動|控制器| MODEL:

視圖|控制器 - 從視圖控制器的方法的loadView我發送的消息的「hello」的視圖,其中包含於「自我」的參考。在(視圖對象的)hello方法中,我把這個指向視圖控制器的指針放在全局變量中供以後使用。

控制器|模型 - 我的視圖控制器分配/初始化模型對象的實例,並保存指針,在視圖控制器的全局變量。

我能夠通過VEW控制不斷上升,在使用這兩個指針從視圖模型的橋樑。我不知道我做得足夠好,知道我是否可以完成與IB的這種聯繫。

重述工作原理

的drawRect發送請求/消息用於更新圖像到ViewController。然而

視圖控制器可以充當它想,但由於它具有通過手勢處理程序調整了參數,就可以通過與這些參數的模型的特定請求。

該模型然後獲取CG忙,使用CGBitmapContextCreateImage(從模型中的位圖上下文)並返回一個CGImageRef(視圖控制器)。然後視圖控制器返回與原始請求結果相同的CGImageRef。然後,drawRect執行[[UIImage imageWithCGImage:modelImage] drawInRect:rect]將圖像放入視圖中。

可能的不利,最後的思考

它/可能/慢,但可能只是妄想。該模型通常會繪製8K或更多行來製作位圖圖像,但該視圖不需要做太多工作來複制結果像素。我應該使用儀器來查看發生了什麼。

我也很擔心圖像質量。似乎沒問題。我不認爲我通過首先繪製到CGbitmap上下文,然後通過CGBitmapContextCreateImage,然後最後是UIImage imageWithCGImage失去了什麼,如上所述。所有相同的確切大小。

0

首先,您可能需要重新繪製參數會導致數據更改的時間。因此,當視圖需要重新繪製時,請不要請求新數據,讓視圖或視圖控制器監視數據,以便在視圖更改時重繪視圖。 drawRect真的不應該請求數據,尤其是不是從視圖控制器間接請求數據,這打破了整個MVC設計,因爲視圖需要知道它的視圖控制器(因此它可以請求數據)。其次,對於速度,使用cgcontext直接繪製圖像:CGContextDrawImage(GContextRef c, CGRect rect, CGImageRef image);