步驟:發(fā)微博01-導(dǎo)航欄內(nèi)容 -> 發(fā)微博02-自定義TextView -> 發(fā)微博03-完善TextView和發(fā)送微博按鈕 -> 發(fā)微博04-顯示工具條 -> 發(fā)微博05-封裝工具條和相冊 -> 發(fā)微博06-發(fā)送微博
發(fā)微博01-導(dǎo)航欄內(nèi)容
APP的演示操作:

從APP的演示操作中可知,當(dāng)點(diǎn)擊tabBar的“+”按鈕時APP會以modal的方式跳轉(zhuǎn)到發(fā)微博的控制器。實(shí)現(xiàn)代碼如下:

在HMComposeViewController類的viewDidLoad方法中,設(shè)置導(dǎo)航欄內(nèi)容,并添加輸入控件(用于輸入微博正文),如下:

HMComposeViewController類的初始化方法如下:


發(fā)微博02-自定義TextView
APP的演示操作:

前文中,已經(jīng)初步添加了輸入控件UITextView,但是輸入控件UITextView并不能完全滿足我們的要求,即無法實(shí)現(xiàn)占位文字。
所以,新建了一個繼承自UITextView的HMTextView類,將占位文字的實(shí)現(xiàn)以及輸入控件的具體邏輯都封裝到HMTextView類中,只將占位文字和占位文字顏色兩個屬性提供給外界(HMComposeViewController類)使用。如下:

在HMTextView類中,占位文字的實(shí)現(xiàn)有多種方式:第一種是添加UILabel,第二種是重寫drawRect:方法。在這里,我們采用的是第二種方式。重寫drawRect:方法,如下:

觀察APP的演示操作,一開始進(jìn)入發(fā)微博界面時,輸入控件上顯示的是“分享新鮮事”,當(dāng)我們輸入文字后,“分享新鮮事”就會“消失”。這里的實(shí)現(xiàn)原理是通知。具體代碼如下:

注意:這里不適合使用代理,用通知即可。發(fā)出通知后,會觸發(fā)textDidChange事件,然后重新調(diào)用drawRect方法進(jìn)行重繪。
發(fā)微博03-完善TextView和發(fā)送微博按鈕
APP的演示操作:

在前文的基礎(chǔ)上繼續(xù)完善輸入控件,并且當(dāng)有輸入文字后,導(dǎo)航欄的右邊發(fā)送按鈕可以響應(yīng)(發(fā)送微博)。
參考前面,HMComposerViewController監(jiān)聽輸入文字同樣是采用通知的方式。如下:

其中,textDidChange方法的具體代碼如下:

在HMComposerViewController中,監(jiān)聽方法send是用于發(fā)送微博,具體代碼如下:

說明:
1.完善前文中設(shè)置導(dǎo)航欄內(nèi)容的代碼,要考慮是否有微博名,如下:

2.HMTextView類聲明了兩個屬性placedholder和placedholderColor,由于這兩個屬性不是系統(tǒng)屬性,所以在優(yōu)先級上會較低,我們有時候需要重寫它們的setter方法,如下:

3.每一次使用通知,都要注意調(diào)用dealloc方法,移除觀察者。如下:

發(fā)微博04-顯示工具條
APP的演示操作:

仔細(xì)觀察APP的演示操作,工具條一開始是顯示在屏幕底部,當(dāng)鍵盤彈出時工具條才移動到鍵盤的頂部。
在HMComposeViewController的viewDidLoad方法添加工具條,如下:

其中,setupToolBar方法如下:

問題:對于工具條的類HMComposerToolbar暫時不要考慮,先弄明白為什么當(dāng)鍵盤一出現(xiàn)工具條就會移動鍵盤的頂部?實(shí)現(xiàn)原理是什么?
思路:
1.鍵盤會在進(jìn)入發(fā)微博頁面后就彈出是因?yàn)檎{(diào)用了viewDidAppear:方法,如下:

2.彈出鍵盤后移動工具條,這是因?yàn)楫?dāng)鍵盤的frame發(fā)生改變時就會發(fā)出通知UIKeyboardWillChangeFrameNotification,觸發(fā)keyboardWillChangeFrame:事件, 執(zhí)行動畫移動工具條,如下:

其中,keyboardWillChangeFrame:方法,如下:

在HMComposerToolbar類(繼承自UIView)中,設(shè)置工具條上的按鈕。具體代碼如下:
@implementation HMComposeToolbar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"compose_toolbar_background"]];
//初始化按鈕
[self setupBtn:@"compose_camerabutton_background" highImage:@"compose_camerabutton_background_highlighted"];
[self setupBtn:@"compose_toolbar_picture" highImage:@"compose_toolbar_picture_highlighted"];
[self setupBtn:@"compose_mentionbutton_background" highImage:@"compose_mentionbutton_background_highlighted"];
[self setupBtn:@"compose_trendbutton_background" highImage:@"compose_trendbutton_background_highlighted"];
[self setupBtn:@"compose_emoticonbutton_background" highImage:@"compose_emoticonbutton_background_highlighted"];
}
return self;
}
/**
* 創(chuàng)建一個按鈕
*/
- (void)setupBtn:(NSString *)image highImage:(NSString *)highImage
{
UIButton *btn = [[UIButton alloc] init];
[btn setImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
[self addSubview:btn];
}
/**
* 設(shè)置按鈕的尺寸
*/
- (void)layoutSubviews
{
[super layoutSubviews];
//設(shè)置按鈕的frame
NSUInteger btnCount = self.subviews.count;
CGFloat btnW = self.size.width / 5;
CGFloat btnH = self.size.height;
for (int i = 0; i< btnCount; i++) {
UIButton *btn = self.subviews[i];
btn.x = i * btnW;
btn.y = 0;
btn.width = btnW;
btn.height = btnH;
}
}
@end
發(fā)微博05-封裝工具條和相冊
APP的演示操作:

仔細(xì)觀察APP的演示操作,在輸入文字下面添加了相冊,用于顯示發(fā)微博的圖片。而工具條上的按鈕也可以響應(yīng)某些事件。其實(shí)現(xiàn)過程相當(dāng)復(fù)雜。
在HMComposeViewController的viewDidLoad方法添加相冊,如下:

其中,setupPhotosView方法如下:

在HMComposePhotosView(繼承自UIView)中,添加圖片到發(fā)微博的相冊中,設(shè)置圖片的frame。關(guān)鍵代碼如下:

其中,要將方法addPhoto提供外界,用于從外界添加圖片。
在HMComposeToolbar類,完善之前的代碼,使得工具條上的按鈕可以響應(yīng)。不同于之前所用到的通知,這里要通過代理來實(shí)現(xiàn)按鈕的點(diǎn)擊事件。
過程:
1.聲明代理協(xié)議和代理屬性,具體代碼如下:

2.通知代理對象,具體代碼如下:

說明:由于使用到btn.tag,所以要對之前的代碼進(jìn)行完善,如下:

在HMComposeViewController中,遵守HMComposeToolbarDeleagate代理協(xié)議,實(shí)現(xiàn)代理方法,如下:

其中,openCamera和openAlbum方法分別對應(yīng)工具條上的“拍照”和“相冊”按鈕。具體代碼如下:

openImagePickerController:設(shè)置代理,遵守
UINavigationControllerDelegate和UIImagePickerControllerDelegate代理協(xié)議,實(shí)現(xiàn)代理方法imagePickerController:didFinishPickingMediaWithInfo:方法,如下:

在imagePickerController:didFinishPickingMediaWithInfo:方法中,取出系統(tǒng)相冊里的圖片后,調(diào)用HMComposePhotosView類的addPhoto方法,將圖片添加到發(fā)微博的相冊photosView中。
發(fā)微博06-發(fā)送微博
APP的演示操作:

仔細(xì)觀察APP的演示操作,此時發(fā)微博除了發(fā)送文字,還可以發(fā)送圖片。截圖如下:

實(shí)際上,在前文的send方法中的api接口是沒辦法發(fā)送圖片的,需要另外一個接口。這就需要我們考慮兩種情況(有圖片和沒圖片)。
完善send方法,具體代碼如下:

其中,sendWithImage方法如下:

sendWithoutImage方法如下:

說明:
1.發(fā)送帶有圖片的微博,需要將圖片上傳到新浪的服務(wù)器。
這就涉及HMComposePhotosView類,需要HMComposePhotosView類提供photos屬性給外界用來獲取圖片資源。
由于外界沒必要對圖片資源進(jìn)行修改,只需要獲取即可。所以對photos屬性進(jìn)行特殊聲明(readonly)。如下:

并且要完善下addPhoto方法的代碼,如下:

總結(jié):主要掌握好工具條的設(shè)置和如何移動,并且進(jìn)一步加深對readonly屬性的認(rèn)識。