在开发过程中,有好多应用都会嵌入新浪微博的界面,今天整理一下代码。
首先看界面效果图:
Demo下载地址:http://download.csdn.net/detail/rhljiayou/6760745
思路:首先放一个UITableView,自定义一个UITableViewCell,分析新浪微博中的数据,并且显示在界面上,这个稍微费一下事,主要是分析数据并且算出位置。
还有要处理@#链接 特殊字符,并以不同颜色显示出,这个可以参考另外一遍博文:
http://blog.csdn.net/rhljiayou/article/details/17019651,讲的是正则表达式,不过里面有包含内容关于如何使@#链接 特殊字符处理的。可以通过AutoHyperlinks,稍加修改就可以写出完美的特殊字符处理。
今天我主要讲三点东西: 1、UITableViewCell的重用机制(不要范错误)2、自定义UITableViewCell 3、MVC 的思想
为什么要讲这些,这跟今天的 Demo 有关系吗?
答:关系重大,因为我发现有的同学用 UITableView 写东西的时候把所有的东西添加到系统的 UITableViewCell中去了,这样会导致一些问题,我觉得比较严重,所以就想写此文来让大家避免这些错误,看大家是否也范这样的错误了!
1、UITableViewCell的重用机制(不要范错误)
首先您先看这样的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static
NSString *CellIdentifier =
@Cell
;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if
(cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(
0
,
0
,
320
,
20
)];
nameLabel.text = @这是一个自定义的 name;
[cell addSubview:nameLabel];
return
cell;
}
|
感觉有问题吗?(声明一下,我写代码都用 arc,所以大家看到代码没有release,是正常不是错误。)
肯定是有问题的,看这一句:[cell addSubview:nameLabel];大家先看一下我截的图:
有没有发现,我标注那几行,字体明显比其他的粗!那是因为我把tableView划动了几行,并且是把上面两行划过屏之外了,最后一行也划过屏幕之外了。如果你觉得的不够明显,自己可以写一写。
为什么会导致此问题呢,是 UITableViewCell 的重用机制,比如我屏幕上可以显示10行,那么就会创建10个 UITableViewCell,当我划动时,上面划出屏的UITableViewCell实际上是挂起状态,下面行出现到屏上实际是不会再创建 UITableViewCell 了,而是引用上面划出屏幕的 UITableViewCell,这样以来,每次划进屏后,那个cell上都会添加nameLabel,导致重叠重叠又重叠,所以会出现字体明显比别的粗些,因为有好几个label被重叠了。
避免此错误,只要给 nameLabel 再赋上值就好了,没必要再添加到cell上。
但是,有的同学为避免这个重叠错误,这样做了,请看以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static
NSString *CellIdentifier =
@Cell
;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if
(cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else
{
UILabel *label = (UILabel*)[cell viewWithTag:
200
];
[label removeFromSuperview];
}
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(
0
,
0
,
320
,
20
)];
nameLabel.text = @这是一个自定义的 name;
nameLabel.tag =
200
;
[cell addSubview:nameLabel];
return
cell;
}
|
把[label removeFromSuperview];这样解决,的确不会出现字体变粗的情况了,但是,新问题出现了。UITableViewCell 的重用机制体现何在?每个cell上都重新删除再添加,相当于每个cell都是独立的,这样就不能体现出UITableViewCell真正的优点了,它的优点就是重用机制,你只要添加一次再重新赋值就好了,为什么还要每次都重新添加,这样感觉即浪费资源又不能体现规范性还没有优点。
2、自定义UITableViewCell
如果你的 cell 上很复杂,系统cell上的View根本不够用,那么就考虑自定义cell吧。
不推荐在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath此方法中,
把所有需要的view 都添加到 cell 上。
推荐方法:
继承UITableViewCell创建自定义的CustomCell,代码如下:
CustomCell:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#
import
CustomCell.h
@implementation
CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [
super
initWithStyle:style reuseIdentifier:reuseIdentifier];
if
(self) {
// Initialization code
_nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(
0
,
0
,
320
,
20
)];
[self addSubview:_nameLabel];
}
return
self;
}
- (
void
)setSelected:(BOOL)selected animated:(BOOL)animated
{
[
super
setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
|
使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static
NSString *CellIdentifier =
@CustomCell
;
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if
(cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.nameLabel.text = @这是一个自定义的 name;
return
cell;
}
|
3、MVC 的思想
现在完整 app 都会从后台取数据,如果数据很复杂,你会如何让他们显示在界面上。
比如以下数据是从后台取出来的:
{
name: rhl,
sex: 女,
job: coder,
age: 0,
csdn: http://blog.csdn.net/rhljiayou,
main: 3G/移动开发,
qq 群: 113820038
}
这数据算少的算简单的,我只是用这个做一下例子,真实的数据有可能很多很复杂!
拿到数据后,都会把它解析成数组对象NSMutableDictionary *dict;
有二种写法
第一种:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static
NSString *CellIdentifier =
@CustomCell
;
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if
(cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.nameLabel.text = [dict objectForKey:
@name
];
cell.sexLabel.text = [dict objectForKey:
@sex
];
cell.jobLabel.text = [dict objectForKey:
@job
];
cell.ageLabel.text = [dict objectForKey:
@age
];
cell.csdnLabel.text = [dict objectForKey:
@csdn
];
cell.mainLabel.text = [dict objectForKey:
@main
];
cell.qqLabel.text = [dict objectForKey:
@qq
群];
return
cell;
}
|
这样也能达到预期效果,只是如果你此类中的代码非常之多,再添加这点代码其实也好,假如像我 demo 中的新浪微博中的数据,你就有可能头大了。
比如多个viewController中都用到此数据呢,你是不是也照样这样写一遍啊。由此看来,是不是感觉代码的藕合性有些高啊,就是说 view 和数据是在一块儿,有几套 view 就有几套数据这样写,那么我们为何不尝试把这些赋值的这些操作统一的就写一份儿呢?
接下来就是第二种写法:
在 CustomCell 中
1
2
3
4
5
6
7
8
9
10
|
-(
void
)setContent:(NSMutableDictionary*)dict
{
self.nameLabel.text = [dict objectForKey:
@name
];
self.sexLabel.text = [dict objectForKey:
@sex
];
self.jobLabel.text = [dict objectForKey:
@job
];
self.ageLabel.text = [dict objectForKey:
@age
];
self.csdnLabel.text = [dict objectForKey:
@csdn
];
self.mainLabel.text = [dict objectForKey:
@main
];
self.qqLabel.text = [dict objectForKey:
@qq
群];
}
|
用法
1
2
3
4
5
6
7
8
9
10
11
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static
NSString *CellIdentifier =
@CustomCell
;
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if
(cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell setContent:dict];
return
cell;
}
|
这样,我们只需要[cell setContent:dic];就能完成赋值操作!别的界面中也用到此 cell 时只需这一行代码就完成赋值了。
我一般拿到数据后会将其字典NSMutableDictionary封装成成模型对象,这样更符合 MVC 的思想。
所谓MVC,我这里搜到一个人的回答还是瞒详细的,
也很易懂:http://zhidao.baidu.com/link?url=giaoyhccUjcAiQjWVLB_nNI7-BsLPAq-gsDz_avnAGCvaPZW3hDmxLqNYsxG8dtSi5ciLCdUMyh1AVZsKCVDVq
原文地址:http://www.2cto.com/kf/201312/267263.html