<轉(zhuǎn)>從Java轉(zhuǎn)iOS第一個項目總結

從Java轉(zhuǎn)iOS第一個項目總結

閱讀目錄

0.前言

1.項目介紹

2.項目使用的第三方開源庫

3.工具和插件介紹

4.集成友盟

5.即時通訊

6.項目總結

0.前言

本人14年12月份觅够,從網(wǎng)站開發(fā)組轉(zhuǎn)到了移動開發(fā)組,自己的java兩年半工作經(jīng)驗變成了object-c零經(jīng)驗巷嚣。2015年1月份新啟動了一個移動項目喘先,年后因為人事變動,自己從輔助開發(fā)變成了"核心"開發(fā)廷粒,目前項目基本接近尾聲窘拯,下面進行總結,希望對一些人能有幫助, 另外也希望ios大牛進行指導

回到頂部

1.項目介紹

項目屬于一款社區(qū)類軟件坝茎,包含小組/帖子涤姊,視頻,文章嗤放,推薦搜索思喊,即時通訊,好友次酌,第三方登錄/分享恨课,推送等,涵蓋常用app的基本功能

回到頂部

2.項目使用的第三方開源庫

http://github.ibireme.com/github/list/ios/整理了比較常用的ios第三方組件岳服,以及github上的統(tǒng)計

項目使用了CocoaPods(類似java中的maven)管理常用的第三方庫,一些特殊的單獨引用,下面介紹下比較好用的幾個

1.AFNetworking

目前比較推薦的ios網(wǎng)絡請求組件剂公,默認網(wǎng)絡請求是異步,通過block回調(diào)的方式對返回數(shù)據(jù)進行處理吊宋。

需要注意的是AFNetworking對網(wǎng)絡請求返回的ContentType要求嚴格纲辽,比如默認只支持application/json的返回。所以可能需要添加對test/html返回的支持璃搜,否則后臺可能無法獲得返回數(shù)據(jù)拖吼。

另外就是文件上傳,這里推薦使用第二種

1

2

3[formData?appendPartWithFormData:?name:];

[formData?appendPartWithFileData:?name:?fileName:?mimeType:];

第一種只需要傳入表單名和文件流腺劣,源碼也是根據(jù)文件流獲得對應的文件名和文件類型然后調(diào)用第二種方法绿贞。但是樓主遇到了使用第一種方法,提交后后臺判斷為非文件上傳橘原,無法獲得文件流籍铁。還有如果后臺是根據(jù)文件后綴文件類型涡上,那么第一種也無法使用。

AFNetworking是異步的拒名,也可以使用同步的網(wǎng)絡請求方法.

2.FMDB

對sqlite數(shù)據(jù)庫操作進行了封裝吩愧,對于做后臺開發(fā)多年的我來說,沒有什么問題增显,看一下就知道怎么用了

3.MBProgressHUD

也是ios項目常用的一個組件雁佳,用于顯示過渡效果的,比較網(wǎng)絡請求之前顯示loding同云,網(wǎng)絡結束隱藏loading糖权。建議封裝在BaseViewController中,所有ViewController繼承就能使用

4.MJRefresh

這個是傳智播客李明杰老師的作品炸站,自己的oc基礎就是看他的視頻半個周末就基本拿下了星澳。MJRefresh主要用于刷新操作,提供了常用的刷新操作旱易,還有刷新動畫禁偎,用著很好用。建議把方法封裝在BaseViewController中阀坏,這樣修改刷新操作時如暖,就只需要改動一份。(之前用的舊版MJRefresh忌堂,只支持普通的刷新盒至,不支持動畫,后來到更新后發(fā)現(xiàn)變化很大浸船,舊的方法已經(jīng)不推薦使用了妄迁,所以還是封裝基類中使用比較好寝蹈,也方便修改)

5.SDWebImage

這個也是ios最常用的一個組件李命,用戶加載網(wǎng)絡圖片,可以緩存到本地箫老。大概原理時封字,第一次加載后,會根據(jù)url加密作為文件名緩存在本地耍鬓,如果再次加載圖片時阔籽,就直接從本地加載。用著也比較簡單牲蜀。這里也分享遇到的一個問題笆制,

先從網(wǎng)絡加載一張小圖,然后小圖作為展位圖涣达,再從網(wǎng)絡加載一張大圖

1

2

3

4

5[imageView?sd_setImageWithURL:[NSURL?URLWithString:imageURLString]?placeholderImage:DefaultPostPic];

[imageView?sd_setImageWithURL:[NSURL?URLWithString:_bigImageURLStringArray[i]]?placeholderImage:imageView.image?options:SDWebImageDelayPlaceholder?completed:^(UIImage?*image,?NSError?*error,?SDImageCacheType?cacheType,?NSURL?*imageURL)?{

}];

6.RDVTabBarController

一個TabBar組件在辆,可以方便設置底部菜單的文字圖片证薇,點擊效果,小紅點提示等

7.Toast

類似android的toast提示效果匆篓,封裝在BaseViewController中浑度,需要的地方進行提示

8.XMPPFramework

ios唯一的xmpp類庫,作者在去年8月份添加了xep-0198協(xié)議支持(流管理鸦概,用于xmpp斷線重連)箩张,但是通過pod進行更新時,無法下載到最新版本窗市,可能0198還沒有完善好先慷,無法作為正式版。

9.TPKeyboardAvoiding

用戶鍵盤彈出自動計算高度咨察,進行屏幕滾動操作

10.AMR

做即時通訊的音頻處理熟掂,目前我們的即時通訊使用的錄音文件是m4a箩朴,便于web端的音頻播放

11.TQRichTextView

用于做富文本視圖控件顯示沮翔,用于即時通訊的表情顯示,以及資源評論的富文本顯示

12.CSGrowingTextView

用作即時通訊文本框和評論文本框使用鸟整,可以顯示多行輸入

13.MJExtension

也是李明杰老師的作品二蓝,用于json轉(zhuǎn)model進行使用誉券,有點類似于java中谷歌的Gson.轉(zhuǎn)換效率據(jù)說也很高,使用也比較簡單刊愚,只要前后臺約定好踊跟,json直接就轉(zhuǎn)成了model。一個工作多年的ios朋友說鸥诽,一個項目主要的是對model層的管理商玫,他推薦的是Mantle。不過MJ這個更輕量級點,用著也更加簡單牡借。

回到頂部

3.工具和插件介紹

Xcode

ios開發(fā)的官方工具拳昌,也沒別的選擇。有些功能確實做的挺帥的钠龙,比如StroyBoard的拖拽事件綁定炬藤。不爽的地方就是沒有代碼格式化,另外點擊方法碴里,可能跑到另外一個類中了I蚩蟆!另外左邊的目錄也不會自動發(fā)生變化咬腋,定位到對應文件羹膳,需要command+shift+j

SimPholders2

可以快速找到模擬器對應的沙盒目錄,啟動后右側(cè)頂部工具欄有個類似關閉按鍵的按鈕根竿,顯示最近的幾個應用陵像,點擊就進入到了對應的沙盒目錄

VVDocumenter-Xcode

xcode工具湃缎,///生成注解模板,xcode這功能都不給集成蠢壹,唉

其他的基本就不用介紹了嗓违,有的也不怎么好用。SVN可以使用Cornerstone图贸,Git可以使用SourceTree蹂季,sqlite可以使用SQLite Professional(不過是收費的,免費的只能查看)疏日,還可以用火狐瀏覽器的sqlite插件偿洁。

回到頂部

4.集成友盟

友盟,提供了App和運用的一站式解決方案沟优。公司上個移動項目用到了友盟的推送服務涕滋,這個項目中, 還使用了分享,第三方登錄的功能挠阁,自己也親自參與到了相關集成宾肺。友盟的開發(fā)者文檔還算是比較全的,遇到問題可以聯(lián)系客服或者到友盟的論壇找解決方案侵俗。

1.關于推送

ios推送分為本地推送和遠程推送锨用,本地推送是指本地自己彈出信息,另外一個就是遠程推送隘谣,當應用未啟動時增拥,也能收到相關推送信息。我們項目沒有使用本地推送寻歧,使用的都是友盟的遠程推送掌栅。包括消息(聊天)和通知(用戶信息通知)中。用戶在聊天過程中码泛,手機除了發(fā)送即時通訊以外猾封,也調(diào)用后臺接口,發(fā)送友盟推送弟晚。另外用戶的帖子忘衍,評論,關注卿城,點贊等都會由后臺調(diào)用友盟的推送。

友盟推送(和友盟地址不同)包括單播铅搓,列播瑟押,和廣播,其中廣播限定次數(shù)每天3次星掰,可以和友盟申請?zhí)岣叽螖?shù)多望,其他不限定次數(shù)嫩舟,目前來看單播速度還是挺快的。使用友盟推送怀偷,需要在蘋果開發(fā)者賬號中家厌,新建兩個推送證書,提交給友盟(友盟有詳細的文檔椎工,可以參考)饭于。可以在友盟后臺维蒙,把測試設備的deviceToken加到友盟推送的后臺(需要64位token掰吕,需要通過方法進行計算,直接在xcode或者ituns中拿到token不行)颅痊,從友盟后臺發(fā)起推送殖熟。

推送的大概流程就是,手機在第一次啟動app的時候開啟推送服務斑响,手機在啟動app的時候菱属,注冊友盟服務,同時把deviceToken提交到自己的后臺舰罚,后臺在可以在需要的時候拿著deviceToken調(diào)用友盟的推送接口照皆,友盟再去發(fā)起蘋果的推送服務,使對應的設備收到遠程推送信息沸停。

我們的推送消息膜毁,自定義消息體和xmpp消息體一樣,除了友盟遠程推送以外愤钾,xmpp也會發(fā)一份瘟滨,兩個消息本地只存儲一份,哪個收到先處理哪個能颁。

2.關于第三方登錄和分享

這塊兒都在友盟的社會化分享中杂瘸,里面也提高了比較全面的文檔。建議第三方分享不用自己特殊設計伙菊,可以使用友盟的默認分享模塊(我們項目的分享模塊自己進行了設計败玉,包括了收藏,所以整塊都需要自定義寫UI和寫分享代碼)镜硕。關于友盟的第三方登錄和分享需要注意的時运翼,QQ和微信登錄分享,都需要手機上安裝應用兴枯,所以需要特殊處理血淌,判斷手機是否安裝應用,否則隱藏相關的圖標,這塊兒友盟的sdk已經(jīng)有相關的判斷方法(應該是友盟集成了QQ和微信悠夯,QQ和微信sdk提供了判斷方法)癌淮。

第三方登錄分享需要到相關的平臺注冊開發(fā)者賬號。微信開發(fā)者賬號(不是訂閱號)的第三方登錄需要交錢才能開通功能沦补,可以支持微信和朋友圈分享乳蓄。QQ開發(fā)者賬號可以支持QQ和QQ空間分享(QQ微博好像需要微博開發(fā)者賬號)。新浪微博需要微博開發(fā)者賬號夕膀。QQ好像需要把測試賬號加成QQ開發(fā)者賬號的好友才能測試虚倒,微博也類似。

第三方登錄自己遇到了QQ提示不是最新版的文本店诗,在友盟論壇中找到了解決方案裹刮。

第三方登錄,我們項目集成了QQ庞瘸,微信捧弃,新浪微博登錄。三個平臺都能獲得用戶的screen_name(用戶名稱)擦囊,另外獲得對應的平臺唯一的id违霞,其中QQ和微信都是openid,新浪是userid瞬场。

第三方分享买鸽,文檔提供了分享圖片,視頻贯被,語音眼五。如果是分享url,需要設置對應平臺的分享地址彤灶,參考解決方案看幼,比如

1

2

3

4[UMSocialData?defaultData].extConfig.qqData.url?=?shareUrl;

[UMSocialData?defaultData].extConfig.qzoneData.url?=?shareUrl;

[UMSocialData?defaultData].extConfig.wechatSessionData.url?=?shareUrl;

[UMSocialData?defaultData].extConfig.wechatTimelineData.url?=?shareUrl;

另外分享到QQ空間,必須制定一張圖片幌陕,否則分享不成功诵姜。

第三方分享建議封裝到一個類中,我們項目是幾個詳情頁都有分享搏熄,評論棚唆,舉報,收藏心例,點贊等功能宵凌。封裝在一個BaseDetailViewController中的,相關頁面繼承契邀,同時傳入對應的資源類型摆寄,只用維護一份代碼。

回到頂部

5.即時通訊

即時通訊網(wǎng)上有第三方的解決方案坯门,比如環(huán)信微饥,融云等。我們是自己搭的xmpp服務器古戴,服務器使用的tigase欠橘,之前寫過相關的博客,自己去年也做了對應的webim现恼。前段時間看了環(huán)信webim的sdk肃续,使用的也是strophe的js類庫,相關實現(xiàn)跟我們的差不多叉袍,不過自己實現(xiàn)的xmpp會遇到了不少問題始锚,比如丟消息。所以如果想比較快速的實現(xiàn)im喳逛,推薦使用第三方的解決方案瞧捌。

移動端的丟消息大概是這個樣子。A和B通訊润文,A發(fā)了一條消息給服務器姐呐,服務器發(fā)給B,但是B網(wǎng)絡不好掉線了典蝌,而服務器卻不知道B退出了(B正常退出會給服務器發(fā)通知)曙砂,所以消息丟失了。XMPP中有xep-0184協(xié)議(消息回執(zhí))骏掀,A給B發(fā)消息鸠澈,消息體中帶一行代碼,要求消息回執(zhí)截驮,當B收到消息后發(fā)送一條回執(zhí)笑陈,證明我收到了。后來XMPP又有了xep-0198協(xié)議(流管理)侧纯,斷線后快速重鏈新锈,同時判斷一定時間收不到消息,就把消息寫離線消息眶熬,減少丟消息情況妹笆。但是可能網(wǎng)絡情況復雜,加上各種不確定因素娜氏,但是還會出現(xiàn)丟消息的問題拳缠。所以目前比較靠譜的方法就是存所有的聊天記錄,由手機端根據(jù)時間點去數(shù)據(jù)庫拉消息贸弥,只要發(fā)出的消息就不會丟窟坐。

這次即時通訊模塊進行了相關改動,也是參考了之前開發(fā)人員的一些建議。比如用戶home返回的時候哲鸳,斷開xmpp連接(ios進入后臺后臣疑,只有5秒的處理時間,特殊方法可延長到10分鐘徙菠,如果內(nèi)存不夠讯沈,應用隨時就被殺死了)。所以返回home時就斷開婿奔,進入應用再連接缺狠。同時應用使用狀態(tài)下,有心跳檢測萍摊,判斷是否保持連接挤茄。用戶聊天除了發(fā)送xmpp消息,同時也調(diào)用遠程push(push設置過期時間冰木,避免特殊情況穷劈,推送延時,聊天結束了才收到推送)片酝。

關于推送囚衔,ios有AppDelage中有兩個方法,一個是使用中收到推送雕沿,不會提示练湿,會直接處理推送信息。另外是程序非使用狀態(tài)审轮,收到推送肥哎,會進行提示,點擊推送進入應用疾渣,調(diào)用對應方法獲得對應的推送消息篡诽,(需要注意,點擊推送啟動應用榴捡,view還沒有加載杈女,消息不能立刻處理)。

所以考慮到ios的特殊性吊圾,采取了xmpp和遠程推送都走的方法达椰,推送的自定義消息體和xmpp消息體一樣,消息的處理方法一樣项乒。一是解決ios應用未啟動時的推送接收啰劲,二是解決xmpp丟消息的問題。

android端因為是真后臺檀何,所以可以后臺一直保持運行蝇裤,android端無論收到xmpp消息還是友盟推送廷支,都是自己處理,然后自己彈一個本地推送(也有弊端栓辜,如果android程序殺死恋拍,就無法接受消息和推送)。ios端因為后臺不可控啃憎,所以推送使用遠程推送芝囤,進入應用再收xmpp全部離線消息(也可能有問題似炎,比如用戶量大辛萍,友盟推送能否保證及時)。當然大部分還是正常情況羡藐,在使用過程中贩毕,就實時收到了xmpp的消息或者遠程推送,直接就提示了仆嗦。只要保證用戶看到的數(shù)據(jù)一致性就行了(所以QQ和微信難以望其項背盎越住)。

根據(jù)測試反饋的情況瘩扼,IOS這個應用的丟消息情況比上個應用有一定改善谆甜。具體情況再進一步觀察把。

我們的即時通訊也包括語音和圖片集绰,采用的是http的解決方案规辱,xmpp也支持二進制的傳輸,但是估計都沒人那樣用栽燕。具體就是先把附件傳到附件服務器拿到附件服務器的地址罕袋,再封裝到消息體。接收方收到消息解析的時候碍岔,再從附件服務器拿到對應的資源浴讯,加載到本地。?同時屏蔽蔼啦,取消屏蔽等一些實時操作也都會發(fā)xmpp榆纽,第一時間雙方更新狀態(tài)。

回到頂部

6.項目總結

目前項目已經(jīng)接近尾聲了捏肢,再過不到半月就要上線了奈籽。自己算是項目的主要負責人了。項目前期ios和android有一周多前期準備和框架搭建猛计,另外就是我根據(jù)頁面原型唠摹,定義接口文檔開發(fā)計劃,協(xié)調(diào)開發(fā)奉瘤」蠢可能大家項目經(jīng)驗也都不多把煮甥,框架和接口或多或少都會有點問題,隨著經(jīng)驗慢慢積累肯定都會越來越好的藕赞。關于IOS的總結下:

1.框架搭建的時候成肘,要考慮好App中各功能點的實現(xiàn)方案。設計好相關文件目錄斧蜕,封裝相關類文件双霍。

2.封裝整理相關方法,比如BaseViewController中包括批销,基本ui洒闸,頂部導航條,左按鈕均芽,右按鈕丘逸,標題,相關點擊事件掀宋,顯示/隱藏loading深纲,網(wǎng)絡請求失敗統(tǒng)一處理方法,上拉/下拉刷新綁定劲妙,刷新顯示/隱藏湃鹊。分析項目中的功能相同模塊,封裝對應操作镣奋,相同功能代碼維護一份币呵。

3.考慮好刷新機制,比如A頁面進入B頁面唆途,B更新后富雅,返回后A頁面的刷新,如果采用block的方法肛搬,可以統(tǒng)一進行設計没佑。或者多個頁面之間的數(shù)據(jù)刷新温赔,采用通知的方式(KVO)蛤奢,進行更新操作。盡量開發(fā)階段陶贼,就把可能出現(xiàn)的問題提前解決啤贩。

4.確定是否進行相關頁面統(tǒng)計,比如加友盟的頁面統(tǒng)計拜秧,需要設置相關view的viewWillAppear和viewWillDisappear()

5.ViewController中初始化view和數(shù)據(jù)請求后刷新view分離痹屹,封裝和整理好網(wǎng)絡請求前和請求后的相關操作,考慮下拉刷新頁面和上拉加載更多的相關數(shù)據(jù)處理和view顯示枉氮。有網(wǎng)下的數(shù)據(jù)緩存以及無網(wǎng)下的緩存數(shù)據(jù)加載

6.提前做好相關頁面的跳轉(zhuǎn)志衍,以及代碼解耦暖庄,需要不斷優(yōu)化和重構代碼。如果發(fā)現(xiàn)問題或者有更好的解決方案楼肪,盡量早期就進行修改培廓,避免修修補補,代碼不便于后期維護和擴展春叫。在可以接受的情況下肩钠,可以犧牲一些系能,保持邏輯簡單暂殖,便于維護价匠。

7.通過代碼寫view計算坐標時,盡量參考上一個元素的坐標和寬高央星,這樣當一個元素位置或?qū)捀甙l(fā)生變化時霞怀,其他元素基本都能隨著發(fā)生變化。

8.數(shù)據(jù)處理能放在服務器端處理就由服務器端處理莉给,前臺就進行無腦顯示

9.考慮程序的兼容性,32位和64位一些變量的值不同廉沮,注意值的越界問題颓遏。注意程序的內(nèi)存問題,和使用過程中的內(nèi)存變化

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滞时,一起剝皮案震驚了整個濱河市叁幢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坪稽,老刑警劉巖曼玩,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窒百,居然都是意外死亡黍判,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門篙梢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顷帖,“玉大人,你說我怎么就攤上這事渤滞”岫眨” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵妄呕,是天一觀的道長陶舞。 經(jīng)常有香客問我,道長绪励,這世上最難降的妖魔是什么肿孵? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任论咏,我火速辦了婚禮,結果婚禮上颁井,老公的妹妹穿的比我還像新娘厅贪。我一直安慰自己,他們只是感情好雅宾,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布养涮。 她就那樣靜靜地躺著,像睡著了一般眉抬。 火紅的嫁衣襯著肌膚如雪贯吓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天蜀变,我揣著相機與錄音悄谐,去河邊找鬼。 笑死库北,一個胖子當著我的面吹牛爬舰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寒瓦,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼情屹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杂腰?” 一聲冷哼從身側(cè)響起垃你,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喂很,沒想到半個月后惜颇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡少辣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年凌摄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毒坛。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡望伦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出煎殷,到底是詐尸還是另有隱情屯伞,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布豪直,位于F島的核電站劣摇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弓乙。R本人自食惡果不足惜末融,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一钧惧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勾习,春花似錦浓瞪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至艺栈,卻和暖如春英岭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背湿右。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工诅妹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毅人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓吭狡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親堰塌。 傳聞我的和親對象是個殘疾皇子赵刑,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容