项目实战No11 精华模块

一 评论刷新

  • 加载更多评论,加载到最后一页,隐藏拉新控件
  // 判断评论数据是否已经加载完全
  if (self.latestComments.count >= [responseObject[@"total"] intValue]) {
     // 已经完全加载完毕(2种写法)
     [weakSelf.tableView.footer noticeNoMoreData]; // 显示已经全部加载完毕
     weakSelf.tableView.footer.hidden = YES;  //  直接隐藏掉
        } else { // 应该还会有下一页数据
         // 结束刷新(恢复到普通状态,仍旧可以继续刷新)
         [weakSelf.tableView.footer endRefreshing];
        }

  • 视频、声音模块实现
    • 5个模块代码相似度很高,重构代码
  • 重构方法1:继承
    • 传输数据,引用枚举头文件params[@"type"] = @(self.type);
   if ([self isKindOfClass:NSClassFromString(@"XMGAllViewController")]) {
       params[@"type"] = @(XMGTopicTypeAll);
   } else if ([self isKindOfClass:NSClassFromString(@"XMGVideoViewController")]) {
      params[@"type"] = @(XMGTopicTypeVideo);
   } else if ([self isKindOfClass:[XMGVoiceViewController class]]) {
      params[@"type"] = @(XMGTopicTypeVoice);
  }

注意:上述做法,父类过度依赖子类,需要知道子类内容

  • 重构方法2:抽取变量
    • 各子板块不同点就是帖子的类型,每个控制器都有自己的type
/** 帖子的类型 */
@property (nonatomic, assign) XMGTopicType type;

上述方法优点:一个控制器搞定多个小模块,节省代码;
缺点:不利于扩展,不方便给每个子类加一些特性内容
注意点:type可以随意修改,子类代码调用顺序问题(viewDidload)

  • 解决上述注意点

    • 顺序问题
    // 父控制器   params[@"type"] = @(self.type);
    //  只要父类self.type就会调用子控制器的下面方法
    // 子控制器  
    - (XMGTopicType)type
    {
    return XMGTopicTypeWord;
    }
  • 修改type问题

    //  重写get方法,只能访问不能赋值
    - (XMGTopicType)type

    二 新帖评论

- (NSString *)aParam
{
    // [a isKindOfClass:c] 判断a是否为c类型或者c的子类类型
    if ([self.parentViewController isKindOfClass:[XMGNewViewController class]]) {
        return @"newlist";
    }

    return @"list";
}
  • 没有评论数据,服务器返回不是字典,而是nil
  if ([responseObject isKindOfClass:[NSArray class]]) {
       // 意味着没有评论数据
       // 结束刷新
       [weakSelf.tableView.header endRefreshing];      
        // 返回
        return;
    }
  • 评论cell添加分割线
- (void)awakeFromNib
{
    self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mainCellBackground"]];
}

三 UIMenuController

- (void)labelClick
{
    // 获得菜单
    UIMenuController *menu = [UIMenuController sharedMenuController];

    // 菜单最终显示的位置
    CGRect rect = CGRectMake(100, 100, 100, 100);
    [menu setTargetRect:rect inView:self.label];
    /*
     targetRect:menuController指向的矩形框
     targetView:targetRect以targetView的左上角为坐标原点
     */
    // 显示菜单
    [menu setMenuVisible:YES animated:YES];
 }
  • 需要通过第一响应者,来告诉MenuController它内部应该显示什么内容
/**
 * 说明控制器可以成为第一响应者
 */
- (BOOL)canBecomeFirstResponder
{
    return YES;
}
  • 通过这个方法告诉UIMenuController它内部应该显示什么内容
//  返回YES,就代表支持action这个操作
 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
   if (action == @selector(cut:)
        || action == @selector(copy:)
        || action == @selector(paste:)) {
        return YES;
    }  
    return NO;
}
  • 其它控件要想成为第一响应者,需要调这行代码(控制器不需要)
  [self becomeFirstResponder];
  • 菜单最终显示位置,可以指向自己
// 方法1
[menu setTargetRect:self.bounds inView:self];
// 方法2
[menu setTargetRect:self.frame inView:self.superview];
  • 全局粘贴板:UIPasteboard generalPasteboard
- (void)cut:(UIMenuController *)menu
{
    // 将label的文字存储到粘贴板
    [UIPasteboard generalPasteboard].string = self.text;
    // 清空文字
    self.text = nil;
}
  • 拷贝功能
- (void)copy:(UIMenuController *)menu
{
    // 将label的文字存储到粘贴板
    [UIPasteboard generalPasteboard].string = self.text;
}
  • 粘贴功能
- (void)paste:(UIMenuController *)menu
{
    // 将粘贴板的文字赋值给label
    self.text = [UIPasteboard generalPasteboard].string;
}
  • 弹窗文字语言选择
    这里写图片描述

  • cell弹窗实现

- (void)labelClick
{
    // 让label成为第一响应者
    [self becomeFirstResponder];
    // 获得菜单
    UIMenuController *menu = [UIMenuController sharedMenuController];
    // 设置菜单内容
    menu.menuItems = @[
                       [[UIMenuItem alloc] initWithTitle:@"顶" action:@selector(ding:)],
                       [[UIMenuItem alloc] initWithTitle:@"回复" action:@selector(reply:)],
                       [[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(warn:)]
                       ];   
    // 菜单最终显示的位置
    [menu setTargetRect:self.bounds inView:self]; 
    // 显示菜单
    [menu setMenuVisible:YES animated:YES];
}
#pragma mark - UIMenuController相关
/**
 * 让Label具备成为第一响应者的资格
 */
- (BOOL)canBecomeFirstResponder
{
    return YES;
}
/**
 * 通过第一响应者的这个方法告诉UIMenuController可以显示什么内容
 */
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持复制
        || (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切
        || action == @selector(paste:)
        || action == @selector(ding:)
        || action == @selector(reply:)
        || action == @selector(warn:)) return YES;

    return NO;
}

四 评论模块增加UIMenuController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 取出cell
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    UIMenuController *menu = [UIMenuController sharedMenuController];

    // 设置菜单内容
    menu.menuItems = @[
                       [[UIMenuItem alloc] initWithTitle:@"顶" action:@selector(ding:)],
                       [[UIMenuItem alloc] initWithTitle:@"回复" action:@selector(reply:)],
                       [[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(warn:)]
                       ]; 
    // 显示位置
    CGRect rect = CGRectMake(0, cell.height * 0.5, cell.width, 1);
    [menu setTargetRect:rect inView:cell];
    // 显示出来
    [menu setMenuVisible:YES animated:YES];
}
  • 获得当前选中行的评论
- (XMGComment *)selectedComment
{
    // 获得被选中的cell的行号
    NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
    NSInteger row = indexPath.row;

    // 获得评论数据
    NSArray *comments = self.latestComments;
    if (indexPath.section == 0 && self.hotComments.count) {
        comments = self.hotComments;
    }
    return comments[row];
}
  • 键盘文本框不需要弹窗设置
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (!self.isFirstResponder) { // 文本框弹出键盘, 文本框才是第一响应者
        if (action == @selector(ding:)
            || action == @selector(reply:)
            || action == @selector(warn:)) return NO;
    } 
    return [super canPerformAction:action withSender:sender];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值