需求詳解: 在實際開發中,有可能是在後期優化的時候,會有這麼需要優化的需求:聊天輸入框保存之前輸入的文本,提高用戶的良好體驗。 在聊天模塊中,用戶可能會在輸入框輸入若幹字元,但是沒有點擊發送就點擊退出聊天,或者要點擊用戶頭像確認用戶的信息,或者比如需要向好友發送另一個好 友的ID不得不暫時退出當前好 ...
需求詳解:
在實際開發中,有可能是在後期優化的時候,會有這麼需要優化的需求:聊天輸入框保存之前輸入的文本,提高用戶的良好體驗。
在聊天模塊中,用戶可能會在輸入框輸入若幹字元,但是沒有點擊發送就點擊退出聊天,或者要點擊用戶頭像確認用戶的信息,或者比如需要向好友發送另一個好 友的ID不得不暫時退出當前好友聊天界面跳轉找到別的界面找ID,然而當前聊天輸入框也已經輸入好了若幹字元,用戶當然不希望退出之後就刪除之前輸入好的 文字。所以這裡就需要暫時保存用戶輸入好的但是沒有發送出去的字元串。
但是,還需要滿足1、完全殺掉或者完全退出應用就需要清楚這個暫時保存的字元串,2、發送出去之後,肯定就要delegate之前暫時保存的字元串嘍。
開始:
這部分邏輯的實現一開始我沒怎麼比較好的頭緒,只想到本地序列化,但實際上這個還不算是最好的思路,因為本地序列化用到這裡有點小題大做了,其實只要用全局靜態變數的字典就可以了。
具體實現的邏輯,我也特意閱讀研究了Coding項目的實現,畢竟這個項目是比較成熟的項目,聊天模塊也做的很不錯,所以學學別人的思想,正所謂站在巨人的肩膀上,也是很好的哦。
那麼下麵,我就直接解讀Coding源碼(學習Coding-iOS開源項目日誌(一))在這個聊天模塊內容保存的邏輯吧,就不拿自己工作開發的項目來講了。
1、首先聲明全局static的變數,Coding中用inputStrDict存儲輸入框的字元串,而inputMediaDict我暫時不知道它具體存什麼的,應該是media之類的元素:
2、然後將很多邏輯封裝在這個UIMessageInputView類中,方法都不用公開,完全利用UIMessageInputView活動周期的邏輯就可以了。
1 #pragma mark remember input
2
3 - (NSMutableDictionary *)shareInputStrDict{
4 if (!_inputStrDict) {
5 _inputStrDict = [[NSMutableDictionary alloc] init];
6 }
7 return _inputStrDict;
8 }
9
10 - (NSMutableDictionary *)shareInputMediaDict{
11 if (!_inputMediaDict) {
12 _inputMediaDict = [[NSMutableDictionary alloc] init];
13 }
14 return _inputMediaDict;
15 }
16
17 - (NSString *)inputKey{
18 NSString *inputKey = nil;
19 if (_contentType == UIMessageInputViewContentTypePriMsg) {
20 inputKey = [NSString stringWithFormat:@"privateMessage_%@", self.toUser.global_key];
21 }else{
22 if (_commentOfId) {
23 switch (_contentType) {
24 case UIMessageInputViewContentTypeTweet:
25 inputKey = [NSString stringWithFormat:@"tweet_%@_%@", _commentOfId.stringValue, _toUser.global_key.length > 0? _toUser.global_key:@""];
26 break;
27 case UIMessageInputViewContentTypeTopic:
28 inputKey = [NSString stringWithFormat:@"topic_%@_%@", _commentOfId.stringValue, _toUser.global_key.length > 0? _toUser.global_key:@""];
29 break;
30 case UIMessageInputViewContentTypeTask:
31 inputKey = [NSString stringWithFormat:@"task_%@_%@", _commentOfId.stringValue, _toUser.global_key.length > 0? _toUser.global_key:@""];
32 break;
33 default:
34 break;
35 }
36 }
37 }
38 return inputKey;
39 }
40
41 - (NSString *)inputStr{
42 NSString *inputKey = [self inputKey];
43 if (inputKey) {
44 DebugLog(@"inputStr_get:%@",[[self shareInputStrDict] objectForKey:inputKey]);
45 return [[self shareInputStrDict] objectForKey:inputKey];
46 }
47 return nil;
48 }
49
50 - (void)deleteInputData{
51 NSString *inputKey = [self inputKey];
52 DebugLog(@"inputKey_delegate:%@",inputKey);
53 if (inputKey) {
54 [[self shareInputStrDict] removeObjectForKey:inputKey];
55 [[self shareInputMediaDict] removeObjectForKey:inputKey];
56 }
57 }
58
59 - (void)saveInputStr{
60 NSString *inputStr = _inputTextView.text;
61 NSString *inputKey = [self inputKey];
62 DebugLog(@"inputKey_save:%@",inputKey);
63 if (inputKey && inputKey.length > 0) {
64 if (inputStr && inputStr.length > 0) {
65 [[self shareInputStrDict] setObject:inputStr forKey:inputKey];
66 }else{
67 [[self shareInputStrDict] removeObjectForKey:inputKey];
68 }
69 }
70 }
71
72 - (void)saveInputMedia{
73 NSString *inputKey = [self inputKey];
74 if (inputKey && inputKey.length > 0) {
75 if (_mediaList.count > 0) {
76 [[self shareInputMediaDict] setObject:_mediaList forKey:inputKey];
77 }else{
78 [[self shareInputMediaDict] removeObjectForKey:inputKey];
79 }
80 }
81 }
82
83 - (NSMutableArray *)inputMedia{
84 NSString *inputKey = [self inputKey];
85 if (inputKey) {
86 return [[self shareInputMediaDict] objectForKey:inputKey];
87 }
88 return nil;
89 }
90
91 - (void)setToUser:(User *)toUser{
92 _toUser = toUser;
93 NSString *inputStr = [self inputStr];
94 if (_inputTextView) {
95 if (_contentType != UIMessageInputViewContentTypePriMsg) {
96 self.placeHolder = _toUser? [NSString stringWithFormat:@"回覆 %@", _toUser.name]: @"撰寫評論";
97 }else{
98 self.placeHolder = @"請輸入私信內容";
99 }
100 _inputTextView.selectedRange = NSMakeRange(0, _inputTextView.text.length);
101 [_inputTextView insertText:inputStr? inputStr: @""];
102
103 _mediaList = [self inputMedia];
104 [self mediaListChenged];
105 }
106 }
上面無非就是通過聊天對象的名字拼接成key值,然後對應存儲當前輸入框的字元串到全局static的字典中,然後是取出、刪除的幾個方法。
3、再看看那哪些地方調用了這些方法:
保 存的方法,放在frame重寫的方法里,因為輸入框會隨著鍵盤的現實和隱藏而切換frame,不過我公司的項目一開始聊天模塊是我同事開發的,我發現他用 Masonry的佈局代碼去變換輸入框的位置,選擇了佈局約束也就意味著放棄了frame,所以何處調用save方法還是要根據實際需求和實際的編碼實 現。另外,其實在最開始開發這個輸入框的時候,可以考慮其運作的周期:開始編輯->正在編輯->結束編輯,這些運作周期是可以實現出各自的方 法,就和一個控制器的生命周期一樣。總之思路很多,做好是能實現出好管理好維護的邏輯。
然後找找刪除的方法,刪除的方法是放在將字元串發出去的最前面,因為已經發送出去了,是可以將字典中存儲的元素刪除了去。
另外,在創建key的時候,這個key字元串是依賴當前聊天對象的,因為當前輸入框的內容要和當前好友對象一一對應,不能我保存了當前好友對應的輸入框內容,跳到別的好友卻又出現了一樣的內容。所以key值需要依據當前好友的字元串來決定,所以Coding源碼中重寫了ToUser屬性的set方法:
尊重勞動成果:http://www.cnblogs.com/goodboy-heyang/p/5782201.html