中山大学数据科学与计算机学院本科生实验报告

(2019年春季学期)

课程名称 IOS开发 任课老师 郑贵锋
年级 16 专业(方向) 软件工程(计算机应用方向)
学号 16340132 姓名 梁颖霖
电话 13680473185 Email dic0k@qq.com
开始日期 2019/5/12 完成日期 2019/5/15

一、实验题目

IM聊天工具

二、实现内容

  • 个人详情页面UI
  • 后端接口:获取聊天消息记录

三、实验结果

聊天消息记录

1.概述

为了实现聊天工具对话的消息传递,这里我们引入了序列号的概念,每一个消息都有它特定的序号,我们根据这个序列号来确定这个消息是否已经发送,是否已经被接受到,是否需要删除等逻辑。

除此之外,为了实现多用户间的对话,例如A->B, A->C, B->C,他们之间如何能找到属于他们各自的信息呢?这里我们利用的是维护一个消息表,每一条消息都有发送用户的id,接受用户的id,内容的id,然后再通过内容的id在内容表格中找具体的内容。

2. URL设计

获取用户之间聊天记录
/history/personal
POST
{to: {username}
data: {}
}

在Django的urls.py文件中表现为

urlpatterns = [path('personal', views.personal, name='personal'),
]

3. 具体实现

a.从消息表通过用户名获取聊天记录
# 返回聊天记录
def personal(request, t_username):response = {'state':'fail', 'msg':'no msg'}# 要在登录状态下if 'login_id' not in request.session:response['msg'] = 'no login'return HttpResponse(json.dumps(response), content_type = 'application/json')# 只允许GET方法if request.method != 'POST':response['msg'] = 'wrong method'return HttpResponse(json.dumps(response), content_type = 'application/json')# 查询的用户名为空if t_username == '':response['msg'] = 'miss username'return HttpResponse(json.dumps(response), content_type = 'application/json')# 已经登录, 所以拿取用户信息cur_username = request.session['login_id']# 数据库操作,查询消息try:# 当前用户发送给对方的信息cur_to_t_msg = Msg.objects.filter(Username = t_username, From = cur_username)# 对方发送给当前用户的信息t_to_cur_msg = Msg.objects.filter(Username = cur_username, From = t_username)except Exception as e:response['msg'] = 'db error'return HttpResponse(json.dumps(response), content_type = 'application/json')else:# 根据两类消息的ContentID来找出所有content# 这里先假设所有记录为文字类型,图片类型未知结果,待测试# Content_Text ctArray = []# Content_Image ciArray = []for msg in cur_to_t_msg:if msg.Type == 'text':ctArray.append(Content_Text.objects.filter(Cid = msg.ContentID))elif msg.Type == 'image':ciArray.append(Content_Image.objects.filter(Cid = msg.ContentID))for msg in t_to_cur_msg:if msg.Type == 'text':ctArray.append(Content_Text.objects.filter(Cid = msg.ContentID))elif msg.Type == 'image':ciArray.append(Content_Image.objects.filter(Cid = msg.ContentID))# 根据ContentID来进行append,保证时间有序if len(Content_Text) >= 1:# 序列化,返回多条文字内容serialized_obj = serializers.serialize('json', ctArray)response = {'state':'ok', 'msg':'ok', "data":serialized_obj}else:response['msg'] = 'no data'return HttpResponse(json.dumps(response), content_type = 'application/json')

具体逻辑

  • 定义返回体的内容,包括一个state和msg
  • 判断是否已经登陆状态
    • 是,直接返回HttpResponse,告诉前端已经登陆,无须注册
    • 否,下一步
  • 判断方法是否为GET
  • 判断查询的用户名是否为空
  • 获取用户登陆的用户名以及密码
  • 数据库操作
    • 通过用户名获取当前用户发送给对方的信息
    • 通过用户名获取对方发送给当前用户的信息
    • 根据两类消息的ContentID来找出所有content
    • 根据ContentID来进行append,保证时间有序
    • 序列化,返回多条文字内容

个人详情页面

效果截图:

个人详情页面是使用UITableView来模仿微信聊天工具的详情所制作的

InfoViewController.h

#import <UIKit/UIKit.h>
#import "UserModel.h"NS_ASSUME_NONNULL_BEGIN@interface InfoViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *Birthplace;
@property (weak, nonatomic) IBOutlet UILabel *NickName;
@property (weak, nonatomic) IBOutlet UILabel *ID;
@property (weak, nonatomic) IBOutlet UILabel *Gender;
@property (strong, nonatomic) UserModel* User;
@property (weak, nonatomic) IBOutlet UIImageView *ProfilePicture;@end

首先在.h文件定义所用到的一些属性,包括用户名,地区,性别,id号,头像等,还有一个登陆后的User的信息。

InfoViewController.m

这里首先定义所用到TableView,以及左侧的标题列表,右侧的内容列表来存储数据

#import "InfoViewController.h"@interface InfoViewController ()<UITableViewDelegate, UITableViewDataSource>@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, strong) NSMutableArray<NSString*> *titleList;
@property(nonatomic, strong) NSMutableArray<NSString*> *contentList;@end

viewDidLoad函数中加载数据

  • 绑定User中的信息到之前定义的属性当中。
  • 定义navigationItem的标题名。
  • 获取屏幕的宽与高来定义tableview视图的大小与位置
  • 取消tableview默认的多余的横线
- (void)viewDidLoad {[super viewDidLoad];// [self.navigationController setNavigationBarHidden:NO animated:NO];self.navigationController.navigationBarHidden = NO;// Do any additional setup after loading the view.if (self.User == nil){self.User = [[UserModel alloc] initWithProperties:@"peppa ID" NickName:@"Peppa" RemarkName:@"peppy" Gender:@"female" Birthplace:@"UK" ProfilePicture:@"peppa.jpg"];}self.ProfilePicture.image = [UIImage imageNamed:self.User.ProfilePicture];self.NickName.text = self.User.NickName;self.ID.text = self.User.UserID;self.Gender.text = self.User.Gender;self.Birthplace.text = self.User.Birthplace;self.navigationItem.title = @"个人信息";// 获取屏幕的宽高CGRect rect = [[UIScreen mainScreen] bounds];CGSize size = rect.size;CGFloat width = size.width;CGFloat height = size.height;self.tableView = ({UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, width, height/2+70) style:UITableViewStylePlain];tableView.delegate = self;tableView.dataSource = self;tableView;});// 取消多余的横线self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];[self.view addSubview:self.tableView];[self loadData];
}

加载数据,定义titleList,contentList

- (void)loadData {self.titleList = [NSMutableArray array];self.contentList = [NSMutableArray array];[self.titleList addObjectsFromArray:[[NSArray alloc] initWithObjects:@"头像", @"昵称", @"账号", @"性别", @"地区",nil]];[self.contentList addObjectsFromArray:[[NSArray alloc] initWithObjects:@"小猪佩奇", @"Peppa", @"peppy", @"female", @"UK",nil]];
}
  • 用numberOfSectionsInTableView定义tableview的section数目
  • 用heightForRowAtIndexPath定义tableview每一个cell的高度
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return 1;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.titleList.count;
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {return 80;
}

根据不同的行来给每个cell自定义accessoryView, 并绑定不同的数据。这里我们第一行是图片,故需要特殊处理来显示图片,而其他行则是显示内容,我这里修改一下它的字体与大小使得更加美观,对比度更加高。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {NSString *cellID = [NSString stringWithFormat:@"cellID:%zd", indexPath.section];UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];if (nil == cell) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}// cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;cell.textLabel.text = self.titleList[indexPath.row];cell.textLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:18.f];if (indexPath.row != 0){UILabel *rightLabel = [[UILabel alloc]initWithFrame:CGRectMake(0,0,70,55)];rightLabel.text = self.contentList[indexPath.row];rightLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:14.f];rightLabel.textColor = [UIColor grayColor];cell.accessoryView = rightLabel;//cell.accessoryView.backgroundColor = [UIColor redColor];   //加上红色容易看清楚}else{cell.accessoryView = ({UIImageView *imgV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.User.ProfilePicture]];CGRect frame = imgV.frame;frame = CGRectMake(0, 0, 100, 55);imgV.frame = frame;[imgV setContentMode:UIViewContentModeScaleAspectFit];imgV;});}return cell;
}

点击列表的item时跳转至修改页面

#pragma mark ------------ UITableViewDelegate ------------------- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {[tableView deselectRowAtIndexPath:indexPath animated:YES];InfoViewController *controller = [[InfoViewController alloc] init];controller.hidesBottomBarWhenPushed = YES;[self.navigationController pushViewController:controller animated:YES];
}

用户退出按钮绑定事件,这里要与服务器进行交互,删除之前登陆的session

- (IBAction)logout:(id)sender {NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:nil delegateQueue:[NSOperationQueue mainQueue]];NSURL *url = [NSURL URLWithString:@"http://118.89.65.154:8000/account/logout/"];NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if(error == nil) {if(NSClassFromString(@"NSJSONSerialization")) {NSError *e = nil;id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&e];if(e) {NSLog(@"error");}if([object isKindOfClass:[NSDictionary class]]) {NSDictionary *result = object;if([result[@"state"] isEqualToString:@"ok"]) {NSLog(@"logout success");UIStoryboard *indexStoryboard = [UIStoryboard storyboardWithName:@"Index" bundle:nil];[UIApplication sharedApplication].keyWindow.rootViewController = indexStoryboard.instantiateInitialViewController;}else {NSLog(@"logout fail");}}else {NSLog(@"Not dictionary");}}}else {NSLog(@"网络异常");}}];[task resume];
}

IOS开发笔记(九)——IM聊天工具个人详情页面,自定义tableview的accessaryView相关推荐

  1. IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法...

    IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法 Author:hmjiangqq Email:jiangqqlmj@163.com ...

  2. iOS开发笔记-两种单例模式的写法

    iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h"st ...

  3. [置顶] XMPPFrameWork IOS 开发(六)聊天室

    原始地址:XMPPFrameWork IOS 开发(六)聊天室 聊天室 [cpp]  view plain copy print ? //初始化聊天室 XMPPJID *roomJID = [XMPP ...

  4. IOS开发笔记之推广安装(用网页判断是否安装App)

    IOS开发笔记之推广安装(用网页判断是否安装App) 在做App推广的时候,我们经常会用到网页链接下载,亦或是一张二维码,最常见的做法就是将App在iTunes中的下载链接嵌入,当用户扫描或者点击网页 ...

  5. iOS开发笔记之五十九——OS X和iOS安全机制之一——签名机制

    一.背景 在OS X上病毒和恶意软件很少见,给大家的感觉是OS X和iOS更加安全.到底是什么原因导致的OS X更加安全呢? (1)OS X占有率较低,没有吸引足够的恶意软件开发者的注意(假设你是恶意 ...

  6. IOS开发笔记之常用的第三方库(太多了。)

    图像: 1.图片浏览控件MWPhotoBrowser  实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作. ...

  7. iOS开发笔记--iOS应用架构谈 view层的组织和调用方案

    前言 <iOS应用架构谈 开篇>出来之后,很多人来催我赶紧出第二篇.这一篇文章出得相当艰难,因为公司里的破事儿特别多,我自己又有点私事儿,以至于能用来写博客的时间不够充分. 现在好啦,第二 ...

  8. IOS开发笔记之常用库索引

    code4app.com 这网站不错,收集各种 iOS App 开发可以用到的代码示例  cocoacontrols.com/ 英文版本的lib收集  objclibs.com/ 精品lib的收集网站 ...

  9. IOS开发笔记2-C语言基础复习

    转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/53439812 本文出自:[顾林海的博客] 前言 在正式进入ios开发前 ...

最新文章

  1. 赠书 | 图解机器学习算法,看这文就够了!
  2. 用反向传播算法解释大脑学习过程?Hinton 等人新研究登上 Nature 子刊
  3. SQL2K数据库开发十一之表操作创建UNIQUE约束
  4. ansible+powershell DSC 可以管理windows server了
  5. sdut 2134 数据结构实验之栈与队列四:括号匹配
  6. Android 项目中常用到的第三方组件
  7. Markdown会干掉Html吗?
  8. oracle中间键配置,Oracle Exalogic中间件云服务器简介及产品配置特点(2)
  9. python opencv报错_OpenCV in Python 入门问题,python报错 -问答-阿里云开发者社区-阿里云...
  10. arcengine 图层中节点抽稀功能(c++)
  11. GBDT、随机森林、xgboost算法原理解析视频公开
  12. linux查看essbase进程,ESSBASE的使用及优化.doc
  13. 深度学习自学(十七):caffe-sphereface-编译matcaffe遇到的问题
  14. 【渝粤教育】国家开放大学2018年春季 0179-21T数据库基础与应用 参考试题
  15. 开心庄园html的代码,HTML第五章(示例代码)
  16. build/envsetup.sh 简介
  17. SQL server 期末复习
  18. Defending Against Model Stealing Attacks with Adaptive Misinformation
  19. Auto CAD2004完全笔记
  20. php获取QQ音乐直链,~~~获取qq音乐外链方法+源码~~~

热门文章

  1. wps2016向程序发送命令_Excel:向程序发送命令时出现问题
  2. 腾讯优测-优社区干货精选 | android开发在路上:少去踩坑,多走捷径(上)
  3. 分数换算小数补0法_高考志愿填报时“线差法”和“位次法”哪个好?
  4. 罗素问题 ——来自知乎大神
  5. android x86引导修复,Android-x86 9.0-r2 发布,更新内核与UEFI引导修复
  6. 灵活组合复合图元模板,电路图状态图业务定义可配置,浮云E绘图软件源码开发
  7. 过拟合现象,原因,以及降低过拟合的方法
  8. arduino 土壤温湿度传感器_怎样将Arduino与土壤湿度传感器FC-28连接起来
  9. 自动驾驶职位选择和常见术语
  10. (1)英特尔工业边缘洞见平台(EII)安装指南