@(iOS 项目实战)[项目实战]
- 作者: Liwx
- 邮箱: 1032282633@qq.com
目录
- 新帖登录界面运行效果
- 1.新帖
- 推荐标签搭建
- 推荐标签相关知识点
- 2.关注和登陆界面
- 使用xib搭建关注界面
- 使用xib搭建登陆界面
- xib使用注意
新帖登录界面运行效果
1.新帖
推荐标签搭建
- 1.在push方法中统一设置跳转到非根控制器隐藏tabBar,必须在push前隐藏tabBar
// ----------------------------------------------------------------------------
// 重写pushViewController:方法,在跳转前统一设置返回按钮
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// ------------------------------------------------------------------------
// 1.判断如果不是根控制器,则设置viewController控制器返回按钮
if (self.childViewControllers.count > 0) {
// 必须在push前隐藏tabBar
viewController.hidesBottomBarWhenPushed = YES;
viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem backItemWithImage:[UIImage imageNamed:@"navigationButtonReturn"] highImage:[UIImage imageNamed:@"navigationButtonReturnClick"] target:self action:@selector(back) title:@"返回"];
}
[super pushViewController:viewController animated:animated];
}
- 2.设置推荐标签的标题两种方式,
self.title = @"标题文字"
,必须在非根控制器的时候才能这么使用
,否则有问题.
// 方式一
self.navigationItem.title = @“推荐标签”;
// 方式二,只有在非根控制器的时候才能这么使用,否则有问题.
self.title = @“推荐标签”;
-
3.获取推荐标签网络数据
- 接口文档
- 基本url: http://mobads.baidu.com/cpro/ui/mads.php
- 请求方式: GET
- 请求参数(必选): 参数tag_recommend,sub,topic
- 1.创建请求回话管理者
- 2.设置响应体的数据格式,添加@"text/html"(可选)
// ------------------------------------------------------------------------ // 2. 设置响应体的数据格式,添加@"text/html" AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer]; serializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil]; manager.responseSerializer = serializer;
-
3.拼接请求参数
-
4.发送请求,请求广告数据
- 4.1 获取广告数据 ,返回的广告数据是数组,有[],所以要用lastObject取出数据
- 4.2 字典转模型
mj_objectWithKeyValues:方法作用是将字典转换成对应的模型
- 4.3 设置广告界面的数据,返回数据中有广告图片的尺寸
注意
广告界面bug: 服务器返回的图片宽度有可能为0,需判断宽度是否为0,否则会出现NaN崩溃错误
,原因是因为除以0
, 不等于0才可以除. - 4.4 添加点击手势,点击图片跳转到广告页
- 默认UIImageView是不能与用户交互的,必须先
设置userInteractionEnabled属性为YES
;
- 默认UIImageView是不能与用户交互的,必须先
-
参考代码
// ---------------------------------------------------------------------------- // 请求广告数据 - (void)loadAdData { // ------------------------------------------------------------------------ // 1.创建请求回话管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // ------------------------------------------------------------------------ // 2. 设置响应体的数据格式,添加@"text/html" AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer]; serializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil]; manager.responseSerializer = serializer; // ------------------------------------------------------------------------ // 3.拼接请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"code2"] = code2; // ------------------------------------------------------------------------ // 4.请求广告数据 [manager GET:@"http://mobads.baidu.com/cpro/ui/mads.php" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 判断取回来的数据是否正确 // 4.1 获取广告数据 ,返回的广告数据是数组,有[],所以要用lastObject取出数据 NSDictionary *adDict = [responseObject[@"ad"] lastObject]; // 判断是否请求到数据,如果没有数据,则退出 if (adDict == nil) { return; } // 4.2 字典转模型 mj_objectWithKeyValues:方法作用是将字典转换成对应的模型 WXAdItem *adItem = [WXAdItem mj_objectWithKeyValues:adDict]; self.adItem = adItem; // 4.3 设置广告界面的数据,返回数据中有广告图片的尺寸 CGFloat w = screenW; // NaN:除以0, 不等于0才可以除 if (adItem.w) { // 计算宽高比例 CGFloat h = screenW / adItem.w * adItem.h; UIImageView *adImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, w, h)]; [adImageView sd_setImageWithURL:[NSURL URLWithString:adItem.w_picurl]]; [self.adView addSubview:adImageView]; adImageView.userInteractionEnabled = YES; // 4.4 添加点击手势,点击图片跳转到广告页 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)]; [adImageView addGestureRecognizer:tap]; } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@", error); }]; }
- 接口文档
- 4.搭建推荐标签界面
-
1.加载xib中cell的两种方式
-
NSBundle方式(必须在
xib绑定标识
才能循环利用cell)
xib绑定标识.png
static NSString * const ID = @"cell"; // 从缓冲池获取cell WXSubTagCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { // 从xib创建cell cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([WXSubTagCell class]) owner:nil options:nil] lastObject]; }
-
注册方式(使用
self.tableView registerNib
方法注册,可以不用在xib中绑定标识
)
// 在viewDidLoad方法中注册cell [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([WXSubTagCell class]) bundle:nil] forCellReuseIdentifier:ID];
-
NSBundle方式(必须在
-
2.展示cell数据
-
3.处理cell中的细节
- 圆形头像处理
- 方式一: 在awakeFromNib设置头像的圆角半径
layer.cornerRadius
并裁减masksToBounds
.
- 方式一: 在awakeFromNib设置头像的圆角半径
- (void)awakeFromNib { self.iconImageView.layer.cornerRadius = self.iconImageView.bounds.size.width * 0.5; self.iconImageView.layer.masksToBounds = YES; }
- 方式二: 在xib中使用KVC设置(不建议使用)
- 圆形头像处理
-
- 方式三: 先裁减图片,再显示到iconImageView
- 订阅数(子标题)处理
- 处理订阅数(超过万的时候处理,让小数点如果是.0,不显示.0,通过字符串替换,将.0替换成空串)
- cell分割线处理(具体如下操作)
- 5.cell分割线处理
-
方式一: 用
UIView自定义分割线
. -
方式二: 利用系统
tableView的separatorInset属性
. -
处理系统分割线(分割线靠最左边):
设置cell的layoutMargins
属性,只支持iOS8以上. -
方式三:
重写cell的setFrame实现(常用)
- 1.
取消系统的样式
separatorStyle为UITableViewCellSeparatorStyleNone - 2.设置tableView的背景色为分割线的颜色,目的是为了
让露出的背景部分充当分割线
. - 3.重写cell的setFrame方法,内部需先调用[super setFrame:frame];让frame的高度属性减去一个值,比如减去1,如果要让分割线更宽,减去的值为更大值即可.
- cell的尺寸和位置是在每次刷新表格/表格要显示的时候,先把所有cell位置全部计算出来.当cell要显示的时候,会从刚刚计算好的位置取出来给cell赋值.
- 1.
-
方式三实现参考代码
-
// WXSubTagViewController.m中取消tableView原本的分割线,设置tableView的背景色为分割线颜色
// ----------------------------------------------------------------------------
// 设置分割线,需在cell内部将cell高度-1,这样让漏出的背景充当分割线
- (void)setupSeparatorLine
{
// 分割线: 1.自定义分割线 2.利用系统属性 3.重写cellsetFrame
// 4.取消系统的分割线
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// 设置tableView背景色,之后将cell的高度-1,漏出的背景充当分割线
self.tableView.backgroundColor = WXColor(206, 206, 206);
}
// 在WXSubTagCell.m中
// ----------------------------------------------------------------------------
// 重写setFrame方法,目的是为了让分割线占据屏幕整个宽度
- (void)setFrame:(CGRect)frame
{
// 露出1pt充当背景分割线,
frame.size.height -= 1;
[super setFrame:frame];
}
-
6.AFN取消请求业务
- 发送请求前弹出指示器
- .在viewWillDisappear方法中隐藏指示器
- 在viewWillDisappear方法中使用AFHttpSessionManager的tasks属性(tasks是数组), 让数组里面的每个任务都调用cancel方法取消任务.
- viewWillDisappear方法内部实现参考代码
// ---------------------------------------------------------------------------- // 取消网络请求任务, 控制器的view即将消失的时候调用 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // 取消所有网络任务 [self.mgr.tasks makeObjectsPerformSelector:@selector(cancel)]; // 隐藏指示器 [SVProgressHUD dismiss]; }
推荐标签相关知识点
-
裁减图片步骤(存在锯齿)
- 1.开启位图上下文(
自适应位图上下文比例
) - 2.贝塞尔曲线描述裁减路径
- 3.设置裁减区域
- 4.绘图
- 5.从上下文获取才叫好的图片
- 6.关闭上下文
- 7.用抗锯齿分类设置圆形图片抗锯齿(抗锯齿实现原理: 生成1像素的图形边框)
- 裁减图片参考代码
// 1.开启位图上下文(自适应位图上下文比例) UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); // 2.贝塞尔曲线描述裁减路径 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; // 3.设置裁减区域 [path addClip]; // 4.绘图 [image drawAtPoint:CGPointZero]; // 5.从上下文获取裁剪好的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // 6.关闭上下文 UIGraphicsEndImageContext(); // 7.用抗锯齿分类设置圆形图片抗锯齿(抗锯齿实现原理: 生成1像素的图形边框) self.iconImageView.image = [newImage imageAntialias];
- 1.开启位图上下文(
-
tableView优化
- 帧数小于45就会出现明显感觉卡顿现象
- iOS9不需要担心圆角使帧数降低
-
观察刷新帧数工具: Core Animation工具(只能在真机上才能观察)
打开Core Animation
打开Core Animation.pngXcode的工具软件,选中Core Animation
Xcode的工具软件.png
Core Animation界面
Core Animation界面.png
2.关注和登陆界面
使用xib搭建关注界面
-
1.UILabel文字换行
- 1.UILabel在
xib实现换行按option + 回车
. - 2.代码实现换行只需在显示的文本添加\n
即可换行.
- 1.UILabel在
-
2.自动布局关注界面
- 1.设置立即登陆注册按钮为Custom类型,并设置按钮普通/高亮状态显示的内容.
-
3.绑定xib的管理类,并设置xib的view为控制器的view
-
关注界面效果图
关注界面效果图.png
使用xib搭建登陆界面
- 1.划分结构: 采用
占位视图思想
(3部分,顶部,中间,底部)
xib设计图
xib设计图.png
运行效果图,橙色背景色只是为方便分析而添加的.
运行效果图.png-
2.设置背景图片
-
3.布局顶部关闭和注册帐号按钮
- 1.设置注册帐号按钮普通/选中状态的文字.
-
4.自定义中间登陆LoginRegisterView
-
1.添加和帐号和密码的文本框背景一样尺寸的view,作为占位视图
-
2.添加ImageView到占位视图view中,
-
3.设置帐号密码文本框左右间距
-
修改文本框样式Border Style
修改文本框样式Border Style.png
-
-
4.设置登陆按钮
- 1.通过代码或使用xib设置(xib中KVC方式设置)设置圆角半径并裁减.
- 2.在awakeFromNib方法中获取按钮的背景图片,并重新生成拉伸中间1x1的图片.
获取按钮当前状态背景图片:currentBackgroundImage属性获取当前按钮状态的背景图片
.
-
5.在同一个xib描述两个不同的view
- 1.提供一个快速创建登陆view的类方法
-
2.提供一个快速创建注册view的类方法
xib描述两个不同的view.png
-
6.登陆和注册界面动画
-
1.通过修改约束来实现修改登陆和注册界面的位置,从
约束拖线关联.pngxib中将最左边的间距拖入代码成为属性
.
-
2.点击注册按钮实现自动布局动画参考代码
-
更新约束强制刷新方法layoutIfNeeded
,如果没有调用layoutIfNeeded方法,不会立即更新
.
-
-
// ---------------------------------------------------------------------------- // 注册按钮点击 - (IBAction)registerOrLogin:(UIButton *)sender { // 1.切换选中状态 sender.selected = !sender.isSelected; // 2.更新约束 self.leftMargin.constant = self.leftMargin.constant == 0 ? -screenW : 0; // 3.执行动画(更新约束动画刷新方法layoutIfNeeded) [UIView animateWithDuration:0.25 animations:^{ // 3.1 强制刷新 [self.view layoutIfNeeded]; }]; }
- 7.通过
xib创建的控件,加载时默认是xib的位置尺寸
.从xib加载的view必须再重新设置frame来适配不同屏幕
.- 1.
不要在viewDidLoad方法中重新设置frame
,最好在viewDidLayoutSubviews方法中重新设置xib中view的frame
.
- 1.
-
-
5.底部快速登陆界面
- 1.布局底部三个第三方登陆按钮.
- 2.自定义按钮,调整按钮的位置,让图标显示在上面,标题显示在下面.
- 投机方式: 通过
改变按钮的imageView和titleLabel内边距
(不建议使用) -
自定义FastLoginButton
并重写layoutSubviews重新布局
按钮的子控件,图片放置顶部,标题放置底部.-
重新计算文字的宽度,在给titleLabel宽度赋值,否则会出现文字用…显示
.使用[self.titleLabel sizeToFit]
就能解决.
-
- 投机方式: 通过
-
3.设置快速登陆UILabel和左右两边的线条UIImageView,设置UIImageView的contentMode,左边线设置为Right模式,右边先设置为Left模式.
设置UIImageView的contentMode.png
xib使用注意
-
1.从xib加载的view必须要重新设置位置和尺寸.
-
2.不要在viewDidLoad方法中重新设置frame,最好
在viewDidLayoutSubviews方法中重新设置xib中view的frame
.
网友评论