任靖娟
手機端聊天工具的設計與實現
任靖娟
針對如何在IOS平臺創建即時通訊軟件,使用object-c語言在xcode上編寫和調試IOS程序,接下來xmpp框架的導入和各種效果的實現,最后,介紹了程序的設計思路和模式(如MVC模式)。
IOS openfire XMPP ASIHttpRequest 通訊
隨著智能手機的問世,人們不再僅限于使用手機的短信和通話功能。人們開始傾向于使用手機軟件來通信,于是實時通信軟件不斷被開發和優化。實時通信軟件比短信服務(SMS)更加方便和實用,因此人們更加喜歡用通信軟件進行通信[1]。
下面介紹怎樣用Objective-C語言來實現基于iPhone端的實時通訊軟件,使用當前最流行的UI設計元素,而且有良好的功能實現和用戶體驗。
系統設計的任務是設計軟件系統的模塊層次結構,設計數據庫的結構以及設計模塊的控制流程。此軟件主要采用MVC的設計模式,把所有的邏輯分別歸類到M:模型V:視圖C:控制器中,使整個程序更加明晰。
1.1 系統功能分析
在這個過程中服務器端數據庫要及時準確地存儲、檢索相應的數據,該軟件的需求如下:
(1)注冊:把用戶名和密碼傳給服務器,服務器存入數據庫;
(2)登陸:把用戶名密碼傳給服務器,服務器進行匹配,返回結果;
(3)顯示聯系人:從服務器獲取當前在線聯系人,返回到客戶端,得到數據后填充到界面上;
(4)添加好友:發送當前用戶的用戶名,服務器把數據存到自己好友的表中;
(5)好友列表:從服務器得到好友的數據,服務器遍歷好友表,返回結果;
(6)發送消息:當用戶在線時把消息發送到服務器,服務器轉發給聯系人;
(7)收到信息:當服務器收到消息,消息中帶有目的位置,服務器把消息轉發到目的位置;
(8)消息記錄:發送的消息和收到的消息被及時的存入到了數據庫,可以實現聊天記錄的查看;
(9)刷新:當下拉列表時調用下拉方法,再次請求服務器,知道得到數據后收起加載頁面,使得第一條數據永遠是最新的數據;
(10)注銷:點擊注銷,調用下線的方法,斷開連接。1.2 系統功能結構
該系統分別部署到兩臺服務器上,一個數據服務器一個聊天服務器。數據服務器存儲用戶登陸的信息和相關內容,聊天服務器完成聊天數據的轉發C/S (Client/Server,客戶端/服務器)[2]結構,即客戶機和服務器結構。它是軟件系統體系結構,通過它可以充分利用兩端硬件環境的優勢,將任務合理分配到Client端和Server端來實現,降低了系統的通訊開銷。目前大多數應用軟件系統都是Client/Server形式的兩層結構,由于現在的軟件應用系統正在向分布式的 Web應用發展,Web和Client/Server應用都可以進行同樣的業務處理,應用不同的模塊共享邏輯組件;因此,內部的和外部的用戶都可以訪問新的和現有的應用系統,通過現有應用系統中的邏輯可以擴展出新的應用系統。這也就是目前應用系統的發展方向。本軟件采用了C/S設計結構,客戶端主要功能圖列出了客戶端的主要功能。如圖1所示:

圖1 客戶端主要功能圖
注冊功能:用戶在移動設備上點擊軟件圖標后進入當前程序頁面,進入主界面后,如果已有賬號則可直接點擊登陸,如果沒有賬號,點擊登陸頁面后,會出現注冊按鈕,點擊注冊按鈕輸入用戶名和密碼系統會提示注冊成功或失敗,如果提示成功則注冊成功,如果失敗則提示注冊失敗。
登陸功能:如果已有賬號輸入用戶名密碼以完成登陸操作,如果沒有賬號,注冊成功后,注冊的用戶名和密碼會留在輸入框中,直接點擊登陸按鈕即可完成登錄,點擊登錄按鈕以后系統會提示成功或失敗,如果登陸成功系統跳進主界面如果失敗系統提示登陸失敗。
朋友功能:朋友界面是用戶在發現頁面中添加的好友都會顯示在朋友頁面,當點擊任意一行,即可與當前聯系人進行聊天。
發現功能:發現界面中的數據都是來自openfire數據庫中的ofuer表[3],里面存了所有的注冊用戶,當點擊發現時客戶端請求服務器,服務器返回當前在線的用戶,
消息功能:當和朋友發生聯系后,所有的聊天數據都會存入到消息界面。
注銷功能:點擊注銷按鈕后,系統會退出登錄狀態。
服務器主要功能圖,列出了服務器端的主要功能,如圖2 所示:

圖2 服務器主要功能圖
(1)tomcat服務器:tomcat服務器主要完成業務數據的操作,把圖片和用戶名、密碼存入數據庫,并把存用戶名和密碼的表中的數據復制到openfire數據庫中的ofuser表中。
(2)Openfire服務器:openfire服務器主要完成聊天數據的轉發,這種數據服務器和聊天服務器分開設計從而實現了高并發量。
(3)當用戶發送消息數據會存到hacpi的message表中,
(4)當用戶登錄時,post用戶名和密碼到openfire服務器,當驗證通過后,調用xmpp的已通過驗證的代理方法。
2.1 Xmpp框架導入IOS工程
(1)從github下載xmpp[4]框架導入工程,如圖3所示:

圖3 導入工程圖
選中的文件拖入工程中,其中Extension中的模塊可以選擇添加(只添加當前工程需要的模塊)xmppframework設計是模塊化的,包括核心和擴展,第三方開發人員可以方便的添加自己的擴展實現;同時開發人員也只需要添加自己工程需要的模塊。一般擴展都會依賴一些額外的包, 要注意同時添加進去。
(2)添加framework 選擇工程/選擇Build Phases/Link Binary With Libraries點加號添加,需要添加的庫包括(注意根據你添加的模塊不同,可能需要添加的庫不一樣)如圖4所示:

圖4 鏈接庫圖
(3)添加一個搜索路徑如圖5所示:

圖5 引用文件路徑圖
(4)創建 xmpp對象并實現它的代理方法,初始化xmppStream 設置xmppStream的deleagte實現goOnLine方法完成在線狀態的發送,實現goOffLine方法完成下線方法的發送。實現connect方法從本地獲取用戶名、密碼和服務器地址,通過xmppStream的setMyJID方法設置用戶名,通過setHostName方法設置服務器地址,連接服務器如果成功返回yes,連接服務器后會調用xmppStreamDelegate的方法xmppStreamDidConnect連接服務器,如果成功電泳驗證方法,如果驗證成功調用xmppStreamDidAuthenticate,驗證通過后即可調用上線的方法上線,上線后即可發送消息和收到消息[5]。
2.2 FMdataBase
FMDB框架其實只是一層很薄的封裝,主要的類也就兩個:FMDatabase和FMResultSet[6]。
(1)首先,得實例化一個 FMDatabase對象,這跟Sqlitepersistentobjects 派生一個子類進行操作是不同。接著打開一個數據庫(如果沒有會創建一個數據庫),paths:ios下Document路徑,Document為中ios可讀寫的文件夾,創建數據庫實例 db 這里說明下:如果路徑中不存在“Test.db”的文件,sqlite會自動創建“Test.db”。
(2)接下來,我們可以通過這個數據庫對象進行操作了。操作主要是update和queries。
(3)這樣我們就有了一張表了。接下我們對表進行操作。插入數據!注意插入的數據使用了通配符,這跟 iphone直接使用sqlite借口的綁定變量是一樣的,后面的通配符匹配的數據。
(4)把數據存入數據庫中,插入數據庫中。(5)對數據庫進行查詢操作。
2.3 SBJson的使用
SBJson是Objective-C實現的一個JSON解析器和生成器。JSON是一種數據交換語言,和XML是同樣用途的。不過JSON的體積要比XML小,也就意味著在網絡傳輸中速度會比XML更快。
JSON(JavaScriptObject Notation) 是一種輕量級的數據交換格式[7]。它基于 JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON采用完全獨立于語言的文本格式,但是,也使用了類似于C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的數據交換語言。易于人閱讀和編寫,同時也易于機器解析和生成。
在項目如果要解析json字符串需要創建json對象,調用objectWithString:方法完成json串的轉換。
2.4 自定義Cell的使用
創建一個UITableViewCell的子類[8]:選中Custom Cell目錄,依次選擇File/New /New File,在彈出的窗口,左邊選擇Cocoa Touch,右邊選擇Objective-C class,單擊Next,輸入類名CustomCell,Subclass of選擇UITableViewCell,之后選擇 Next和 Create,就建立了兩個文件:CustomCell.h和CustomCell.m。
(1)創建CustomCell.xib:依次選擇File/New/New File,在彈出的窗口,左邊選擇User Interface,右邊選擇Empty,單擊Next,選擇iPhone,再單擊Next,輸入名稱為CustomCell,選擇好位置,單擊Next,選擇iPhone,再單擊Next,輸入名稱為CustomCell,選擇好位置,拖拽自己想要的控件。
打開CustomCell.h,添加屬性,打開CustomCell.m,向其中添加代碼。
設置重用標志,使得cell可以重用。
在表的代理方法里創建cell對象,并對視圖賦值。
本程序中用到的自定cell的類都放在了cell文件夾里,里面是所有要用的cell,自定義cell可以讓用于看到不同形式的表視圖,增加了內容的閱讀行,使得 ui多樣化,能使整個程序更加美觀。
3.1 編碼風格
本軟件的編碼風格嚴格按照 Objective-C[9]的編碼規范,并注意編寫時的細節,增加代碼的清晰度和易讀性。
(1)類名:
①所有的類名均以大寫字母開頭,多單詞組合時,后面的單詞首字母大寫,類是有意義的。使用駝峰命名法,方法名全部都有特定的涵義和目的,參數和方法都有注釋。
②所有繼承自系統的某類則用某類的名字作為結尾。例如繼承自 UIView 的類以 View 結尾,繼承自ViewController[10]的類以viewController結尾,表示是視圖控制器。
③所有保存數據的實體以 object結尾,并放在 model文件夾中。
(2)常量:
所有的常用數據都進行了宏定義,放在了預編譯頭文件中,當某個類中需要用到的時候,直接調用宏就行。在Define中相類似的定義要對齊。如:

(3)變量:
①變量必須起有意義的名字,使其他組員可以很容易讀懂變量所代表的意義,變量命名可以采用同義的英文命名,可使用幾個英文單詞,第一個單詞首字母小寫,其他單詞首字母大寫。
例如:NSString *username;
②對于一些特殊類型的變量,命名時要帶上類型,如NSArray的變量命名為xxxArray,其他的如xxxDictionary,xxxSize等。這樣就可以從名稱上知道是什么類型的變量。
③對于要和interface builder關聯的的輸出口變量,命名時要后綴以特定的控件名。
例如:IBOutlet UILabel *userNameLabel;
④盡量避免使用全局變量,使用全局變量時,在變量前加一個下劃線,如_dishesArray。
(4)方法:
①方法的名稱使用有意義的單詞組成,且以小寫字母開頭,多單詞組合時,后面的單詞首字母大寫。
例如:-(void)getDishDetail
②設置類變量的內容的方法應使用set作為前綴,讀取變量的內容的方法應使用get作為前綴。
例如:-(void)getDishes;
③方法中的參數:第一個參數名稱要從函數名稱上攜帶出來,第二個參數的首字母小寫,多個單詞組合時,后面單詞首字母大寫。參數有別名時,參數別名與參數名一致,但參數名前綴以_。參數別名與前一參數保留1個空格。參數無別名時,以有意義的字母命名。
例如:
-(void)getDishWithOffest:(NSString *)aOffest limit:(NSString *)aLimit;
(5)方法的定義:
①所有的私有方法和屬性全部定義在.m文件中。
②所有的共有方法和屬性全部定義在.h文件中。
③建立工具類jxxmpp來完成所有xmpp相關的操作。
④使用委托和通知來完成消息的傳遞。
3.2 編碼思想
在編碼中主要采用的是面向對象的思想進行源碼實現的[11]。面向對象的設計方法使得代碼結構好且效率高,例如在解析服務器返回的json數據時,將同屬于一個字典的屬性放到一個數據模型類中,在這個數據模型類中有若干屬性,用于保存該模型在數據庫中的各個字段。在該模型類中實現數據的具體解析,在不同的地方使用的時候,只需要調用該模型類的屬性即可。這樣,減少了重復代碼,也使得代碼的結構更加清晰。
在面向對象設計中,編碼時我還注意使用了各種設計模式:MVC模式、工廠模式、觀察者模式、代理模式和單例模式。
MVC[12]全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯和數據顯式分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在界面和用戶圍繞數據的交互能被改進和個性化定制的同時而不需要重新編寫業務邏輯。MVC被獨特的發展起來用于映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。
MVC模式:即模型、視圖、控制器。模型主要負責數據的存儲,視圖主要負責不同視圖效果的顯示,控制器主要負責不同視圖的承載和切換。這樣做的好處有:①降低代碼的耦合性,實現數據層、視圖層和業務層的分離。視圖層和業務層分離,就能允許更改視圖層代碼而不用重新編譯模型和控制器,同樣,一個應用的業務流程或者業務規則的改變之需要改動MVC的模型層即可。②高重用性和實用性,例如在工程中要實現用新浪微博、豆瓣、QQ3種方式登錄,根據用戶的選擇,改變不同的 WebView,使用同一個viewController,達到了重用的目的。③增加可維護性,由于不同的層各司其職,每一層的應用具有某些不同的特征,有利于代碼的管理、維護。
觀察者模式:在此種模式中,一個目標物件管理所有相依于它的觀察者物件,讓多個觀察者對象同時監聽某一主題對象,這個主題對象在狀態上發生變化時會通知所有的觀察者對象,使他們能夠自動更新自己。例如在工程中,當屏幕旋轉時發出通知,此時,viewController就能夠接收到通知,在需要旋轉的viewController中寫相應的代碼就可以試想不同的視圖效果。
本項目通過使用結構化分析方法進行了需求分析、可行性分析、概要設計、詳細設計,用業務流程圖、數據流圖和功能結構圖清晰地得到了軟件的模塊結構。在設計過程中,從整個程序的結構出發,利用模塊結構圖表述程序模塊之間的關系。
在功能的實現中,多采用 GCD[13]防止程序卡頓,大大提高了用戶體驗,使得整個軟件更加流暢和完美。
在編碼的過程中特別注意運用面向對象分析方法,使代碼結構好且效率高,不僅減少了重復代碼,也使得代碼結構清晰、降低耦合度。在編碼過程中,好的編碼習慣也是非常重要的,增加了代碼的可讀性和可維護性。除此之外,各種設計模式的使用也使得程序更加穩定,代碼更加可行、高效。MVC模式減低了代碼的耦合度,實現了數據層、視圖層和業務層的分離;觀察者模式定義了一種一對多的依賴關系,在觀察者和被觀察者之間建立一個抽象的耦合;代理模式解決了某個類不能靈活地完成具體操作的情況;單例模式實現了整個工程內數據的唯一性,可以從內存中直接讀取到需要的數據,而避免了頻繁地讀寫本地數據庫或者本地 plist文件。在測試時特別注意了不同操作系統和不同分辨率的屏幕的適配的問題。
[1] 劉志富基于xmpp的ios上的IM客戶端的研究與實現[D].華南理工大學.2012:3-5.
[2] 詹雄濤.基于MVC模式的移動業務支撐系統設計[J].福建電腦,2008,24(9):136-137.DOI:10.3969/j.issn.1673-2782.20 08.09.084.
[3] 林云.基于 iOS的房產信息系統設計與實現[D].北京交通大學.2013.56-58.
[4] 趙曉燕.基于XMPP協議網站即時通訊系統的研究與實現[D].大連理工大學.2012.23-78.
[5] 周文永.基于XMPP協議的企業級IM關鍵功能的研究及其在iOS端的實現[D].華南理工大學,2013,12-28.
[6] 李國正.基于手機的移動學習平臺的設計與實現[D].新疆師范大學,2010.89-116.
[7] 張濤,黃強,毛磊雅等.一個基于 JSON的對象序列化算法[J].計算機工程與應用,2009,43(15):98-100,133.
[8] Liquan Shen,Zhi Liu,Tao Yan et al.Early SKIP mode decision for MVC using inter-view correlation[J].Signal Processing. Image Communication,2010,25(2):88-93.
[9] Mark Dalrymple,Scott Knaster.Objective-C基礎教程[M].北京:人民郵電出版社,2012:13-15.
[10] 陳雯菁.一種基于核心節點的信息安全設備聯動協議模型[J].計算機與現代化.2012(12).89-119.
[11] 李小倩.基于 OS架構的在線測試應用軟件設計[D].吉林大學.2012.45-89.
[12] 趙曉燕.基于XMPP協議網站即時通訊系統的研究與實現[D].大連理工大學.2012.23-78.
[13] 賴云剛.方云龍.淺析計算機網絡環境下單位網絡安全和技術[A].巨化集團公司化工學會論文集(九)[C].2011.
TP393.1文獻標志碼:A
2015.03.18)
1007-757X(2015)08-0022-04
河南省科技廳基礎與前沿研究課題(142300410296)
任靖娟(1969-)女,河南省濮陽市人,漢族,碩士研究生,河南中醫學院,實驗師,研究方向:現代教育技術與多媒體技術,鄭州,450046