1. 程式人生 > >UIViewController和UIViewController之間的互動

UIViewController和UIViewController之間的互動

轉載時請註明出處和作者聯絡方式

       UIViewController之間,是否需要互動,怎樣互動?這個問題困擾我一段時間了,憑空的去想象,其實很難想明白,尤其是在短時間內。最好的辦法,還是在持久的編碼/讀程式碼的過程中,根據不同的使用場合及使用需求,來學習體會。

       順便還想說一句,圖形介面程式設計,最基本的程式設計思路和方法都是類似的,如果你熟悉不止一種圖形SDK,你就會發現其實它們都是觸類旁通的。最近我就遊走於cocoa和qml之間,再加上之前qtwidget、gtk、clutter的程式設計經驗,我發現使用這些不同的sdk,對於我個人的程式設計技能的增長,很好的起到了互補的作用。

       假設使用UINavigationController進行導航,有兩層介面結構,都使用自定義UIViewController的子類,分別為level1ViewController和level2ViewController。

1 單向互動。

       第一級level1ViewController負責建立第二級level2ViewController,並且設定level2ViewController相關的屬性,然後push level2ViewController。虛擬碼如下:

[[level2ViewController alloc] init];
 
[level2ViewController setProp_1];
[level2ViewController setProp_2];
[level2ViewController setProp_3];
 
[level1ViewController. navigationController
pushViewController:level2ViewController];
 
[level2ViewController release];


       這種情況下,從level1ViewController的角度來看,它只需要初始化level2ViewController,設定它的一些屬性,呼叫push,然後就什麼都不用管了。從level2ViewController的角度來看,當它被push後,在它的生命期內,都不會影響level1ViewController,不需要呼叫level1ViewController的函式,也沒有事件需要通知level1ViewController。

       這是最簡單的使用情形,也是最理想化的。在專案設計階段,應該儘量把程式碼設計成這種結構(僅僅是儘量,並不是必須。而且,也並不是所有的使用場景都都可以設計成這樣的結構,畢竟這個太理想化了)。

2 雙向互動,共享資料

       level1ViewController和level2ViewController使用共同的一個數據shareData(一定要理解這裡“共同”的含義------兩個controller共享同一個資料,並且都有可能進行讀寫操作,尤其是寫操作。如果level2ViewController只對資料進行讀操作,那其實就跟前面1中的情形是一致的)。第一級level1ViewController負責建立第二級level2ViewController,並且設定level2ViewController相關的屬性,同時還要把shareData傳遞給level2ViewController,然後push level2ViewController。虛擬碼如下:

[[shareData alloc] init];
…
[[level2ViewController alloc] init];
 
[level2ViewController setProp_1];
[level2ViewController setProp_2];
[level2ViewController setData: shareData];
 
[level1ViewController. navigationController
pushViewController:level2ViewController];
 
[level2ViewController release];


        和前一種情形的區別是,在level2ViewController的生命期內,它可能會對shareData進行寫操作,當發生這種寫操作的時候,需要讓level1ViewController知道這種變化,並且作出對應的處理。

        這個時候,比較容易想到的一種解決辦法是使用Delegate,當level2ViewController寫操作shareData時,通過Delegate機制通知level1ViewController,給予level1ViewController一個機會作出正確的響應。

        這種辦法雖然可行,但並不是首選,在面向物件程式設計中,經常會提到“解耦”,這裡我們就要想辦法讓這兩個controller不要聯絡的這麼緊密。那麼怎麼辦呢?

就是使用MVC模式(UIViewController本身就是MVC中的C)。這個時候,shareData就不應該再是一個普通的資料,而應該封裝成model,當model中的資料發生了改變的時候,會發出通知告訴C(和/或 V)。這樣的話,兩個controller之間就比較鬆散了。引入dataModel後,虛擬碼如下:

[[shareData alloc] init];
[dataModel alloc] initWithData: shareData];
…
[[level2ViewController alloc] init];
 
[level2ViewController setProp_1];
[level2ViewController setProp_2];
[level2ViewController setModel: dataModel];
 
[level1ViewController. navigationController
pushViewController:level2ViewController];
 
[level2ViewController release];


       當level2ViewController修改shareData後,不需要負責通知level1ViewController。shareData會負責通知它的controller。

3 雙向互動,逆向訊息傳遞

       這時,基本操作都還是前面描述的1或2中的情形,區別點在於,在level2ViewController的生命期內,發生了某個事件,需要讓level1ViewController知道這個事件,並且作出對應的處理。

       這個時候,就只能用Delegate了。當level2ViewController發生某個事件時,通過Delegate機制通知level1ViewController,給與level1ViewController一個機會作出正確的響應。

       但是!一定要謹慎使用這種方案。如果發現程式碼中需要用到這種結構,首先應該重新審視專案的架構,看能不能用前面兩種方案來處理,可能需要做一定的程式碼重構。當前面的方案實在是無能為力的時候,才考慮使用此方案。而且,儘量讓這種逆向的訊息傳遞更簡單,訊息事件不要太多。

4 雙向互動,大量逆向訊息傳遞

       這種情形和前面的3是一樣的,但是level2ViewController和level1ViewController之間的訊息傳遞更復雜。

       這個時候,同樣,要審視程式碼的結構是否合理。而且很大的可能性是設計不合理,應該考慮把level2ViewController中管理的UIView遷移到level1ViewController中,把controller之間的互動,變成controller內部的view之間的互動,讓level1ViewController的內部聚合的更緊密一些,對外部,level1ViewController則表現的更鬆散。例如,UIAlertView或UIActionSheet,都是UIView的子類。(此處並不絕對,在有些sdk中,類似於UIAlertView或UIActionSheet的元件,它的使用情形,是符合前面3中的描述的,因為這兩種元件的行為模式,是有規律性的,可以很方便的複用,舉個例子,桌面程式設計環境中,檔案選擇器這種元件,通常就是一個頂層window)

最後還要補充說明一些內容。

        Cocoa是比較嚴格的執行了MVC設計模式,其中的UIViewController,可以看成是某種使用場合下,一些內在聯絡很緊密、並且協同工作的UIView的一個頂層管理容器。

        在其他的sdk中,不一定有嚴格的controller,很有可能只有M和V(C的功能在V內實現),甚至只有V(簡單的使用場景,就可以不區分M和C,全在V內管理)。這個時候,就有頂層View的概念(有很多種叫法,比如page、window,或者直接使用abstractWidget),這種邏輯概念上的頂層View,在設計的時候,同樣需要考慮它們之間的互動,前面描述的這些情形,同樣可以套用。

        在使用者體驗的角度來看,controll或者頂層view,通常被成為“場景”,場景之間是否需要互動,前面的描述,也有一定的參考價值。

        但是場景的概念並非總和controll或頂層view嚴格對應,“場景”是更抽象化的內容,更符合人類的直觀感覺,而controll/頂層view是更工程化的概念,更精確。在使用者體驗設計中,有些不同的場景,在邏輯上其實可以屬於同一個controll或頂層view。這個隨著經驗的增長,體會才能夠更加的深刻。

        關於使用者體驗設計中的場景,推薦一片文章,可以看看其中舉的一些例子,找找感覺。


相關推薦

UIViewControllerUIViewController之間互動

轉載時請註明出處和作者聯絡方式        UIViewController之間,是否需要互動,怎樣互動?這個問題困擾我一段時間了,憑空的去想象,其實很難想明白,尤其是在短時間內。最好的辦法,還是在持久的編碼/讀程式碼的過程中,根據不同的使用場合及使用需求,來學習

angularjs中如何實現控制器指令之間互動

如果我們具有下面的DOM結構: <div ng-controller="MyCtrl"> <loader>滑動載入</loader> </div>同時我們的控制器具有如下的簽名: var myM

使用JNI在JAVAC++之間進行互動操作

原文連結地址: https://library.vuforia.com/articles/Solution/How-To-Communicate-Between-Java-and-C-using-the-JNI 本文旨在描述如何使用JNI(Java Native Interface)實現JA

angularjs之間如何實現指令指令之間互動

我們看看下面的頁面的結構: <!doctype html> <html ng-app="MyModule"> <head> <meta charset="utf-8"> <link rel="styl

IOS中 UIViewUIViewController的區別

宣告:這篇文章不是原創,因為覺得寫的好,才複製過來保留 ------------------------------------------------------------------------------ UIViewController顧名思義:檢視控制器。應該

javapython之間資料互動,不同語言間傳輸資料:使用RabbitMQ

java和python之間資料互動,不同語言間傳輸資料:使用RabbitMQ 問題描述 方法 方法一:java直接執行python指令碼.py檔案,把資料放到引數裡傳遞 方法二:通過第三方檔案作為中間站 方法三:使用訊息佇列的方式,

C# 利用Socket類實現客戶端伺服器之間的通訊,可在本機之間實現資訊互動

利用Socket類實現了本機之間的客戶端與服務端的資訊互動。 伺服器: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using

iOS開發——純程式碼介面(UIViewController文字類控制元件)

一、新增檢視控制器(UIViewController) 建立一個ViewController類繼承UIViewController ViewController.m做如下修改 - (void)viewDidLoad { [super viewDid

混合開發之webView載入html,android html之間進行資料互動

現在混合開發比較普遍了,其實早就該學學了,只限於自己對html不是很熟,搭的介面太醜了,哈哈… 今天寫Demo的需求是這樣的 1、在一個介面裡,半面html,半面android原生控制元件。 2、點選html傳送html的資料給android ,andro

AndroidUnity3D之間的資料互動

如果將一個unity3D專案匯出成Android工程,然後將該專案作為另一個Android專案的module使用時,如果涉及到相互呼叫,可以寫一個Activity繼承自UnityPlayerActivity public class UnityActivity exten

Fragment(3)其他Fragment之間互動--偉大的介面回撥

這個是我一直想要找的,沒想到偉大的官網竟然有。感動到流鼻涕了。。 為了重用Fragment UI元件,我們應該建立一個完全獨立的自控的,定義自己佈局和行為的模型元件。一旦我們定義了這些可重用的Fragments,我們就可以把它們和Activity關聯起來並且用應用邏輯連線

伺服器客戶端之間互動時使用BufferedReader的阻塞問題

1.遇到的問題 Socket socket = serverSocket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()

html與jsphp之間實現資料互動

一、總述 標題取得假大空,主要還是為了記錄一下課設做的圖片搜尋引擎。 之前的python是用來爬取圖片搜尋引擎的圖片資源的,然後把圖片放在伺服器,圖片對應的tag(關鍵字)和存放路徑放在mangoDB裡面。 這篇部落格主要記錄一下我完成前端(html+js

C# DataTable List之間相互轉換的方法

dbn execute 屬性 ins 集合 方法 summary efault getprop 一、List<T>/IEnumerable轉換到DataTable/DataView private DataTable ToDataTable<T>(

tcpudp之間區別的

比較 需要 快速 區別 復雜 udp 連接 可能 順序 1.tcp需要建立連接   udp不需要建立連接 2.tcp占用系統資源大   udp占用系統資源少 3.tcp結構復雜   udp結構簡單 4.tcp使用的是stearm流模式   udp使用的是Dragm數據報模式

TCPListenerTCPClient之間的通信代碼

方式 基於 通信 client ogr net odi ask 建立 《服務端》 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.N

byte[]數組int之間的轉換

san bar public ava clas href byte[] bytes 記錄 這裏簡單記錄下兩種轉換方式: 第一種: 1、int與byte[]之間的轉換(類似的byte short,long型) [java] view plain copy /*

轉載----execute、executeQueryexecuteUpdate之間的區別

als del mman 必須 ont 修改 效果 一次 都是 JDBCTM中Statement接口提供的execute、executeQuery和executeUpdate之間的區別 Statement 接口提供了三種執行 SQL 語句的方法:executeQuery、e

lte bburru之間的接口是什麽協議

nbsp 同步 10g 串行化 pri 光纖 基本 是什麽 物理 CPRI協議定義了兩個協議層。兩個協議層為物理層(L1)和數據鏈路層(L2)。在物理層中,將上層接入點的傳輸數據進行復/分接,並采用8B/10B編解碼,通過光模塊串行收發數據。數據鏈路層定義了一個同步的幀結構

php js之間使用json通信

鍵值 type 依然 字符 從數據 信息 轉換成 數據轉換 行處理   有時候我們需要用後臺從數據庫中得到的數據在js中進行處理,但是當從php中獲取到數據的時候,使用的是鍵值對形式的多維關聯數組。而我們知道,js只支持索引數組,不支持關聯數組,這個時候從後臺傳遞過來的數據