QQ列表代码不难,思路上可能会要想一下下,思路上的难点:列表的展开和闭合,这里需要用到代理或者通知,在以下中会用多种方式来仔细分析详细过程.
问题小结:在.h中声明的成员属性和在.m中声明的成员属性的区别?
如下所示:
.h文件:
// // HMSectionHeaderView.h // qq列表第二次 // // Created by 曹魏 on 2016/11/12. // Copyright © 2016年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @class HMFriendGroup; @interface HMSectionHeaderView : UITableViewHeaderFooterView @property (nonatomic,strong)HMFriendGroup *friendGroup; @end
.m文件
// HMSectionHeaderView.m // qq列表第二次 // // Created by 曹魏 on 2016/11/12. // Copyright © 2016年 itcast. All rights reserved. // #import "HMSectionHeaderView.h" #import "HMFriendGroup.h" @interface HMSectionHeaderView () @property (nonatomic,strong)HMFriendGroup *friendGroup; @end
答案:问题很简单,其实也就是.h和.m文件中声明属性的区别,我们知道,在.h中声明属性是全局的,而.m中声明的属性是局部的,全局属性可以被子类继承,而局部的只能
在当前文件中使用,仅此而已.
知识点(一):静态单元格:
静态单元格就是UITableview的cell,cell分为动态和静态,动态就是用代码写的,静态就是直接在storyBoard中设置的,但只能设置UITableviewController,不能在UIviewController上拖个tableView,否则是会报错的
知识点(二):原型cell和静态cell和默认cell
默认cell:就是用代码写
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1.定义一个重用标识符 static NSString *reuseID = @"cell"; //2.根据重用标识符获取重用cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseID]; //3.判断是否有重用cell if (!cell) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseID]; } //4.赋值 HMFriendsGroup *friendsGroup = self.dataArray[indexPath.section]; HMFriends *friends = friendsGroup.friends[indexPath.row]; cell.imageView.image = [UIImage imageNamed:friends.icon]; cell.textLabel.text = friends.name; cell.detailTextLabel.text = friends.intro; return cell; }
原型cell:系统在获取重用cell这一步的时候(就是上述代码的第二步),会先从SB中找是否有重用标识符,如果有就加载SB中的cell,这个cell就成为原型cell,
注意点:两种获取重用cell的方法的区别:
//2.根据重用标识符获取重用cell //这句话写完后同样也会去SB中找重用标识符,如果有,就加载原型cell,如果没有就自己创建. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseID];
//forIndexPath 多了这样一个参数-->参数的用处,首先indexPath无论有任何值,都没有任何意义,它在这里的唯一作用,就是用来判断,是否是从原型cell中进行创建
如果我这样设置了,但没有在storyBoard中设置重用标识符,会报错的,这个参数的作用其实就是:去找重用标识符,找不到就报错,因为有了这个参数就告诉你我就是要用原型cell的,其他都不行.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1. 定义重用标识 static NSString *reuseId = @"friendGroup"; //2. 根据重用标识获取重用cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath]; // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId]; //3. 设置数据 //3.1 获取控件 UIImageView *imageView = [cell viewWithTag:10]; UILabel *nameLabel = [cell viewWithTag:20]; UILabel *dLabel = [cell viewWithTag:30]; // 3.2 获取数据 HMFriendGroup *friendGroup = self.friendGroupArray[indexPath.section]; HMFriend *friend = friendGroup.friends[indexPath.row]; //3.3 给控件设置数据 imageView.image = [UIImage imageNamed:friend.icon]; nameLabel.text = friend.name; dLabel.text = friend.intro; //4. 返回cell return cell; }
插入上述代码我其实就是想说:代码的创建其实是可以有多种方式:例如上述这个原型cell我可以设置控件的tag值,也可以将cell中的控件拖线与ViewController相联系.
知识点(三):小知识:BOOL值默认是0也就是FALSE.
在第九天补充资料里面有总结关于UIView的一些特殊方法.
layoutSubviews这个方法作用:可以获取到当前view的宽高,所以一般在布局子控件的时候会用到这个方法来设置子控件的frame.
布局子控件的时候在添加子控件到当前view的时候就会调用这个方法.
如上图所示:如果改变view的frame是会调用他的layoutSubviews方法的(其实是设置view的frame,因为从没有设置到设置也是变化).