- [ ] 準備階段:數據層model
?
請求數據-ContactsService
?
- 寫一個mock網絡請求獲取JSON數據的方法:
?
+ (void)getContactsCompleteBlock:(void (^)(ContactsListEntity *contactsListEntity, NSError *error))completeBlock;
?
提示:此方法不需要傳入參數
?
- 方法的實現:使用<ServiceProvider/ServiceProvider> 中network的方法:
?
-(NSURLSessionDataTask *)requestAPI:(NSString *)apiName nameSpace:(NSString *)nameSpace parameters:(NSDictionary *)parameters options:(SPNetworkOptions)options complete:(void (^)(NSURLResponse *, SPNetworkResponseObject *, NSError *))complete {
return [self fetchMockByAPIName:apiName parameters:parameters complete:complete];
}
提示:這里請求的API即為請求的JSON文件的前綴:@"getContactList"
?
- complete block的實現:
獲得的返回的responseObject的entity,并用它初始化contactsListEntity
?
ContactsListEntity *contactsListEntity = [[ContactsListEntity alloc] initWithDictionary:responseObject.entity];
?
沒有出錯的情況下,即error為nil,completeBlock返回contactsListEntity完成回調。
?
?
解析數據
?
1、JSON數據
在工程中對應的mock文件夾中創建getContactList-alimockapi.json文件
- 設計JSON格式
- 一層:array contactList
- 二層:contactList中元素為一個個cell的信息(dictionary)
這里包含信息是,key:contactName、contactId、contactAdd、contactNumber
提示:value都是string類型的。
?
2、ContactsListEntity
- property:
?
@property (nonatomic, strong) NSArray *contacts;
?
- method:重寫AliEntity中的映射方法,這里面解析方法都已經寫好,可以理解為這里是調用一個接口,只需要告訴它名稱的對應關系即可。
?
+(NSDictionary *)arrayItemMap;
?
+(NSDictionary *)propertyMap;
- propertyItemMap 自定義映射關系。這里把JSON中的某數據結構(例如這里是數組:contactList)賦值給ContactsListEntity中名為contacts的成員變量。
return @{@"contactList" : @"contacts"};
- arrayItemMap 定義數組中的item都應該是什么類型。這里是指JSON中對應的數組contactList應該由ContactsInfoEntity組成。
?
?
3、ContactsInfoEntity
- property:
?
@property (nonatomic, copy) NSString *contactName;
@property (nonatomic, copy) NSString *contactId;
@property (nonatomic, copy) NSString *contactNumber;
@property (nonatomic, copy) NSString *contactAddress;
?
- method:重寫Entity中的映射方法。道理同listEntity。
提示:此Entity中的屬性名如果與JSON中相同,則可以省去映射步驟。若不同,則需要單獨處理。
?
+ (NSDictionary *)propertyMap {
return @{@"contactAdd" : @"contactAddress"};
}
?
?
?
?
?
?
- [ ] 準備階段:視圖層view
?
數據綁定-ContactsTableViewCell
?
1、自動調用UITableViewCell初始化方法:
?
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier NS_AVAILABLE_IOS(3_0) NS_DESIGNATED_INITIALIZER;
2、cell初始化函數commonInit:
初始化子view,并將其添加到父視圖
?
_checkContainerView = [UIView new];
[self.contentView addSubview:_checkContainerView];
?
3、設計布局,使用Masonry 添加約束
?
使用mas_maekConstraints設置約束條件:mas_equalTo
示例:
?
[textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(StyleSpacing2);
make.top.mas_equalTo(StyleSpacing4);
make.bottom.mas_equalTo(StyleSpacing4);
make.right.mas_equalTo(StyleSpacing2);
}];
注意添加約束要在addSubview之后。
?
?
4、public method:實現數據綁定
?
- (void)configWithContactsInfoEntity:(ContactsInfoEntity *)entity;
?
將ContactsInfoEntity中屬性值賦值給cell中的lable.text
示例:
?
self.contactName.text = entity.contactName;
提示:cell這里容易出錯,詳見Contacts報錯總結。
?
?
?
?
- [ ] 開始“動工”:控制層controller
控制層-ContactsViewController
?
viewController生命周期:
?
viewDidLoad:
- 初始化tableView
?
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
- 設置tableView的其他屬性(背景顏色、分割樣式等等)
- 給tableView綁定delegate、datasource
?
self.tableView.delegate = self;
self.tableView.dataSource = self;
- 將tableView添加到父視圖
?
[self.view addSubview:self.tableView];
?
- 調用加載數據方法reloadData
?
?
viewDidAppear:
?
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
?
其他生命周期過程省略。
?
?
加載數據-reloadData
?
這個方法是用來加載數據的,數據就是從mock網絡請求獲取而來的,既然如此,那么之前精心準備的ContactsService就華麗登場啦:
?
[ContactsService getContactsCompleteBlock:^(ContactsListEntity *contactsListEntity, NSError *error) {
if (!error) {
NSLog(@"contacts : %@", contactsListEntity);
self.contactsListEntity = contactsListEntity;
[self.tableView reloadData];
} else {
NSLog(@"error : %@", error.localizedDescription);
}
}];
?
請求數據成功之后,在無錯誤的情況下completeBlock執行:把成功返回的contactsListEntity傳給本地的contactsListEntity。
?
?
TableView Delegate&Datasource
- delegate:
?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
?
因為暫無特殊要求,這里高度直接設置為了固定值。
?
?
- datasource:
1、列表行數
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
?
?
列表行數返回的是加載數據成功后的contactListEntity中數組contacts的元素數。
?
return self.contactsListEntity.contacts.count;
}
?
2、cell
?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
?
此時,就要用到之前準備的ASCContactsTableViewCell啦。
先實例化一個它的對象cell:
ContactsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContactsTableViewCell" forIndexPath:indexPath];
?
然后用加載數據成功后的contactListEntity中數組contacts的某個元素內容去構造這個cell,調用ASCContactsTableViewCell類的方法:
[cell configWithContactsInfoEntity:self.contactsListEntity.contacts[indexPath.row]];
?
最后返回這個cell,工程主體就大功告成啦!
?
?
?
?
- [ ] 用起來~
功能入口-AliMyAlibaba
修改view
在頁面內添加一個新的headerButton,與原有的三個button:“Favorite Companies、Favorite Products、Browsing History” 并列放置。

?
?
?
添加響應事件
為新設置的按鈕添加響應方法actContacts
?
- (void)actContacts {//跳轉聯系人頁面
[UT ctrlClicked:@"MyContacts" page:self args:nil];
[AccountHelper executeUserRequiredAction:^{
ContactsViewController *cc= [[ContactsViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:cc animated:YES];
}];
}
這里就實例化了ContactsViewController類的對象,并通過push的方法顯示出來。那么這個功能的入口就寫好了,可以用起來啦~

?
加個聯系人頭像美化一下:
?

?
再添加一個下拉翻頁功能,好啦~任務完成了~
