第三天

******** 九宫格代码的现实
@interface HMViewController ()
/** 应用程序列表 */
@property (nonatomic, strong) NSArray *appList;
@end @implementation HMViewController - (NSArray *)appList
{
if (_appList == nil) {
// appList保存的是字典=>模型
// _appList = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]];
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]]; // 创建一个临时数组 字典转模型
NSMutableArray *arraM = [NSMutableArray array]; //把NSArray 转NSMutableArray
// 遍历数组,依次转换模型
for (NSDictionary *dict in array) {
HMAppInfo *appInfo = [[HMAppInfo alloc] init];
appInfo.name = dict[@"name"];
appInfo.icon = dict[@"icon"]; [arraM addObject:appInfo];
} // 将临时数组为属性赋值
_appList = arraM;
}
return _appList;
} - (void)viewDidLoad
{
[super viewDidLoad]; // 搭建界面,九宫格
#define kAppViewW 80
#define kAppViewH 90
#define kColCount 3
#define kStartY 20 // 320 - 3 * 80 = 80 / 4 = 20
CGFloat marginX = (self.view.bounds.size.width - kColCount * kAppViewW) / (kColCount + );
CGFloat marginY = ; for (int i = ; i < ; i++) {
// 行
// 0, 1, 2 => 0
// 3, 4, 5 => 1
int row = i / kColCount; // 列
// 0, 3, 6 => 0
// 1, 4, 7 => 1
// 2, 5, 8 => 2
int col = i % kColCount; CGFloat x = marginX + col * (marginX + kAppViewW);
CGFloat y = kStartY + marginY + row * (marginY + kAppViewH); UIView *appView = [[UIView alloc] initWithFrame:CGRectMake(x, y, kAppViewW, kAppViewH)];
// appView.backgroundColor = [UIColor redColor];
[self.view addSubview:appView]; // 实现视图内部细节
// NSDictionary *dict = self.appList[i];
HMAppInfo *appInfo = self.appList[i]; // 1> UIImageView
UIImageView *icon = [[UIImageView alloc] initWithFrame:CGRectMake(, , kAppViewW, )];
// icon.backgroundColor = [UIColor greenColor]; // 设置图像
//icon.image = [UIImage imageNamed:dict[@"icon"]];
icon.image = [UIImage imageNamed:appInfo.icon];// // 设置图像填充模式,等比例显示(CTRL+6)
icon.contentMode = UIViewContentModeScaleAspectFit; [appView addSubview:icon]; // 2> UILabel -> 应用程序名称
// CGRectGetMaxY(frame) = frame.origin.y + frame.size.height
UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(, CGRectGetMaxY(icon.frame), kAppViewW, )]; //icon.frame icon的y的组大值
// lable.backgroundColor = [UIColor blueColor]; // 设置应用程序名称
// lable.text = dict[@"name"];
lable.text = appInfo.name; // 设置字体
lable.font = [UIFont systemFontOfSize:13.0];
lable.textAlignment = NSTextAlignmentCenter; [appView addSubview:lable]; // 3> UIButton -> 下载按钮
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(, CGRectGetMaxY(lable.frame), kAppViewW, )];
button.backgroundColor = [UIColor yellowColor]; // 背景图片
[button setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted]; // 按钮都是有状态的,不同状态可以对应不同的标题
[button setTitle:@"下载" forState:UIControlStateNormal];
// *** 一定不要使用以下方法,修改按钮标题
// button.titleLabel.text = @"aaa"; // 修改字体(titleLabel是只读的)
// readonly表示不允许修改titleLabel的指针,但是可以修改label的字体
// 提示:按钮的字体是不区分状态的!
button.titleLabel.font = [UIFont systemFontOfSize:12.0]; [appView addSubview:button];
}
}
@end
********模型的优化
- (NSArray *)appList
{
if (_appList == nil) {
// appList保存的是字典=>模型
// _appList = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]];
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]]; // 创建一个临时数组
NSMutableArray *arraM = [NSMutableArray array];
// 遍历数组,依次转换模型
for (NSDictionary *dict in array) { // 类方法可以快速实例化一个对象
// HMAppInfo *appInfo = [[HMAppInfo alloc] initWithDict:dict]; HMAppInfo *appInfo = [HMAppInfo appInfoWithDict:dict]; // NSString *str = [HMAppInfo appInfoWithDict:dict];
// NSLog(@"%d", str.length); [arraM addObject:appInfo];
} // 将临时数组为属性赋值
_appList = arraM;
}
return _appList;
} @implementation HMAppInfo
- (instancetype)initWithDict:(NSDictionary *)dict
{
// self 是 对象
self = [super init];
if (self) {
// 用字典给属性赋值,所有与plist键值有关的方法,均在此处!
self.name = dict[@"name"];
self.icon = dict[@"icon"];
}
return self;
} + (instancetype)appInfoWithDict:(NSDictionary *)dict
{
// self 是 class
return [[self alloc] initWithDict:dict];
} @end
//接口
@interface HMAppInfo : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon; /**
instancetype 主要用于在类方法实例化对象时,让编译器主动推断对象的实际类型 以避免使用id,会造成开发中不必要的麻烦,减少出错几率! instancetype是苹果在iOS7才开始主推的 C++11 auto
在swift语言中,绝大多数类的实例化,都不需要再指定类型 instancetype只能用于返回值使用!!!不能当做参数使用
*/ /** 通常在写模型的实例化方法时,以下两个方法,都需要实现 */
/** 使用字典实例化模型 */
- (instancetype)initWithDict:(NSDictionary *)dict;
/** 类方法可以快速实例化一个对象 */
+ (instancetype)appInfoWithDict:(NSDictionary *)dict; @end
******* 模型的封装KVC的使用

@implementation HMAppInfo
// 合成指令,主动指定属性使用的成员变量名称
@synthesize image = _image; /**
使用KVC的注意事项 1> plist中的键值名称必须与模型中的属性一致
2> 模型中的属性可以不全部出现在plist中
*/
- (UIImage *)image
{
if (_image == nil) {
_image = [UIImage imageNamed:self.icon];
}
return _image;
} - (instancetype)initWithDict:(NSDictionary *)dict
{
// self 是 对象
self = [super init];
if (self) {
// 用字典给属性赋值,所有与plist键值有关的方法,均在此处!
// self.name = dict[@"name"];
// self.icon = dict[@"icon"]; // KVC - key value coding键值编码
// 是一种间接修改/读取对象属性的一种方法
// KVC 被称为 cocoa 的大招!
// 参数:
// 1. 数值
// 2. 属性名称
// [self setValue:dict[@"name"] forKeyPath:@"name"];
// [self setValue:dict[@"icon"] forKeyPath:@"icon"];
// setValuesForKeysWithDictionary本质上就是调用以上两句代码
[self setValuesForKeysWithDictionary:dict];
}
return self;
} + (instancetype)appInfoWithDict:(NSDictionary *)dict
{
// self 是 class
return [[self alloc] initWithDict:dict];
} + (NSArray *)appList
{
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]]; // 创建一个临时数组
NSMutableArray *arrayM = [NSMutableArray array]; // 遍历数组,依次转换模型
for (NSDictionary *dict in array) {
[arrayM addObject:[HMAppInfo appInfoWithDict:dict]];
} return arrayM;
} @end
*******按钮的操作
*******按钮的操作
按钮的事件
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; /** 按钮监听方法 */
- (void)click:(UIButton *)button
{
NSLog(@"%s %d", __func__, button.tag); // 取出appInfo
HMAppInfo *appInfo = self.appList[button.tag]; // 添加一个UILabel到界面上
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
// 数值是0表示黑色,1表示纯白
// alpha表示透明度
label.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.2]; label.text = appInfo.name;
label.textAlignment = NSTextAlignmentCenter; [self.view addSubview:label];
// 动画效果
// 收尾式动画,修改对象的属性,frame,bounds,alpha
// 初始透明度,完全透明
label.alpha = 0.0; // 禁用按钮
button.enabled = NO; // 动画结束之后删除
// ^ 表示是block,块代码,是一个预先准备好的代码块,可以当做参数传递,在需要的时候执行!
// 块代码在OC中,使用的非常普遍!
[UIView animateWithDuration:1.0f animations:^{
NSLog(@"动画开始");
// 要修改的动画属性
label.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
// 动画完成后,所做的操作
NSLog(@"动画完成"); // button.enabled = NO; [label removeFromSuperview];
}];
}]; NSLog(@"-------"); // 收尾式动画,不容易监听动画完成时间,而且不容易实现动画嵌套
// [UIView beginAnimations:nil context:nil];
// [UIView setAnimationDuration:1.0f];
// label.alpha = 1.0;
// [UIView commitAnimations];
}

***********XIB优化九宫格

***********XIB优化九宫格
#import "HMViewController.h"
#import "HMAppInfo.h" #define kAppViewW 80
#define kAppViewH 90
#define kColCount 3
#define kStartY 20 @interface HMViewController ()
/** 应用程序列表 */
@property (nonatomic, strong) NSArray *appList;
@end @implementation HMViewController - (NSArray *)appList
{
if (_appList == nil) {
_appList = [HMAppInfo appList];
}
return _appList;
} - (void)viewDidLoad
{
[super viewDidLoad]; // XIB的测试代码
// 加载XIB,XIB中可以包含多个自定义视图,通常只保存一个
// UIView *view = [[[NSBundle mainBundle] loadNibNamed:@"HMAppView" owner:nil options:nil] lastObject]; // 搭建界面,九宫格
// 320 - 3 * 80 = 80 / 4 = 20
CGFloat marginX = (self.view.bounds.size.width - kColCount * kAppViewW) / (kColCount + );
CGFloat marginY = ; for (int i = ; i < self.appList.count; i++) {
// 行
// 0, 1, 2 => 0
// 3, 4, 5 => 1
int row = i / kColCount; // 列
// 0, 3, 6 => 0
// 1, 4, 7 => 1
// 2, 5, 8 => 2
int col = i % kColCount; CGFloat x = marginX + col * (marginX + kAppViewW);
CGFloat y = kStartY + marginY + row * (marginY + kAppViewH); // 从XIB来加载自定义视图
UIView *appView = [[[NSBundle mainBundle] loadNibNamed:@"HMAppView" owner:nil options:nil] lastObject];
// 设置视图位置
appView.frame = CGRectMake(x, y, kAppViewW, kAppViewH); // UIView *appView = [[UIView alloc] initWithFrame:CGRectMake(x, y, kAppViewW, kAppViewH)];
[self.view addSubview:appView]; // 实现视图内部细节
HMAppInfo *appInfo = self.appList[i]; // 1> UIImageView
UIImageView *icon = appView.subviews[];
// UIImageView *icon = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kAppViewW, 50)]; // 设置图像
icon.image = appInfo.image; // 设置图像填充模式,等比例显示(CTRL+6)
// icon.contentMode = UIViewContentModeScaleAspectFit; // [appView addSubview:icon]; // 2> UILabel -> 应用程序名称
UILabel *label = appView.subviews[];
// UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(icon.frame), kAppViewW, 20)]; // 设置应用程序名称
label.text = appInfo.name; // 设置字体
// label.font = [UIFont systemFontOfSize:13.0];
// label.textAlignment = NSTextAlignmentCenter; // [appView addSubview:label]; // 3> UIButton -> 下载按钮
UIButton *button = appView.subviews[];
// UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(label.frame), kAppViewW, 20)]; // 背景图片
// [button setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];
// [button setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted]; // 按钮都是有状态的,不同状态可以对应不同的标题
// [button setTitle:@"下载" forState:UIControlStateNormal];
// *** 一定不要使用以下方法,修改按钮标题
// button.titleLabel.text = @"aaa"; // 修改字体(titleLabel是只读的)
// readonly表示不允许修改titleLabel的指针,但是可以修改label的字体
// 提示:按钮的字体是不区分状态的!
// button.titleLabel.font = [UIFont systemFontOfSize:12.0]; // [appView addSubview:button]; // 给按钮添加监听方法
button.tag = i; [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
}
} /** 按钮监听方法 */
- (void)click:(UIButton *)button
{
NSLog(@"%s %d", __func__, button.tag); // 取出appInfo
HMAppInfo *appInfo = self.appList[button.tag]; // 添加一个UILabel到界面上
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
// 数值是0表示黑色,1表示纯白
// alpha表示透明度
label.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.2]; label.text = appInfo.name;
label.textAlignment = NSTextAlignmentCenter; [self.view addSubview:label];
// 动画效果
// 收尾式动画,修改对象的属性,frame,bounds,alpha
// 初始透明度,完全透明
label.alpha = 0.0; // 禁用按钮
button.enabled = NO; // 动画结束之后删除
// ^ 表示是block,块代码,是一个预先准备好的代码块,可以当做参数传递,在需要的时候执行!
// 块代码在OC中,使用的非常普遍!
[UIView animateWithDuration:1.0f animations:^{
NSLog(@"动画开始");
// 要修改的动画属性
label.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
// 动画完成后,所做的操作
NSLog(@"动画完成"); // button.enabled = NO; [label removeFromSuperview];
}];
}]; NSLog(@"-------"); // 收尾式动画,不容易监听动画完成时间,而且不容易实现动画嵌套
// [UIView beginAnimations:nil context:nil];
// [UIView setAnimationDuration:1.0f];
// label.alpha = 1.0;
// [UIView commitAnimations];
} @end
***********模型显示视图
***********模型显示视图
// 从XIB来加载自定义视图
HMAppView *appView = [[[NSBundle mainBundle] loadNibNamed:@"HMAppView" owner:nil options:nil] lastObject]; #import "HMAppView.h"
#import "HMAppInfo.h" @interface HMAppView()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *label;
@end @implementation HMAppView /**
利用setter方法设置视图的界面显示
*/
- (void)setAppInfo:(HMAppInfo *)appInfo
{
_appInfo = appInfo; self.label.text = appInfo.name;
self.iconView.image = appInfo.image;
} /** 按钮监听方法 */
- (IBAction)click:(UIButton *)button
{
// NSLog(@"%s %d", __func__, button.tag);
//
// // 取出appInfo
// HMAppInfo *appInfo = self.appList[button.tag]; // 添加一个UILabel到界面上
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
// 数值是0表示黑色,1表示纯白
// alpha表示透明度
label.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.2]; label.text = self.appInfo.name;
label.textAlignment = NSTextAlignmentCenter; // self.superview就是视图控制器中的self.view
[self.superview addSubview:label];
// 动画效果
// 收尾式动画,修改对象的属性,frame,bounds,alpha
// 初始透明度,完全透明
label.alpha = 0.0; // 禁用按钮
button.enabled = NO; // 动画结束之后删除
// ^ 表示是block,块代码,是一个预先准备好的代码块,可以当做参数传递,在需要的时候执行!
// 块代码在OC中,使用的非常普遍!
[UIView animateWithDuration:1.0f animations:^{
NSLog(@"动画开始");
// 要修改的动画属性
label.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
// 动画完成后,所做的操作
NSLog(@"动画完成"); [label removeFromSuperview];
}];
}];
} @end
******************以上的代码的优化
HMAppView *appView = [HMAppView appViewWithAppInfo:self.appList[i]]; #import "HMAppView.h"
#import "HMAppInfo.h" @interface HMAppView()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *label;
@end @implementation HMAppView + (instancetype)appView
{
return [[[NSBundle mainBundle] loadNibNamed:@"HMAppView" owner:nil options:nil] lastObject];
} + (instancetype)appViewWithAppInfo:(HMAppInfo *)appInfo
{
// 1. 实例化一个视图
HMAppView *view = [self appView]; // 2. 设置视图的显示
view.appInfo = appInfo; // 3. 返回视图
return view;
} /**
利用setter方法设置视图的界面显示
*/
- (void)setAppInfo:(HMAppInfo *)appInfo
{
_appInfo = appInfo; self.label.text = appInfo.name;
self.iconView.image = appInfo.image;
} /** 按钮监听方法 */
- (IBAction)click:(UIButton *)button
{
// NSLog(@"%s %d", __func__, button.tag);
//
// // 取出appInfo
// HMAppInfo *appInfo = self.appList[button.tag]; // 添加一个UILabel到界面上
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
// 数值是0表示黑色,1表示纯白
// alpha表示透明度
label.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.2]; label.text = self.appInfo.name;
label.textAlignment = NSTextAlignmentCenter; // self.superview就是视图控制器中的self.view
[self.superview addSubview:label];
// 动画效果
// 收尾式动画,修改对象的属性,frame,bounds,alpha
// 初始透明度,完全透明
label.alpha = 0.0; // 禁用按钮
button.enabled = NO; // 动画结束之后删除
// ^ 表示是block,块代码,是一个预先准备好的代码块,可以当做参数传递,在需要的时候执行!
// 块代码在OC中,使用的非常普遍!
[UIView animateWithDuration:1.0f animations:^{
NSLog(@"动画开始");
// 要修改的动画属性
label.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
// 动画完成后,所做的操作
NSLog(@"动画完成"); [label removeFromSuperview];
}];
}];
} @end

IOS第三天的更多相关文章

  1. iOS开发三步搞定百度推送

    iOS开发三步搞定百度推送   百度推送很简单,准备工作:在百度云推送平台注册应用,上传证书. 步骤一: 百度云推送平台 http://push.baidu.com/sdk/push_client_s ...

  2. iOS的三种多线程技术NSThread/NSOperation/GCD

    1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心 ...

  3. 【读书笔记】iOS网络-三种错误

    一,操作系统错误. iOS人机界面指南中,Apple建议不要过度使用AlertViews,因为这会破坏设备的使用感受. 操作系统错误: 1,没有网络. 2,无法路由到目标主机. 3,没用应和监听目标端 ...

  4. iOS——浅谈iOS中三种生成随机数方法

    ios 有如下三种随机数方法:

  5. iOS中 三种随机数方法详解

    ios 有如下三种随机数方法: //第一种 srand((unsigned)time(0)); //不加这句每次产生的随机数不变 int i = rand() % 5; //第二种 srandom(t ...

  6. iOS-浅谈iOS中三种生成随机数方法

    ios 有如下三种随机数方法:

  7. iOS用三种途径实现一方法有多个返回值

    以前觉得这种标题有点偏向于理论,实际开发中怎么会有这种诡异的需求,但是真正遇到了这种硬需求时觉得还是有那么点价值的,理论付诸了实践在此也就做了个整理. 以我私下开发中的一处代码为例,本意是希望有这么一 ...

  8. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  9. iOS开发- 三步快速集成社交化分享工具ShareSDK

    1.前言 作为现在App里必不可少的用户分享需要,社交化分享显然是我们开发app里较为常用的. 最近因为公司App有社交化分享的需要,就特此研究了会,拿出来与大家分享. 想要集成社交会分享,我们可以使 ...

随机推荐

  1. Python Web 开发的十个框架【转载】

    Python 是一门动态.面向对象语言.其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性.除了语言本身的设计目的之外,Python标准 库也是值得大家称赞的,Python甚至还 ...

  2. Redis执行Lua脚本示例

    Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行.使用脚本的好处如下: 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在red ...

  3. Guacamole 介绍以及架构

    Guacamole的介绍以及架构 guacd Web应用程序 在Guacamole中与用户打交道的就是Web应用程序. 之前说过,Web应用程序自己不实现任何的远程桌面协议.Web应用程序依赖guac ...

  4. django 视图开发与url配置

    可识别的视图需满足一下两个条件: 1.第一个参数的类型:HttpRequest 2.返回HttpResponse实例 在新建app的views当中写下以下内容 from django.shortcut ...

  5. 移动端页头推荐配置 出现找不到favicon.ico错误原因和解决方法

    favicon 在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico .为了保证 favicon 可访问,避免404,必须遵循以下两种方法之一: ...

  6. ACM: HDU 2563 统计问题-DFS+打表

    HDU 2563 统计问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u HDU 2 ...

  7. 洛谷 P1033 自由落体 Label:模拟&&非学习区警告

    题目描述 在高为 H 的天花板上有 n 个小球,体积不计,位置分别为 0,1,2,….n-1.在地面上有一个小车(长为 L,高为 K,距原点距离为 S1).已知小球下落距离计算公式为 d=1/2*g* ...

  8. NOI模拟赛Day2

    深深的感受到了自己的水 ---------------------------------------------------------------------------------------- ...

  9. 注解@PostConstruct与@PreDestroy讲解及实例

    从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...

  10. :nth-child(an+b)

    语法: :nth-child(an+b)为什么选择它,因为我认为,这个选择器是最多学问的一个了.很可惜,据我所测,目前能较好地支持她的只有Opera9+和Safari3+. 描述: 伪类:nth-ch ...