iOS---精仿手工课~(Objective-C)
2016-07-21 08:23
375 查看
前言
手工课是利用业余时间完成的一个项目,这个项目适合刚刚接触 iOS 开发的新手用来练手,首先,这个开源项目中用到了许多优秀的开源框架,感谢开源,好了,废话不多说.让我们先来看一下这个项目中涉及到的知识点:利用 UICollectionView 实现常见界面的搭建,以及自定义布局
转场动画的实现
利用 FMDB 实现数据储存
简单动画的实现
利用 Block实现封装一个常用的控件
如何封装一个常用的控制器
如何更好的使用三方类库,比如(AFN...)
我本来就是菜鸟,(看我名字就可以看出来了),希望各大神在代码结构给予指导.......,最后说一句,开源万岁
效果预览
新版本.gif
首页-精选.gif
首页-精选-直播.gif
教程01.gif
市集.gif
手工圈.gif
首页-达人.gif
首页-关注.gif
首页-活动01.gif
我的.gif
教程02.gif
首页-活动02.gif
首页-精选-02.gif
代码结构
Snip20160717_1.png
代码结构我比较喜欢按照业务来区分,大概就是这样子了
新版本特性
思路和实现都比较简单,需要注意的一点是将判断是否有新版本的逻辑提取出来,直接上代码AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; self.window.rootViewController = [GPGuideTool chooseRootViewController]; [self configApper]; [self.window makeKeyAndVisible]; return YES; }
判断逻辑
// 加载哪个控制器 + (UIViewController *)chooseRootViewController { UIViewController *rootVc = nil; NSDictionary *dict = [NSBundle mainBundle].infoDictionary; // 获取最新的版本号 NSString *curVersion = dict[@"CFBundleShortVersionString"]; // 获取上一次的版本号 NSString *lastVersion = [GPUserDefaults objectForKey:GPVersionKey]; // 之前的最新的版本号 lastVersion if ([curVersion isEqualToString:lastVersion]) { // 版本号相等 rootVc = [[GPAdViewController alloc]init]; }else{ // 有最新的版本号 // 保存到偏好设置 [[NSUserDefaults standardUserDefaults] setObject:curVersion forKey:GPVersionKey]; rootVc = [[GPNewFeatureController alloc]init]; } return rootVc; }
新特性界面实现
- (instancetype)init { // 流水布局 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; // 设置cell的尺寸 layout.itemSize = [UIScreen mainScreen].bounds.size; // 设置每一行的间距 layout.minimumLineSpacing = 0; // 设置每个cell的间距 layout.minimumInteritemSpacing = 0; // 设置滚动方向 layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; return [self initWithCollectionViewLayout:layout]; } - (void)viewDidLoad { [super viewDidLoad]; [self setUpCollectionView]; } // 初始化CollectionView - (void)setUpCollectionView { // 注册cell [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([GPNewFeatureCell class]) bundle:nil] forCellWithReuseIdentifier:reuseIdentifier]; // 取消弹簧效果 self.collectionView.bounces = NO; // 取消显示指示器 self.collectionView.showsHorizontalScrollIndicator = NO; // 开启分页模式 self.collectionView.pagingEnabled = YES; } #pragma mark <UICollectionViewDataSource> - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 5; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { GPNewFeatureCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; NSString *imageName = [NSString stringWithFormat:@"newfeature_0%ld_736",indexPath.item + 1]; cell.image = [UIImage imageNamed:imageName]; return cell; } #pragma mark <UICollectionViewDelegate> - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 4) { // 切换窗口的根控制器进行跳转 [UIApplication sharedApplication].keyWindow.rootViewController = [[GPAdViewController alloc]init]; CATransition *anim = [CATransition animation]; anim.type = @"rippleEffect"; anim.duration = 1; [[UIApplication sharedApplication].keyWindow.layer addAnimation:anim forKey:nil]; } }
请求数据
方式一
直接在 AFN上面简单包装一下+(void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id responseObj))success failure:(void (^)(NSError *))failure { AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { if (success) { success(responseObject); } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { if (failure) { failure(error); } }]; } +(void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id responseObj))success failure:(void (^)(NSError *))failure { AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager]; [mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { if (success) { success(responseObject); } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { if (failure) { failure(error); } }]; }
方式二
在上面的基础上再次进行封装+ (void)getWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure { NSDictionary *params = [param mj_keyValues]; [GPHttpTool get:url params:params success:^(id responseObj) { if (success) { id result = [resultClass mj_objectWithKeyValues:responseObj[@"data"]]; success(result); } } failure:^(NSError *error) { if (failure) { failure(error); } }]; } + (void)getMoreWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure { NSDictionary *params = [param mj_keyValues]; [GPHttpTool get:url params:params success:^(id responseObj) { if (success) { id result = [resultClass mj_objectArrayWithKeyValuesArray:responseObj[@"data"]]; success(result); } } failure:^(NSError *error) { if (failure) { failure(error); } }]; } + (void)postWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure { NSDictionary *params = [param mj_keyValues]; [GPHttpTool post:url params:params success:^(id responseObj) { if (success) { id result = [resultClass mj_objectWithKeyValues:responseObj]; success(result); } } failure:^(NSError *error) { if (failure) { failure(error); } }]; }
首页
Snip20160718_2.png
首页的整体布局是用 UICollection View 实现的, 这里只贴一下关键代码,具体代码可以下载源代码查看
首页可滚动标题栏在多个地方涉及到,所以可以自己进行简单封装,这里我简单封装一下,在开源项目中此处我用到了一个优秀的三方:
#pragma mark - 懒加载 - (NSMutableArray *)btnArray { if (!_btnArray) { _btnArray = [[NSMutableArray alloc] init]; } return _btnArray; } - (instancetype)initWithChildControllerS:(NSArray *)titleArray { if (self = [super init]) { self.titleArray = titleArray; [self layout]; } return self; } - (void)layout { UIButton *lastBtn = nil; for (int i = 0; i < self.titleArray.count; i ++) { UIButton *btn = [[UIButton alloc]init]; [btn setTitle:self.titleArray[i] forState:UIControlStateNormal]; [btn setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateNormal]; [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; btn.userInteractionEnabled = NO; [self.btnArray addObject:btn]; [self addSubview:btn]; if (lastBtn) { btn.sd_layout .leftSpaceToView(lastBtn,40) .topSpaceToView(lastBtn,0) .bottomSpaceToView(lastBtn,0) .widthIs(40); }else{ btn.sd_layout .leftSpaceToView(self,0) .topSpaceToView(self,0) .bottomSpaceToView(self,0) .widthIs(40); } lastBtn = btn; } [self setupAutoWidthWithRightView:lastBtn rightMargin:0]; } // 改变按钮状态 -(void)changeSelectBtn:(UIButton *)btn { self.previousBtn = self.currentBtn; self.currentBtn = btn; self.previousBtn.selected = NO; self.currentBtn.selected = YES; } // 更新按钮状态 -(void)updateSelecterToolsIndex:(NSInteger )index { UIButton *selectBtn = self.btnArray[index]; [self changeSelectBtn:selectBtn]; }
可滚动视图
- (instancetype)initWithChildControllerS:(NSArray *)vcArray selectBlock:(selecBlock)selecB { if (self = [super init]) { self.selecB = selecB; self.backgroundColor = [UIColor whiteColor]; self.pagingEnabled = YES; self.showsVerticalScrollIndicator = NO; self.showsHorizontalScrollIndicator = NO; self.delegate = self; self.childVcArray = vcArray; [self layout]; } return self; } - (void)layout { UIView *lastView = nil; for (UIViewController *viewVc in self.childVcArray) { [self addSubview:viewVc.view]; if (lastView) { viewVc.view.sd_layout .widthIs(SCREEN_WIDTH) .heightIs(SCREEN_HEIGHT) .leftSpaceToView(lastView,0); }else{ viewVc.view.sd_layout .widthIs(SCREEN_WIDTH) .heightIs(SCREEN_HEIGHT) .leftSpaceToView(self,0); } lastView = viewVc.view; } [self setupAutoContentSizeWithRightView:lastView rightMargin:0]; } -(void)updateVCViewFromIndex:(NSInteger )index { [self setContentOffset:CGPointMake(index*SCREEN_WIDTH, 0) animated:YES]; } -(void)scrollViewDidScroll:(UIScrollView *)scrollView { int page = (scrollView.contentOffset.x + SCREEN_WIDTH / 2) / SCREEN_WIDTH; self.selecB(page); }
轮播图
无限滚动的简单思路就是,当滚动到最右边或最左边的时候,交换图片,具体贴代码
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CGFloat w = self.view.frame.size.width; CGFloat h = self.view.frame.size.height; // 初始化scrollView _scrollView.pagingEnabled = YES; _scrollView.contentSize = CGSizeMake(w * 3, 0); _scrollView.contentOffset = CGPointMake(w, 0); _scrollView.showsHorizontalScrollIndicator = NO; _scrollView.delegate = self; // 创建可见的imageView UIImageView *visibleView = [[UIImageView alloc] init]; _visibleView = visibleView; _visibleView.image = [UIImage imageNamed:@"00"]; _visibleView.frame = CGRectMake(w, 0, w, h); _visibleView.tag = 0; [_scrollView addSubview:_visibleView]; // 创建重复利用的imageView UIImageView *reuseView = [[UIImageView alloc] init]; _reuseView = reuseView; _reuseView.frame = self.view.bounds; [_scrollView addSubview:_reuseView]; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { // 获取偏移量 CGFloat offsetX = scrollView.contentOffset.x; CGFloat w = scrollView.frame.size.width; // 1.设置 循环利用view 的位置 CGRect f = _reuseView.frame; NSInteger index = 0; if (offsetX > _visibleView.frame.origin.x) { // 显示在最右边 f.origin.x = scrollView.contentSize.width - w; index = _visibleView.tag + 1; if (index >= kCount) index = 0; } else { // 显示在最左边 f.origin.x = 0; index = _visibleView.tag - 1; if (index < 0) index = kCount - 1; } // 设置重复利用的视图 _reuseView.frame = f; _reuseView.tag = index; NSString *icon = [NSString stringWithFormat:@"0%ld", index]; _reuseView.image = [UIImage imageNamed:icon]; // 2.滚动到 最左 或者 最右 的图片 if (offsetX <= 0 || offsetX >= w * 2) { // 2.1.交换 中间的 和 循环利用的指针 UIImageView *temp = _visibleView; _visibleView = _reuseView; _reuseView = temp; // 2.2.交换显示位置 _visibleView.frame = _reuseView.frame; // 2.3 初始化scrollView的偏移量 scrollView.contentOffset = CGPointMake(w, 0); } }
滑动动画
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { CATransform3D rotation;//3D旋转 // rotation = CATransform3DMakeTranslation(0 ,50 ,20); rotation = CATransform3DMakeRotation( M_PI_4 , 0.0, 0.7, 0.4); //逆时针旋转 rotation = CATransform3DScale(rotation, 0.8, 0.8, 1); rotation.m34 = 1.0/ 1000; cell.layer.shadowColor = [[UIColor redColor]CGColor]; cell.layer.shadowOffset = CGSizeMake(10, 10); cell.alpha = 0; cell.layer.transform = rotation; [UIView beginAnimations:@"rotation" context:NULL]; //旋转时间 [UIView setAnimationDuration:0.6]; cell.layer.transform = CATransform3DIdentity; cell.alpha = 1; cell.layer.shadowOffset = CGSizeMake(0, 0); [UIView commitAnimations]; }
转场动画
关于转场动画,网上有好多大神写的博客,这里我就直接贴一些地址,有兴趣的可以看看,喵神,
wr大神;
登录界面
Snip20160718_8.png
登录界面是Jake lin的一个swift课程,我用OC 重新实现了一遍
#pragma mark - 生命周期 - (void)viewDidLoad { [super viewDidLoad]; [self setupView]; [self setupAnimtion]; [self addEventBar]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self nextAnimtion]; } #pragma mark - 初始化 - (void)setupView { self.navigationController.navigationBarHidden = YES; UIActivityIndicatorView *acView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; self.acView = acView; UIImageView *snipImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Warning"]]; snipImageView.hidden = YES; [self.view addSubview:snipImageView]; self.snipImageView = snipImageView; } - (void)addEventBar { GPEventBtn *eventBtn = [[GPEventBtn alloc]init]; [eventBtn setImage:[UIImage imageNamed:@"activity_works_Btn"] forState:UIControlStateNormal]; [eventBtn sizeToFit]; eventBtn.transform = CGAffineTransformMakeScale(2, 2); [eventBtn showEventButCenter:CGPointMake(SCREEN_WIDTH * 0.5 , SCREEN_HEIGHT - GPEventScale * eventBtn.width)]; eventBtn.transform = CGAffineTransformMakeScale(2, 2); [eventBtn addTarget:self action:@selector(dismissVc) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:eventBtn]; [self.view bringSubviewToFront:eventBtn]; eventBtn.hidden = YES; self.eventBtn = eventBtn; } #pragma mark - 动画 - (void)setupAnimtion { self.buble1.transform = CGAffineTransformMakeScale(0, 0); self.buble2.transform = CGAffineTransformMakeScale(0, 0); self.buble3.transform = CGAffineTransformMakeScale(0, 0); self.buble4.transform = CGAffineTransformMakeScale(0, 0); self.buble5.transform = CGAffineTransformMakeScale(0, 0); self.logo.centerX-= self.view.width; self.dot.centerX -= self.view.width/2; UIView *paddingUserView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, self.userName.height)]; self.userName.leftView = paddingUserView; self.userName.leftViewMode = UITextFieldViewModeAlways; UIView *paddingPassView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, self.password.height)]; self.password.leftView = paddingPassView; self.password.leftViewMode = UITextFieldViewModeAlways; UIImageView *userImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"User"]]; userImageView.x = 5; userImageView.y = 5; [self.userName addSubview:userImageView]; UIImageView *passImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Key"]]; passImageView.x = 5; passImageView.y = 5; [self.password addSubview:passImageView]; self.userName.centerX -= self.view.width; self.password.centerX -= self.view.width; self.loginBtn.centerX -= self.view.width; } - (void)nextAnimtion { [UIView animateWithDuration:0.3 delay:0.3 usingSpringWithDamping:0.4 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.buble1.transform = CGAffineTransformMakeScale(1, 1); self.buble2.transform = CGAffineTransformMakeScale(1, 1); self.buble3.transform = CGAffineTransformMakeScale(1, 1); } completion:nil]; [UIView animateWithDuration:0.3 delay:0.4 usingSpringWithDamping:0.4 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.buble4.transform = CGAffineTransformMakeScale(1, 1); self.buble5.transform = CGAffineTransformMakeScale(1, 1); } completion:nil]; [UIView animateWithDuration:0.5 delay:0.5 usingSpringWithDamping:0.6 initialSpringVelocity:0.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.logo.centerX += self.view.width; } completion:nil]; [UIView animateWithDuration:0.4 delay:0.6 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.userName.centerX += self.view.width; } completion:nil]; [UIView animateWithDuration:0.4 delay:0.7 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.password.centerX += self.view.width; } completion:nil]; [UIView animateWithDuration:0.4 delay:0.8 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.loginBtn.centerX += self.view.width; } completion:nil]; [UIView animateWithDuration:3 delay:1 usingSpringWithDamping:0.1 initialSpringVelocity:0.6 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.dot.centerX += self.view.width * 0.4; } completion:nil]; } #pragma mark - 内部方法 - (IBAction)loginBtnClick:(UIButton *)sender { self.loginBtn.enabled = NO; self.acView.center = CGPointMake(0, 0); [self.acView startAnimating]; [self.loginBtn addSubview:self.acView]; self.snipImageView.center = self.loginBtn.center; self.loginPoint = self.loginBtn.center; [UIView animateWithDuration:0.3 animations:^{ self.loginBtn.centerX -= 30; }completion:^(BOOL finished) { [UIView animateWithDuration:1.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.loginBtn.centerX += 30; } completion:^(BOOL finished) { [UIView animateWithDuration:0.3 animations:^{ self.loginBtn.centerY += 90; [self.acView removeFromSuperview]; }completion:^(BOOL finished) { [UIView transitionWithView:self.snipImageView duration:0.3 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{ self.snipImageView.hidden = NO; }completion:^(BOOL finished) { [UIView transitionWithView:self.snipImageView duration:3 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.snipImageView.hidden = YES; } completion:^(BOOL finished) { [UIView animateWithDuration:0.2 animations:^{ self.loginBtn.center = self.loginPoint; }completion:^(BOOL finished) { self.loginBtn.enabled = YES; }]; }]; }]; }]; }]; }]; } - (void)dismissVc { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self.loginBtn removeFromSuperview]; [UIView transitionWithView:self.eventBtn duration:0.5 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{ self.eventBtn.hidden = NO; } completion:nil]; }
直播
Snip20160718_9.png
聊天界面搭建,用到了
SDAutoLayout,感兴趣的可以学习一下
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { [self setupView]; } return self; } - (void)setupView { self.selectionStyle = UITableViewCellSelectionStyleNone; _iconImageView = [UIImageView new]; [self.contentView addSubview:_iconImageView]; _container = [UIView new]; [self.contentView addSubview:_container]; _label = [MLEmojiLabel new]; _label.delegate = self; _label.font = [UIFont systemFontOfSize:16.0f]; _label.numberOfLines = 0; _label.textInsets = UIEdgeInsetsMake(0, 0, 0, 0); _label.isAttributedContent = YES; [_container addSubview:_label]; _messageImageView = [UIImageView new]; [_container addSubview:_messageImageView]; _containerBackgroundImageView = [UIImageView new]; [_container insertSubview:_containerBackgroundImageView atIndex:0]; _maskImageView = [UIImageView new]; [self setupAutoHeightWithBottomView:_container bottomMargin:0]; // 设置containerBackgroundImageView填充父view _containerBackgroundImageView.sd_layout.spaceToSuperView(UIEdgeInsetsMake(0, 0, 0, 0)); } - (void)setModel:(GPChatData *)model { _model = model; _label.text = model.text; // 根据model设置cell左浮动或者右浮动样式 [self setMessageOriginWithModel:model]; if (model.imageName) { // 有图片的先看下设置图片自动布局 // cell重用时候清除只有文字的情况下设置的container宽度自适应约束 [self.container clearAutoWidthSettings]; self.messageImageView.hidden = NO; self.messageImageView.image = [UIImage imageNamed:model.imageName]; // 根据图片的宽高尺寸设置图片约束 CGFloat standardWidthHeightRatio = kMaxChatImageViewWidth / kMaxChatImageViewHeight; CGFloat widthHeightRatio = 0; UIImage *image = [UIImage imageNamed:model.imageName]; CGFloat h = image.size.height; CGFloat w = image.size.width; if (w > kMaxChatImageViewWidth || w > kMaxChatImageViewHeight) { widthHeightRatio = w / h; if (widthHeightRatio > standardWidthHeightRatio) { w = kMaxChatImageViewWidth; h = w * (image.size.height / image.size.width); } else { h = kMaxChatImageViewHeight; w = h * widthHeightRatio; } } self.messageImageView.size_sd = CGSizeMake(w, h); _container.sd_layout.widthIs(w).heightIs(h); // 设置container以messageImageView为bottomView高度自适应 [_container setupAutoHeightWithBottomView:self.messageImageView bottomMargin:kChatCellItemMargin]; // container按照maskImageView裁剪 self.container.layer.mask = self.maskImageView.layer; __weak typeof(self) weakself = self; [_containerBackgroundImageView setDidFinishAutoLayoutBlock:^(CGRect frame) { // 在_containerBackgroundImageView的frame确定之后设置maskImageView的size等于containerBackgroundImageView的size weakself.maskImageView.size_sd = frame.size; }]; } else if (model.text) { // 没有图片有文字情况下设置文字自动布局 // 清除展示图片时候用到的mask [_container.layer.mask removeFromSuperlayer]; self.messageImageView.hidden = YES; // 清除展示图片时候_containerBackgroundImageView用到的didFinishAutoLayoutBlock _containerBackgroundImageView.didFinishAutoLayoutBlock = nil; _label.sd_resetLayout .leftSpaceToView(_container, kLabelMargin) .topSpaceToView(_container, kLabelTopMargin) .autoHeightRatio(0); // 设置label纵向自适应 // 设置label横向自适应 [_label setSingleLineAutoResizeWithMaxWidth:kMaxContainerWidth]; // container以label为rightView宽度自适应 [_container setupAutoWidthWithRightView:_label rightMargin:kLabelMargin]; // container以label为bottomView高度自适应 [_container setupAutoHeightWithBottomView:_label bottomMargin:kLabelBottomMargin]; } } - (void)setMessageOriginWithModel:(GPChatData *)model { if (model.messageType == GPMessageTypeSendToOthers) { self.iconImageView.image = [UIImage imageNamed:@"001"]; // 发出去的消息设置居右样式 self.iconImageView.sd_resetLayout .rightSpaceToView(self.contentView, kChatCellItemMargin) .topSpaceToView(self.contentView, kChatCellItemMargin) .widthIs(kChatCellIconImageViewWH) .heightIs(kChatCellIconImageViewWH); _container.sd_resetLayout.topEqualToView(self.iconImageView).rightSpaceToView(self.iconImageView, kChatCellItemMargin); _containerBackgroundImageView.image = [[UIImage imageNamed:@"SenderTextNodeBkg"] stretchableImageWithLeftCapWidth:50 topCapHeight:30]; } else if (model.messageType == GPMessageTypeSendToMe) { self.iconImageView.image = [UIImage imageNamed:@"003"]; // 收到的消息设置居左样式 self.iconImageView.sd_resetLayout .leftSpaceToView(self.contentView, kChatCellItemMargin) .topSpaceToView(self.contentView, kChatCellItemMargin) .widthIs(kChatCellIconImageViewWH) .heightIs(kChatCellIconImageViewWH); _container.sd_resetLayout.topEqualToView(self.iconImageView).leftSpaceToView(self.iconImageView, kChatCellItemMargin); _containerBackgroundImageView.image = [[UIImage imageNamed:@"ReceiverTextNodeBkg"] stretchableImageWithLeftCapWidth:50 topCapHeight:30]; } _maskImageView.image = _containerBackgroundImageView.image; } #pragma mark - MLEmojiLabelDelegate - (void)mlEmojiLabel:(MLEmojiLabel *)emojiLabel didSelectLink:(NSString *)link withType:(MLEmojiLabelLinkType)type { if (self.didSelectLinkTextOperationBlock) { self.didSelectLinkTextOperationBlock(link, type); } }
关注
这个界面,有一个下拉弹簧的效果,自定义了流水布局来实现
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; } - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { CGFloat offsetY = self.collectionView.contentOffset.y; NSArray *attrsArray = [super layoutAttributesForElementsInRect:rect]; CGFloat collectionViewFrameHeight = self.collectionView.frame.size.height; CGFloat collectionViewContentHeight = self.collectionView.contentSize.height; CGFloat ScrollViewContentInsetBottom = self.collectionView.contentInset.bottom; CGFloat bottomOffset = offsetY + collectionViewFrameHeight - collectionViewContentHeight - ScrollViewContentInsetBottom; CGFloat numOfItems = [self.collectionView numberOfItemsInSection:nil]; for (UICollectionViewLayoutAttributes *attr in attrsArray) { if (attr.representedElementCategory == UICollectionElementCategoryCell) { CGRect cellRect = attr.frame; if (offsetY <= 0) { CGFloat distance = fabs(offsetY) / 8; cellRect.origin.y += offsetY + distance * (CGFloat)(attr.indexPath.section + 1); }else if (bottomOffset > 0 ){ CGFloat distance = bottomOffset / 8; cellRect.origin.y += bottomOffset - distance *(CGFloat)(numOfItems - attr.indexPath.section); } attr.frame = cellRect; } } return attrsArray; }
达人
Snip20160718_14.png
同样使用 UICoolectionView 布局,代码比较多可以看源码
#pragma mark - 初始化 - (instancetype)init { // 流水布局 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.itemSize =[UIScreen mainScreen].bounds.size; layout.minimumLineSpacing = 0; layout.minimumInteritemSpacing = 0; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; return [self initWithCollectionViewLayout:layout]; } - (void)setupNav { self.collectionView.showsHorizontalScrollIndicator = NO; self.collectionView.pagingEnabled = YES; self.collectionView.bounces = NO; self.collectionView.backgroundColor = [UIColor whiteColor]; UIButton *disBtn = [[UIButton alloc]init]; [disBtn setImage:[UIImage imageNamed:@"Image"] forState:UIControlStateNormal]; disBtn.frame = CGRectMake(5, 25, 20, 20); [disBtn addTarget:self action:@selector(disBtnClick) forControlEvents:UIControlEventTouchUpInside]; [self.collectionView addSubview:disBtn]; } - (void)regisCell { [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([GPDaRenStepOneCell class]) bundle:nil] forCellWithReuseIdentifier:OneIdentifier]; [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([GPDaRenStepTwoCell class]) bundle:nil] forCellWithReuseIdentifier:TwoIdentifier]; [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([GPDaRenStepThreeCell class]) bundle:nil] forCellWithReuseIdentifier:TheerIdentifier]; } - (void)loadData { // 1.添加参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"c"] = @"Course"; params[@"a"] = @"CourseDetial"; params[@"vid"] = @"18"; params[@"id"] = self.tagCpunt; __weak typeof(self) weakSelf = self; // 2.发起请求 [GPHttpTool get:HomeBaseURl params:params success:^(id responder) { weakSelf.picData = [GPDaRenPicData mj_objectWithKeyValues:responder[@"data"]]; weakSelf.stepArray = weakSelf.picData.step; weakSelf.stepToolsArray = weakSelf.picData.tools; weakSelf.stepMaetasArray = weakSelf.picData.material; weakSelf.stepPicArray = weakSelf.picData.step; [weakSelf.collectionView reloadData]; } failure:^(NSError *error) { [SVProgressHUD showErrorWithStatus:@"跪了"]; }]; } #pragma mark <UICollectionViewDataSource> - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 3; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { NSInteger row = 1; if (section == 2) { row = self.stepArray.count; } return row; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *collecTionCell = nil; if (indexPath.section == 0) { GPDaRenStepOneCell *oneCell = [collectionView dequeueReusableCellWithReuseIdentifier:OneIdentifier forIndexPath:indexPath]; oneCell.picData = self.picData; collecTionCell = oneCell; }else if (indexPath.section == 1){ GPDaRenStepTwoCell *twoCell = [collectionView dequeueReusableCellWithReuseIdentifier:TwoIdentifier forIndexPath:indexPath]; twoCell.toolsArray = self.stepToolsArray; twoCell.materiaArray = self.stepMaetasArray; collecTionCell = twoCell; }else{ GPDaRenStepThreeCell *threeCell = [collectionView dequeueReusableCellWithReuseIdentifier:TheerIdentifier forIndexPath:indexPath]; threeCell.sumNum = self.stepPicArray.count; threeCell.currentNum = indexPath.row + 1; threeCell.setpData = self.stepPicArray[indexPath.row]; threeCell.setpBtnClick = ^{ [self setpPicBtnClick]; }; collecTionCell = threeCell; } return collecTionCell; } #pragma mark - 内部方法 - (void)disBtnClick { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)setpPicBtnClick { XWCoolAnimator *animator = [XWCoolAnimator xw_animatorWithType:XWCoolTransitionAnimatorTypePageFlip]; GPDaRenPicsController *picsVc = [[GPDaRenPicsController alloc]init]; picsVc.stepDataArray = self.stepPicArray; picsVc.picData = self.picData; [self xw_presentViewController:picsVc withAnimator:animator]; } -(void)scroolCollection:(NSNotification *)ifno { NSLog(@"%@",ifno.userInfo[@"pic"]); NSIndexPath *indexPath = ifno.userInfo[@"pic"]; CGPoint point = CGPointMake((indexPath.row + 2) * SCREEN_WIDTH, 0); [self.collectionView setContentOffset:point]; }
活动
首页-活动01.gif
首页-活动02.gif
活动界面看似较多,其实就是用了两个 UICollectionView 做的子控制器,类似盆友圈的界面,需要注意离屏渲染,直接设置圆角会导致严重的卡顿
#pragma mark - 生命周期 - (void)viewDidLoad { [super viewDidLoad]; [self regisCell]; [self configThame]; [self loadData]; self.title = @"我的作品"; } - (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [SVProgressHUD dismiss]; } #pragma mark - 懒加载 - (NSMutableArray *)picUrlS { if (!_picUrlS) { _picUrlS = [[NSMutableArray alloc] init]; } return _picUrlS; } - (NSMutableArray *)laudUrlS { if (!_laudUrlS) { _laudUrlS = [[NSMutableArray alloc] init]; } return _laudUrlS; } - (NSMutableArray *)sizeArray { if (!_sizeArray) { _sizeArray = [[NSMutableArray alloc] init]; } return _sizeArray; } #pragma mark - 初始化 - (void)regisCell { [self.tableView registerClass:[GPTimeLineHeadCell class] forCellReuseIdentifier:HeadCell]; [self.tableView registerClass:[GPTimeLineEventCell class] forCellReuseIdentifier:EventCell]; [self.tableView registerClass:[GPTimeLineApperCell class] forCellReuseIdentifier:ApperCell]; [self.tableView registerClass:[GPTimeLIneCommentCell class] forCellReuseIdentifier:CommentCell]; } - (void)configThame { self.view.backgroundColor = [UIColor whiteColor]; } #pragma mark - 数据处理 - (void)loadData { // 1.添加请求参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"c"] = @"HandCircle"; params[@"a"] = @"info"; params[@"vid"] = @"18"; params[@"item_id"] = self.circleID; __weak typeof(self) weakSelf = self; // 2.请求数据 [GPHttpTool get:HomeBaseURl params:params success:^(id responseObj) { weakSelf.timeLineData = [GPTimeLineData mj_objectWithKeyValues:responseObj[@"data"]]; // 九宫格图片 for (GPTimeLinePicData *PicData in weakSelf.timeLineData.pic) { [weakSelf.picUrlS addObject:PicData.url]; } // 只有一张图片的尺寸 GPTimeLinePicData *picFistData = weakSelf.timeLineData.pic.firstObject; [weakSelf.sizeArray addObjectsFromArray:@[picFistData.width,picFistData.height]]; // 点赞头像 for (GPTimeLineLaudData *laudData in weakSelf.timeLineData.laud_list) { [weakSelf.laudUrlS addObject:laudData.avatar]; } // 评论 weakSelf.commentS = weakSelf.timeLineData.comment; [weakSelf.tableView reloadData]; } failure:^(NSError *error) { [SVProgressHUD showErrorWithStatus:@"小编出差了"]; }]; } #pragma mark - 内部方法 #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger sectionRow = 1; if (section == 3) { sectionRow = self.commentS.count; } return sectionRow; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { GPTimeLineHeadCell *headLineCell = [tableView dequeueReusableCellWithIdentifier:HeadCell]; headLineCell.sizeArray = self.sizeArray; headLineCell.timeLineData = self.timeLineData; headLineCell.picUrlArray = self.picUrlS; return headLineCell; }else if(indexPath.section == 1){ GPTimeLineEventCell *timeEventCell = [tableView dequeueReusableCellWithIdentifier:EventCell]; timeEventCell.lineData = self.timeLineData; timeEventCell.EventBtnClick = ^{ [self eventBtnClcik]; }; timeEventCell.backgroundColor = [UIColor whiteColor]; return timeEventCell; }else if (indexPath.section == 2){ GPTimeLineApperCell *timeApperCell = [tableView dequeueReusableCellWithIdentifier:ApperCell]; timeApperCell.laudnum = self.timeLineData.laud_num; timeApperCell.laudArray = self.laudUrlS; return timeApperCell; }else{ GPTimeLIneCommentCell *timeCommentCell = [tableView dequeueReusableCellWithIdentifier:CommentCell]; timeCommentCell.commentData = self.timeLineData.comment[indexPath.row]; return timeCommentCell; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [self cellHeightForIndexPath:indexPath cellContentViewWidth:SCREEN_WIDTH]; } #pragma mark - 内部方法 - (void)eventBtnClcik { GPLoginController *loginVc = [UIStoryboard storyboardWithName:@"GPLoginController" bundle:nil].instantiateInitialViewController; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:loginVc]; self.transition = [[HYBEaseInOutTransition alloc] initWithPresented:^(UIViewController *presented, UIViewController *presenting, UIViewController *source, HYBBaseTransition *transition) { HYBEaseInOutTransition *modal = (HYBEaseInOutTransition *)transition; modal.animatedWithSpring = YES; } dismissed:^(UIViewController *dismissed, HYBBaseTransition *transition) { // do nothing }]; nav.transitioningDelegate = self.transition; [self presentViewController:nav animated:YES completion:NULL]; }
教程
Snip20160718_15.png
Snip20160718_16.png
- (void)viewDidLoad { [super viewDidLoad]; [self addNavTitleView]; [self addChildVc]; [self addConterView]; // [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(setGes) name:@"dawang" object:nil]; } - (void)dealloc{ [[NSNotificationCenter defaultCenter]removeObserver:self]; } #pragma mark - 初始化 - (void)addNavTitleView { __weak typeof(self) weakSelf = self; GPNavTitleView *titleView = [[GPNavTitleView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH * 0.6, 44) block:^(UIButton *button) { [weakSelf.containView updateVCViewFromIndex:button.tag]; }]; self.titleView = titleView; self.navigationItem.titleView = titleView; } // 添加子控制器 - (void)addChildVc { self.picVc = [[GPTutorialPicController alloc]init]; self.videoVc = [[GPTutoriaVideoController alloc]init]; self.subVc = [[GPTutoriSubController alloc]init]; self.chidVcArray = @[self.picVc,self.videoVc,self.subVc]; [self addChildViewController:self.picVc]; [self addChildViewController:self.videoVc]; [self addChildViewController:self.subVc]; } // 添加容器 - (void)addConterView { __weak typeof(self) weakSelf = self; self.containView = [[GPContainerView alloc]initWithChildControllerS:self.chidVcArray selectBlock:^(int index) { [weakSelf.titleView updateSelecterToolsIndex:index]; }]; [self.view addSubview:self.containView]; self.containView.sd_layout.spaceToSuperView(UIEdgeInsetsZero); }
手工圈
Snip20160718_17.png
这里由于我在本地保存了移动后的数据,用到了 FMDB
+ (void)initialize { // 1.获得数据库文件的路径 NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *filename = [doc stringByAppendingPathComponent:@"handMore.sqlite"]; // 2.得到数据库 _db = [FMDatabase databaseWithPath:filename]; NSLog(@"%@",filename); // 3.打开数据库 if ([_db open]) { // 4.创表 BOOL result = [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_more (id integer PRIMARY KEY AUTOINCREMENT, moreName blob NOT NULL,moreStr blob NOT NULL,Remark text NOT NULL)"]; BOOL zero = [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_zero (id integer PRIMARY KEY AUTOINCREMENT, moreName blob NOT NULL,moreStr blob NOT NULL,Remark text NOT NULL)"]; if (result && zero) { NSLog(@"成功创表"); } else { NSLog(@"创表失败"); } } } + (void)saveItemArray:(NSMutableArray *)itemArray remark:(NSString *)remark type:(NSMutableArray *)strArray { NSData *nameData = [NSKeyedArchiver archivedDataWithRootObject:itemArray]; NSData *strData = [NSKeyedArchiver archivedDataWithRootObject:strArray]; [_db executeUpdateWithFormat:@"INSERT INTO t_more (moreName,moreStr,Remark) VALUES (%@, %@,%@)",nameData,strData,remark]; } + (void)saveZeroArray:(NSMutableArray *)itemArray remark:(NSString *)remark type:(NSMutableArray *)strArray { NSData *nameData = [NSKeyedArchiver archivedDataWithRootObject:itemArray]; NSData *strData = [NSKeyedArchiver archivedDataWithRootObject:strArray]; [_db executeUpdateWithFormat:@"INSERT INTO t_zero (moreName,moreStr,Remark) VALUES (%@, %@,%@)",nameData,strData,remark]; } + (BOOL)updateItemArray:(NSArray *)moreNameArray strArray:(NSArray *)moreStrArray remark:(NSString *)remark { NSData *nameData = [NSKeyedArchiver archivedDataWithRootObject:moreNameArray]; NSData *strData = [NSKeyedArchiver archivedDataWithRootObject:moreStrArray]; BOOL isSuccess = [_db executeUpdateWithFormat:@"UPDATE t_more SET moreName = %@,moreStr = %@ WHERE Remark = %@", nameData,strData,remark]; if (isSuccess) { NSLog(@"更新成功"); }else{ NSLog(@"更新失败%@",_db.lastErrorMessage); } return isSuccess; } + (BOOL)updateZeroArray:(NSArray *)moreNameArray strArray:(NSArray *)moreStrArray remark:(NSString *)remark { NSData *nameData = [NSKeyedArchiver archivedDataWithRootObject:moreNameArray]; NSData *strData = [NSKeyedArchiver archivedDataWithRootObject:moreStrArray]; BOOL isSuccess = [_db executeUpdateWithFormat:@"UPDATE t_zero SET moreName = %@,moreStr = %@ WHERE Remark = %@", nameData,strData,remark]; if (isSuccess) { NSLog(@"更新成功"); }else{ NSLog(@"更新失败%@",_db.lastErrorMessage); } return isSuccess; } + (NSMutableArray *)list:(NSString *)name { NSString *sql = [NSString stringWithFormat:@"SELECT * FROM t_more"]; FMResultSet *set = [_db executeQuery:sql]; NSMutableArray *list = [NSMutableArray array]; while (set.next) { NSData *item = [set objectForColumnName:name]; list = [NSKeyedUnarchiver unarchiveObjectWithData:item]; } return list; } + (NSMutableArray *)zeroList:(NSString *)name { NSString *sql = [NSString stringWithFormat:@"SELECT * FROM t_zero"]; FMResultSet *set = [_db executeQuery:sql]; NSMutableArray *list = [NSMutableArray array]; while (set.next) { NSData *item = [set objectForColumnName:name]; list = [NSKeyedUnarchiver unarchiveObjectWithData:item]; } return list; }
市集
这个界面比较简单,就是 UICollectionView 的简单使用C
- (void)loadNewData { GPFariParmer *parmers = [[GPFariParmer alloc]init]; parmers.c = @"Shiji"; parmers.vid = @"18"; parmers.a = self.product; __weak typeof(self) weakSelf = self; [GPFariNetwork fariDataWithParms:parmers success:^(GPFariData *fariData) { weakSelf.hotArray = [NSMutableArray arrayWithArray:fariData.hot]; weakSelf.bestArray = [NSMutableArray arrayWithArray:fariData.best]; weakSelf.topicBestArray = [NSMutableArray arrayWithArray:fariData.topicBest]; weakSelf.topicArray = [NSMutableArray arrayWithArray:fariData.topic]; GPFariTopicData *topicData = weakSelf.topicArray.lastObject; weakSelf.lastId = topicData.last_id; [weakSelf.collectionView reloadData]; [weakSelf.collectionView.mj_header endRefreshing]; } failuer:^(NSError *error) { [weakSelf.collectionView.mj_header endRefreshing]; [SVProgressHUD showErrorWithStatus:@"啦啦啦,失败了"]; }]; } - (void)loadMoreData { GPFariParmer *parmers = [[GPFariParmer alloc]init]; parmers.c = @"Shiji"; parmers.vid = @"18"; parmers.last_id = self.lastId; parmers.a = @"topicList"; parmers.page = self.page; __weak typeof(self) weakSelf = self; [GPFariNetwork fariMoreDataWithParms:parmers success:^(NSArray *topicDataS) { [weakSelf.topicArray addObjectsFromArray:topicDataS]; [weakSelf.collectionView reloadData]; [weakSelf.collectionView.mj_footer endRefreshing]; } failuer:^(NSError *error) { [weakSelf.collectionView.mj_footer endRefreshing]; }]; } #pragma mark - UICollectionView 数据源 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return SectionCouton; }
我的
Snip20160718_18.png
这个界面在任何 app 都比较常见,所以没有用到静态单元格,而是用纯代码封装了一个控制器,即使在其他项目中依然可以快速搭建出类似的界面
- (NSMutableArray *)groups { if (_groups == nil) { _groups = [NSMutableArray array]; } return _groups; } - (instancetype)init { return [self initWithStyle:UITableViewStyleGrouped]; } // 返回有多少组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return self.groups.count; } // 返回每一组有多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 获取当前的组模型 GPSettingGroup *group = self.groups[section]; return group.items.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell GPSettingCell *cell = [GPSettingCell cellWithTableView:tableView style:UITableViewCellStyleValue1]; // 获取对应的组模型 GPSettingGroup *group = self.groups[indexPath.section]; // 获取对应的行模型 GPSettingItem *item = group.items[indexPath.row]; // 2.给cell传递模型 cell.item = item; return cell; } // 返回每一组的头部标题 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { // 获取组模型 GPSettingGroup *group = self.groups[section]; return group.header; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { // 获取组模型 GPSettingGroup *group = self.groups[section]; return group.footer; } // 选中cell的时候调用 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // 取出对应的组模型 GPSettingGroup *group = self.groups[indexPath.section]; // 取出对应的行模型 GPSettingItem *item = group.items[indexPath.row]; if (item.operation) { item.operation(indexPath); return; } // 判断下是否需要跳转 if ([item isKindOfClass:[GPSettingArrowItem class]]) { // 箭头类型,才需要跳转 GPSettingArrowItem *arrowItem = (GPSettingArrowItem *)item; if (arrowItem.destVcClass == nil) return; // 创建跳转控制器 UIViewController *vc = [[arrowItem.destVcClass alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } }
M
#import <Foundation/Foundation.h> @interface GPSettingGroup : NSObject /** 组头 */ @property (nonatomic, copy) NSString *header; /** 组尾 */ @property (nonatomic, copy) NSString *footer; /** * 行模型 */ @property (nonatomic, strong) NSMutableArray *items; @end
V
@implementation GPSettingCell + (instancetype)cellWithTableView:(UITableView *)tableView style:(UITableViewCellStyle)cellStyle { static NSString *ID = @"cell"; GPSettingCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[self alloc] initWithStyle:cellStyle reuseIdentifier:ID]; } return cell; } - (void)setItem:(GPSettingItem *)item { _item = item; [self setUpData]; [self setUpAccessoryView]; } // 设置数据 - (void)setUpData { self.textLabel.text = _item.title; self.detailTextLabel.text = _item.subtitle; } // 设置右边的辅助视图 - (void)setUpAccessoryView { if ([_item isKindOfClass:[GPSettingArrowItem class]]) { // 箭头 self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; }else{ self.accessoryView = nil; self.accessoryType = UITableViewCellAccessoryNone; } }
最后说两句
由于代码量较大,所以还是上源码吧,源码地址文/我是小菜鸟(简书作者)
原文链接:http://www.jianshu.com/p/1bd6524270bf
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
相关文章推荐
- iOS常用公共方法
- ios学习资料
- 关于iOS常用的26中公共方法,可copy的代码
- iOS开发经验相关知识
- iOS开发 UITableView 常用细节
- iOS开发之控件带箭头的弹出窗
- iOS 面试题~愿所有移动开发者熬过寒冬
- 来来来!关于iOS基础面试咱俩好好唠唠
- iOS中字迹动画效果
- 用C语言制作Web服务器
- iOS开发插件推荐(1):利用神插件injectionforxcode倍增你的开发效率
- iOS应用支持IPV6,就那点事儿
- iOS Cell嵌套UIWebView(内附UIWebView详解)
- YYWebImage工作原理介绍-----下载单张图片
- iOS常用方法整理超全
- 优化iOS程序性能的25个方法
- iOS应用瘦身方法思路整理
- Objective-C Runtime
- 深入理解 Objective-C Runtime
- 最新C# Object与json互转