uitableviewcell xib做网络请求会有什么问题

UITableViewCell的prepareForReuse方法 - 推酷
UITableViewCell的prepareForReuse方法
cell被重用如何提前知道? 重写cell的prepareForReuse
官方头文件中有说明.当前已经被分配的cell如果被重用了(通常是滚动出屏幕外了),会调用cell的prepareForReuse通知cell.注意这里重写方法的时候,注意一定要调用父类方法[super prepareForReuse] .这个在使用cell作为网络访问的代理容器时尤其要注意,需要在这里通知取消掉前一次网络请求.不要再给这个cell发数据了.
// if the cell is reusable (has a reuse identifier), this is called just before the cell is returned from the table view method dequeueReusableCellWithIdentifier:. &If you override, you MUST call super.
- (void)prepareForReuse
& & [super prepareForReuse];
自定义UITableViewCell的方法有很多&发现一些人都会遇到自己定义的cell里面图片错乱的问题 这个问题往往是因为没有实现prepareForReuse这个方法导致的.
UITableViewCell在向下滚动时复用, 得用的cell就是滑出去的那些, 而滑出去的cell里显示的信息就在这里出现了 解决的方法就是在UITableViewCell的子类里实现perpareForReuse方法, 把内容清空掉
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
请允许我用Storyboard来表明我的需求。
如图,在这个tableview里面有两个大的cell,一个是另外tableview,一个是collectionview。而且这两个大的cell的高度不是固定的,当点击加载更多的时候,对应的cell里面的tableview长度会增长,cell也会增长(换言之,在这两个cell里面所有内容都需要被全部展示,而不是滑动)。请问如果是这种需求的话,该如何设计呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你的情况其实仅仅一个collectionView就可以搞定了,根据数据源分组对应分几个section,展示更多时候,就修改对应section中的数据源,刷UI就好了,你所“必须”要关注的是你的CollectionView的contentSize以及如何Layout,还有优化的话考虑Cache layout类中的attributes.
今天刚刚这么写了collectionView嵌套collectionView(被要求的,不是没事找事),说下思路(TableView嵌套做法类似,XIB/SB与纯代码区别请忽略...)PS: 有写错的地方,希望- -CollectionView大神来喷..Orz
1)自定义cell
需要挂collectionView的cell里面贴如下代码:
@class WBrowserWhisperFlowL
static NSString *BrowserWhisperCoverFlowCellIdentifier = @"BrowserWhisperCoverFlowCellIdentifier";
@interface WBrowserWhisperCoverFlowCell : UICollectionViewCell
@property (nonatomic, strong) WBrowserWhisperFlowLayout *
@property (nonatomic, strong) UICollectionView *collectionV
- (void)setCollectionViewDataSourceDelegate:(id&UICollectionViewDataSource, UICollectionViewDelegate&)dataSourceD
- (instancetype)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
_layout = [[WBrowserWhisperFlowLayout alloc] init];
_layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
_layout.itemSize = CGSizeMake(CGRectGetWidth(self.frame) - 100, 200);
_layout.scrollDirection = UICollectionViewScrollDirectionH
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout];
[_collectionView registerClass:[WBrowserWhisperCoverFlowItemCell class] forCellWithReuseIdentifier:BrowserWhisperCoverFlowItemCellIdentifier];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.pagingEnabled = YES;
[self.contentView addSubview:_collectionView];
- (void)layoutSubviews {
[super layoutSubviews];
_collectionView.frame = self.contentView.
- (void)setCollectionViewDataSourceDelegate:(id&UICollectionViewDataSource, UICollectionViewDelegate&)dataSourceDelegate {
_collectionView.dataSource = dataSourceD
_collectionView.delegate = dataSourceD
[_collectionView reloadData];
2)记住在cell中的CollectionView是在cell之后初始化的,也就是在初始化这个cell的之后要立即设置这个cell中CollectionView的数据源跟代理,不然Crash没商量。
3.1)修改cell中CollectionView的数据源(若有变化,比如数据主动/被动修改),然后修改该CollectionView属性(layoutAttribute会被修改)以及重新layout两个CollectionView。(tableView则是reloat对应的indexPath)
4)继续吐槽:CollectionView的精髓在于会不会写layout。。CollectionView让TableView可以say goodbye了,但是需要花一定的时间去学习否则很难用好,推荐资源:
iOS UICollectionView, 2nd Edition 电子书
RayWench视频
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
建议不要在 cell 里套 tableView
在 cell 里再加 UITableView,理论上或许可行(让外层 cell 作为内层 tableView 的 delegate),但我从没见过这样的写法,也感觉这样很不好。原因有2:
delegate 复杂,view 的层叠关系复杂
这样反而不能达到你的需求。你说想要:
对应的cell里面的tableview长度会增长,cell也会增长(换言之,在这两个cell里面所有内容都需要被全部展示,而不是滑动)
但 UITableView 的高度是固定的,里面是 ScrollView。它天然是适合滚动的,而不是全部显示。
可能的代替做法
我觉得这个需求可以考虑能否把这上下两个大 cell 考虑为两个 section?上面的大 cell 改成第一个 section,里面的 cell 里左边有图片、右边两个 label 的,footer 或最后一个 cell 是“加载更多”;下面的大 cell 改成第二个 section,里面根据你 collectionView 的情况而定。比如是本来是一行排5个,可以是每个 cell 里排5个;也可以是全排在一个 view 里,把这个 view 添加到唯一的 cell 上或添加到 headerView 上。然后 footer 或最后一个 cell 是加载更多。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
请使用这个方法。
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
如果你要在uitablewview里加一个uitableview的话,可以上网找找有没有开源的。我记得我是看到过的。
如果你在uitableview里加一个uicollection的话。我提供一个想法。因为之前的项目里遇到过一个类似的问题。说一下我的思路。
因为uitableview是支持定义cell的,可以在cell里写一个collectionview,然后在定义你的collectioncell。绝对是可行的,而且个人感觉代码量不是很多。加载数据的时候每次向cell里传递数据,然后collectionview会加载这些数据。
你可以通过代码来在cell里计算高度,这个是可以实现的。
因为电脑不在身边...就不贴代码了,如果需要的话可以给我留言我周一贴一段我写的uitableview+collection搭配的代码
同步到新浪微博
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 App
SegmentFault
一起探索更多未知2187人阅读
XCode(162)
iOS(172)
iPhone(153)
  经常我们会用tableView显示很多条目, 有时候需要显示图片, 但是一次从服务器上取来所有图片对用户来浪费流量, 对服务器也是负担.最好是按需加载,即当该用户要浏览该条目时再去加载它的图片.
  重写如下方法
  - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
  UIImage *image = [self getImageForCellAtIndexPath:indexPath]; //从网上取得图片
  [cell.imageView setImage:image];
  这虽然解决了延时加载的问题, 但当网速很慢, 或者图片很大时(假设,虽然一般cell中的图很小),你会发现程序可能会失去对用户的响应.
  原因是UIImage *image = [self getImageForCellAtIndexPath:indexPath]; 这个方法可能要花费大量的时间,主线程要处理这个method.
  所以失去了对用户的响应.
  所以要将该方法提出来:
  - (void)updateImageForCellAtIndexPath:(NSIndexPath *)indexPath
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  UIImage *image = [self getImageForCellAtIndexPath:indexPath];
  UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
  [cell.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
  [pool release];
  然后再新开一个线程去做这件事情
  - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
  [NSThread detachNewThreadSelector:@selector(updateImageForCellAtIndexPath:) toTarget:self withObject:indexPath];
  同理当我们需要长时间的计算时,也要新开一个线程去做这个计算以避免程序处于假死状态
  以上代码只是示例, 还可以改进的更多, 比如从网上down下来一次后就将图片缓存起来,再次显示的时候就不用去下载.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1708717次
积分:13700
积分:13700
排名:第635名
原创:85篇
转载:249篇
评论:192条
(1)(5)(10)(3)(1)(3)(2)(3)(8)(43)(11)(16)(31)(63)(19)(5)(1)(3)(8)(37)(20)(5)(1)(1)(22)(10)(2)
Android 程序技巧,学习笔记iOS简易总结(2)
cell上控件在请求网络图片的时候,通常会返回图片的宽高比;在项目中碰到需要按照比例来显示图片的问题,如果只有图片一个控件按照宽高比直接设置frame即可,但是如果cell上有很多的控件,自适应高度是比较复杂的.
我们知道在AutoLayout中只要不设置UILabel的高度是可以让其自适应文本高度的,那么UIImageView可不可以也自适应高度呢.
UILabel之所以能够自适应高度,肯定也是在cell显示之前,系统通过UILabel的约束条件/字体大小和显示的文本内容计算出来的;因此只要我们在cell显示之前将UIImageView的各个约束设置好就可以实现UIImageView在cell上自适应高度
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:字体大小],NSFontAttributeName, nil];
[显示的文本 boundingRectWithSize:CGSizeMake(UILabel宽度, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
(此处只说明固定了图片宽度的情况,其余各种情况可以更改更改相应的约束实现)
1. 我们先在cell的xib中拖入一个UIImageView,对其约束好距离左边,右边,上边的距离(当然如果你想全部用代码写约束也行......)
2. 然后我们给tableview设置两个属性,让cell的行高自适应控件的高度
// 设置行高为自动
self.tableView.rowHeight = UITableViewAutomaticD
// default is 0, which means there is no estimate
// 官方解释不为0即可
self.tableView.estimatedRowHeight = 10;
3. 在cell的类中,我们设置一个属性(用处是在返回cell的时候给其赋值请求到的网络图片宽高比)
/** 显示图片 */
@property (weak, nonatomic) IBOutlet UIImageView *iamgeV;
/** 比例约束 */
@property (weak, nonatomic) NSLayoutConstraint *ratioLC;
/** 赋值比例 */
@property (nonatomic, assign) CGF
4. 在返回cell的代理方法里面,对比例进行赋值,通过setRatio方法实现如下:
- (void)setRatio:(CGFloat)ratio {
// &view1.attr1 = view2.attr2 * multiplier + constant&
_ratioLC = [NSLayoutConstraint constraintWithItem:_iamgeV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_iamgeV attribute:NSLayoutAttributeWidth multiplier:ratio constant:0];
[_iamgeV addConstraint:_ratioLC];
5. 运行一下即可看到图片比例不失真,当然其余控件均可以这样实现约束.....
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1214次
排名:千里之外前面已经说过UITableView中的单元格cell是在显示到用户可视区域后创建的,那么如果用户往下滚动就会继续创建显示在屏幕上的单元格,如果用户向上滚动返回到查看过的内容时同样会重新创建之前已经创建过的单元格。如此一来即使UITableView的内容不是太多,如果用户反复的上下滚动,内存也会瞬间飙升,更何况很多时候UITableView的内容是很多的(例如微博展示列表,基本向下滚动是没有底限的)。
前面一节中我们曾经提到过如何优化UIScrollView,当时就是利用有限的UIImageView动态切换其内容来尽可能减少资源占用。同样的,在UITableView中也可以采用类似的方式,只是这时我们不是在滚动到指定位置后更改滚动的位置而是要将当前没有显示的Cell重新显示在将要显示的Cell的位置然后更新其内容。原因就是UITableView中的Cell结构布局可能是不同的,通过重新定位是不可取的,而是需要重用已经不再界面显示的已创建过的Cell。
当然,听起来这么做比较复杂,其实实现起来很简单,因为UITableView已经为我们实现了这种机制。在UITableView内部有一个缓存池,初始化时使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一个可重用标识,就可以将这个cell放到缓存池。然后在使用时使用指定的标识去缓存池中取得对应的cell然后修改cell内容即可。
#pragma mark返回每行的单元格
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//NSIndexPath是一个对象,记录了组和行信息
NSLog(@"生成单元格(组:%i,行%i)",indexPath.section,indexPath.row);
KCContactGroup *group=_contacts[indexPath.section];
KCContact *contact=group.contacts[indexPath.row];
//由于此方法调用十分频繁,cell的标示声明成静态变量有利于性能优化
static NSString *cellIdentifier=@"UITableViewCellIdentifierKey1";
//首先根据标识去缓存池取
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//如果缓存池没有到则重新创建并放到缓存池中
if(!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
cell.textLabel.text=[contact getName];
cell.detailTextLabel.text=contact.phoneN
NSLog(@"cell:%@",cell);
上面的代码中已经打印了cell的地址,如果大家运行测试上下滚动UITableView会发现滚动时创建的cell地址是初始化时已经创建的。
这里再次给大家强调两点:
-(UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)方法调用很频繁,无论是初始化、上下滚动、刷新都会调用此方法,所有在这里执行的操作一定要注意性能;
可重用标识可以有多个,如果在UITableView中有多类结构不同的Cell,可以通过这个标识进行缓存和重新;
来自:Kenshin Cui's Blog
链接:/kenshincui/p/3931948.html#performance
本文来自微信公众账号提交,由微信啦收录,转载请注明出处。
微信扫码 分享文章

我要回帖

更多关于 uitableviewcell 箭头 的文章

 

随机推荐