團(tuán)購01 基本數(shù)據(jù)
效果展示:
01 展示基本數(shù)據(jù)
題外話: 我們上面有一個(gè)播放廣告的地方是利用我們的
tableView
的一個(gè)head...控件實(shí)現(xiàn)的, 后面也有一個(gè)foot....
其實(shí)自定義cell
有兩種方法:
- 通過
Xib
創(chuàng)建 - 通過代碼創(chuàng)建
決定是用這兩種的方法的其中一種的根據(jù)我們的所寫的程序決定的
如果是像上面的這種(所有的cell
都比較類似, 我們就用Xib
, 如果每一個(gè)cell
不一樣, 我們就用代碼來創(chuàng)建)
**開始編寫: **
1. 界面設(shè)計(jì):
storyboard
就是一個(gè)簡單的tableView直接拖進(jìn)去就行了
Xib文件
: 我們在創(chuàng)建Xib
之后, 注意的是這里面不是我們以前說的將一個(gè)UIView
拖進(jìn)去, 而是選擇UITableViewCell
然后, 設(shè)置它里面的控件: 具體的格式是:
2. 代碼的編寫:
上一個(gè)程序中, 我們介紹過有關(guān)于cell
的緩存池, 當(dāng)然也是需要標(biāo)識的. 觀察一下我們在加載我們的Xib
的時(shí)候, 貌似沒有告訴我們的系統(tǒng), 我們加載的這個(gè)自定義cell
沒有標(biāo)識: (這個(gè)里面同樣也牽扯到封裝的原理: 我們將創(chuàng)建cell
的方式給封裝了起來, 后面我將介紹到)
所以我們要在Xib
的這個(gè)位置設(shè)置標(biāo)識:
剩下的都是我們在應(yīng)用管理中的Xib
的一些步驟:
創(chuàng)建新的類, 用來封裝我們的cell
相關(guān)代碼
這里面也包括了一些新的代碼, 在最后, 我會將所有的代碼全部寫在這個(gè)上面的
團(tuán)購 02 添加加載更多功能
2. 1 我們利用TableView
的footerView
來完成我們后面的加載數(shù)據(jù)
**第一種方法: **
就是直接使用footerView
創(chuàng)建一個(gè)加載更多的按鈕:
設(shè)置tableView尾部顯示的控件(tableFooterView的寬度永遠(yuǎn)是tableView的寬度)
tableFooterView只需要設(shè)置高度
UIButton *footerBtn = [UIButton buttonWithType:UIButtonTypeSystem];
footerBtn.frame = CGRectMake(0, 0, 0, 35);
footerBtn.backgroundColor = [UIColor orangeColor];
[footerBtn setTitle:@"加載更多團(tuán)購" forState:UIControlStateNormal];
但是這樣做的不好的地方在于, 顯示的寬度是我們的整個(gè)手機(jī)的屏幕. 而且是我們無法修改的
**第二種方法: **
第二種方法就是創(chuàng)建Xib
直接創(chuàng)建一個(gè)Xib
文件, 將我們想要界面用Xib
給描述出來就可以了
UINib *nib = [UINib nibWithNibName:@"MJTgFooterView" bundle:[NSBundle mainBundle]];
// 創(chuàng)建nib對象
UINib *nib = [UINib nibWithNibName:@"GJTgFooterView" bundle:nil];
// 加載xib\nib
UIView *footerView = [[nib instantiateWithOwner:nil options:nil] lastObject];
self.tableView.tableFooterView = footerView;
**第三種方法: **
也是利用Xib
創(chuàng)建footerView
但是這個(gè)與上一個(gè)方法之間的區(qū)別就是很完美的封裝在不同的類中, 這個(gè)我們的控制器就只需一行代碼就可以直接調(diào)用了,這個(gè)封裝還有效的將我們后面的加載更多數(shù)據(jù)的內(nèi)容也給很好的封裝了
題外話:
現(xiàn)在的我們只是做一些簡單的程序所以我們的代碼文件都是隨意放置的, 今天就說一下關(guān)于文件的如果放置
首先, 放置不同的文件夾規(guī)律是按照我們的MVC的來放置例如:
02. 2. 關(guān)于我們footerView
的 Xib的創(chuàng)建步驟:
首先是Xib
的直接創(chuàng)建
1. 上面中的1就是加載更多的數(shù)據(jù)而這個(gè)控件是直接是這個(gè)`Xib的子類
而我們后面的兩個(gè)控件: (菊花\正在拼命加載)是我們的正在加載提示的子控件
這樣做是為了, 將來在數(shù)據(jù)加載的時(shí)候, 這兩個(gè)控件, 要么一起出來 , 要么就不出來, 注意的是, 我們的正在加載提示這個(gè)控件是個(gè)UIView
但是這個(gè)控件默認(rèn)情況下是hidden
無法顯示, 唯有我們點(diǎn)擊了 加載數(shù)據(jù)這個(gè)按鈕, 他才會顯示出來
這里我們再回憶一次如果用Xib
來封裝一個(gè)view
:
我們牽扯到一個(gè)如何更新數(shù)據(jù), 更新什么數(shù)據(jù)???
/**
* 加載更多的數(shù)據(jù)
*/
- (void)loadingMoreData
{
// 1.添加更多的模型數(shù)據(jù)
GJTg *tg = [[GJTg alloc] init];
tg.icon = @"ad_01";
tg.title = @"新增加的團(tuán)購數(shù)據(jù)..";
tg.price = @"100";
tg.buyCount = @"0";
[self.tgs addObject:tg];
// 2.刷新表格(告訴tableView重新加載模型數(shù)據(jù), 調(diào)用tableView的reloadData)
[self.tableView reloadData];
}
這個(gè)是我們UIView控制器中的代碼, 這個(gè)方法就是更新數(shù)據(jù)的
方法
/**
* 點(diǎn)擊"加載"按鈕
*/
- (IBAction)loadBtnClick {
// 1.隱藏加載按鈕
self.loadBtn.hidden = YES;
// 2.顯示"正在加載"
self.loadingView.hidden = NO;
// 3.顯示更多的數(shù)據(jù)
// GCD
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 3.0s后執(zhí)行block里面的代碼
[self.controller loadingMoreData];
// 4.顯示加載按鈕
self.loadBtn.hidden = NO;
// 5.隱藏"正在加載"
self.loadingView.hidden = YES;
});
}
注意, 這里面是牽扯到一個(gè)界面的變換
如果我們點(diǎn)擊了, 下面的加載更多數(shù)據(jù), 就會顯示正在加載提示的那個(gè)UIView
然后進(jìn)過三秒鐘之后(這個(gè)使用我們的block實(shí)現(xiàn)的)顯示出新的數(shù)據(jù).
而更新數(shù)據(jù)的方法在我們的UIView的控制器中, 我們在Xib
控制器中的這個(gè)方法是如果拿到, 我們的UIView
的方法呢???
這個(gè)有兩種方法:
- 直接將我們的控制器給我們的
Xib
控制器:
- 首先, 讓我們的這個(gè)方法暴露在外面(使任何類都可以訪問)
#import <UIKit/UIKit.h>
@interface GJViewController : UIViewController
- (void)loadingMoreData;
@end
- 然后拿到我們的
UIView
的控制器:
#import <UIKit/UIKit.h>
@class GJViewController;
@interface GJTgFooterView : UIView
/**
* 快速創(chuàng)建一個(gè)footerView對象
*/
+ (instancetype)footerView;
@property (nonatomic , strong) GJViewController *controller;
@end
就可以調(diào)用我們的這個(gè)方法了, 代碼如上面
但是上面的這種方法, 會導(dǎo)致我們的代碼耦合性強(qiáng), 所以不建議使用
所以我們要推薦使用第二種方法:
第二種方法就是利用代理模式即是我們下面要講的內(nèi)容:
團(tuán)購 03 代理設(shè)計(jì)模式
誰代理誰???
其實(shí)是我們的控制器代理我們的Xib
控制器(footerView`)
只有當(dāng)我們的footerView`被點(diǎn)擊之后 , 我們的控制器監(jiān)聽這個(gè)點(diǎn)擊事件, 然后做出反應(yīng)(調(diào)用相應(yīng)的方法)
**代碼分析: **
GJFooterView.h文件
/**
1.協(xié)議名稱: 控件類名 + Delegate
2.代理方法普遍都是@optional
3.
*/
@protocol GJTgFooterViewDelegate <NSObject>
@optional
- (void)tgFooterViewDidClickedLoadBtn:(GJTgFooterView *)tgFooterView;
@end
@interface GJTgFooterView : UIView
@property (nonatomic, weak) id<GJTgFooterViewDelegate> delegate;
@end
*GJViewController.m文件代碼: *
footer.delegate = self;
這個(gè)就是我們利用代理的一部分代碼:
首先, 說明這只是一層重構(gòu), 后面我們會繼續(xù)重構(gòu)
其次:
@property (nonatomic, weak) id<GJTgFooterViewDelegate> delegate;
這一段代碼的中為什么要用id
和遵守這個(gè)協(xié)議<GJTgFooterViewDelegate>
???
- 用
id
可以讓我們充當(dāng)footerView
的代理的類, 不受限制.就是任何類都可以充當(dāng)我們footerView
的代理 - 遵守這個(gè)協(xié)議, 是為了告訴我們的
footerView
調(diào)用代理的哪一個(gè)方法
[self.delegate loadingMoreData];
而我們上面所寫的協(xié)議,只有這一個(gè)方法, 而這個(gè)方法名稱和我們的控制器里面的方法名稱一樣 .
而且, 我們在控制器中的代碼:
@interface GJViewController () <UITableViewDataSource, GJTgFooterViewDelegate>
footer.delegate = self;
這個(gè)代碼的含義就是告訴我們的控制器, 我們的footerView
的代理就是他自己
那么, 當(dāng)我們的footerView
的按鈕被點(diǎn)擊之后 , 它就會直接調(diào)用這個(gè)方法了.
團(tuán)購 04 頭部控件
頭部文件其實(shí)就是一個(gè)圖片輪播器, 這個(gè)我們就不多介紹了, 但是我們要說的是那個(gè)圖片輪播器下面的猜你喜歡是怎么做出來的
其實(shí)就是一個(gè)簡單的UIView
做出來的, 只是這個(gè)UIView
的高度為1而已, 當(dāng)你將UIView
的高度設(shè)置為1的時(shí)候, 可能發(fā)現(xiàn)他的線條比較粗,所以, 建議再將他的透明度設(shè)為0.5這個(gè)就可以達(dá)到效果了,
還有就是我們的圖片輪播器的代碼在哪里寫???
#import "GJTgHeaderView.h"
@interface GJTgHeaderView()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@end
@implementation GJTgHeaderView
+ (instancetype)headerView
{
return [[[NSBundle mainBundle] loadNibNamed:@"GJTgHeaderView" owner:nil options:nil] lastObject];
// headerView.scrollView
}
/**
* 當(dāng)一個(gè)對象從xib中創(chuàng)建初始化完畢的時(shí)候就會調(diào)用一次
*/
- (void)awakeFromNib
{
// 在這里面添加圖片輪播器
}
@end
我們圖片輪播器的代碼就在上面的那個(gè)方法中寫:
作者說:
這次講的是團(tuán)購, 來了解如果自定義一個(gè)簡單的cell
下次我們介紹的是如果利用自定義cell
做一個(gè)微博的簡單界面.