简介

仿 iOS 微信客户端,基于Objective-C语言及 MVC 框架实现。 此为本人第二个iOS项目,第一个项目:知乎日报

Github: Seanwong933/WeChat

实现功能


  1. 聊天(接入图灵机器人API,并用CoreData存储聊天记录)
  2. 通讯录(排序、模糊查询、拼音查询)
  3. 发现(朋友圈)

项目演示


部分技术说明


1. 布局(AutoLayout)

聊天界面用的布局库为Masonry+FDTemplateLayoutCell 后在开发朋友圈时,发现算高插件高度似乎计算有误差,换用SDAutoLayout进行布局

2. 自动回复

接入图灵机器人API实现自动回复,仅支持文字回复。

3. 聊天记录存储(CoreData)

聊天记录通过CoreData进行存储,中间使用IQDatabaseManager帮助类方便操作,并使用NSPredicate进行筛选。

4. 刷新

上下拉刷新均使用MJRefresh

5. 朋友圈菊花

通过扩展MJRefresh插件实现(事实证明完全没有必要),下拉旋转通过CGAffineTransform实现,刷新时的转动通过CABasicAnimation实现

经验总结(技巧、坑)


AutoLayout

1. 在做聊天界面时,自动布局使用Masonry+FDTemplateLayout,约束会莫名其妙地报错。

具体体现在如果不将cell底部约束优先级调低,那么约束就会报错,但是界面看上去又不会崩。

2、 做朋友圈时,由于需要布局的界面比聊天的界面多很多,彻底做不下去了。

期间不断地调整包括优先级,ContentHugging一类的东西,统统无效,相当于拆东墙补西墙的效果,高度怎么都不对。 于是换用了SDAutoLayout,一气呵成两小时就做完了,逻辑也是正常逻辑,完全不需要调整其他东西,这时候才明白可能是插件的问题,改日需要研究一下这几个第三方库的代码才行。

后来算了一下,折腾约束至少延长了项目一半的时间,实乃天坑。

TableView

1. 有时需要在为Cell绑定数据时更新约束,于是写下这两行代码:

[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];

实测时发现有时不会运行,所以我们只好手动调用了...

2. cell高度缓存

大家都知道heightForRowAtIndexPath的基本做法是通过维护一个临时列来获取其高度的,这部分开销本身就很大,导致显示一个单元可能会导致多次高度计算,所以我们必须要将高度缓存下来,在你需要重新计算该列的高度时重置该值即可。

- (CGFloat)tableView:(UITableView*)tableView
  heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
    Moment* model = self.momentsArray[indexPath.row];
    if (!model.height) {
        model.height = [self.tableView cellHeightForIndexPath:indexPath model:model keyPath:@"model" cellClass:[MomentTableViewCell class] contentViewWidth:[self cellContentViewWith]];
    }
    return model.height;
}

3. 不要通过[tableView insertRowsAtIndexPaths]方法更新表格数据

该方法是用来动画插入临时列的,如果用来插入数据源列的话会非常卡,而且会导致tableView的contentOffset失控。

4. TableView及CollectionView的高度自适应

可以参考我的这篇文章

5. tableViewHeader无视约束高度

可以参考我的另一篇文章

内存释放

当pop时记得通过viewDidDisappear释放控制器中的内存。

- (void)viewDidDisappear:(BOOL)animated
{
    self.datasource = nil;
    self.momentsArray = nil;

    [self.tableView removeFromSuperview];
    self.tableView = nil;

    NSLog(@"moments disappear");
}