//前言:仿weixin实现一个即时通讯的案例,支持版本7.0以上

"准备工作 创建项目时使用git"
/*
显示隐藏文件,看到git的文件夹
defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder
defaults write com.apple.finder AppleShowAllFiles No && killall Finder 设置git的(全局)用户与邮箱
git config --global user.name Fung
git config --global user.email fung@qq.com
*/ /**
掌握的知识点
1.配置应用程序的iPad与iPhone的各个设备的AppIcon 2.配置应用程序的iPad与iPhone的各个设备的启动图片(LaunchImage)
*/ 一、设置AppIcon与LaunchImage
> 设置iPhone-iOS8./iOS7. iPad-iOS7.0的AppIcon
> 设置LaunchImage时,
a> Xcode6在TARGETS中去除Launch Sreen File里的值
b> 在Lauch Images Source中添加在assests中的启动图片
c> iPhone横屏与iPad横屏的启动图片不设置
d> iPad1024x768图片不设置
"因为微信资源包没有找到对应尺寸的图片,说明有些启动图片可以不用设置"
"微信iPad运行,如果是横屏启动时,是没有显示图片的" 二、实现登录排版
> 创建一个Login.storyboard,使用导航控制器包装登录控制器
> 自定义导航控制器,设置导航条背景与状态栏样式
> 添加登录框容器,使用AutoLayout,固定大小,顶点间距,水平居中
> 使用Images.xcassets对登录按钮的背景图片进行slicing(切片操作)
> 设置密码的文本输入框样式
*设置borderStyle = UITextBorderStyleNone;"storyboard设置,提醒为什么不能设置高度"
*设置textFiled的高度42 *设置backgroudImage为拉伸后的图片"代码实现,因为背景图片放在xcassets时,xcode会崩溃" *设置密码文件框左边的图片
设置图片控制的尺寸、图片内容模式
设置文本框的leftViewMode为总是显示(UITextFieldViewModeAlways)"否则不显示左边的view" > 对控制器view进行拖拽手势监听实现上,实现登录输入框的上下滑动及反弹 "注:提交git版-微信目录结构分层+登录界面排版" 三、注册界面排版
> 添加一个注册框容器,设置顶部,左边,右边距离固定,高度固定
> 添加手机与密码文本输入框、注册按钮,并设置背影图片,文字居中显示
> 设置按钮的可用状态
"注"
> 判断当前设置是否为iphone,如果为iphone,注册框容器的左右两边间距为10
//[UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
> 设置导航条Item的样式-白色字体 四、实现其它登录排版
>在登录界面的底部添加 "其它方式登录>"按钮
> 将"注册界面"的视图拷贝到新的控制器
> 去除横屏,这样在ipad上可以旋转,iphone上不可以 五、完成主界面排版[MainStoryboard]
> 微信、通讯录、发现、我[拖四个导航控制器到Tabbar控制器]
> 设置tabbarBtn的背景及文字,及导航栏的背景
微信 tabbar_mainframe/tabbar_mainframeHL
通讯录 tabbar_contacts/tabbar_contactsHL
发现 tabbar_discover/tabbar_discoverHL
我 tabbar_me/tabbar_meHL
"注:选设置普通状态的图片与文件,有时间再自定义tabbar"
> 设置全局的状态栏样式
*在info.plist中添加View controller-based status bar appearance=NO
*在自定导航控制器是设置[UIApplication shareApplication].statusBarStyle = UIStatusBarStyleLightContent
*设置导航栏标题 字体为粗体18/颜色为白色,
iOS7或者iOS以上使用NSFontAttributeName/NSForegroundColorAttributeName属性
iOS7以下UITextAttributeFont/UITextAttributeColor
//前言:仿weixin实现一个即时通讯的案例,支持版本7.0以上
/*
日志 git log
恢复指定版本 git reset --hard 版本号
查看指令使用记录 git reflog
*/ "未完成"
/*
* 前题:备置mysql密码时参照 "资源/MySql命令行/设置mysql的root密码"
*/
六、使用xmpp框架实现登录功能
> 导入框架
a> 导入CocoaLumberjack 日志框架 "无须依赖"
b> 导入CocoaAsyncSocket 底层网络框架,实现异步socket网络通讯
"依赖:CFNetwork&Security框架"
c> 导入KisssXML XML解析框架
依赖libxml2.dylib
"还需要配置编译选项""
"Other Linker Flags = -lxml2"
"Header Search Path = /usr/include/libxml2"
e> libidn 直接导入
f> 导入下面四个文件夹
Authentication
Categories
Core
Utilities
"依赖libresolv.dylib"
g> 添加Extensions
h> 将Sample_XMPPFramework.h导入,并将其改名为XMPPFramework.h
"注在xcode6中系统有的Framework可以不用添加,但是dylib一定要添加" > 实现登录
*> 选分析登录的步骤
*> 初始化xmppStream核心类,并添加代理为全局队列dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, )
*> 连接服务器时,设置主机,端口与登录账号[先写死代码]
*> 在"代理中连接成功"时发送密码[先写死代码]
*> 在"代理中授权成功"时, 打印
*> 在"代理中授权失败"时, 打印
*> 在"代理中授权成功"时,通知用户上线
*> 官方把登录数据放在沙盒里 "我们放在单例对象"
*> 登录成功用block的方式通知 "其它方式登录控制器"
*> 在其它方式登录控制器中,用MBProgessHUB 显示进度,"在IPad中显示一定要用toView的显示方法,因为窗口没有横竖屏的概念,只有控制器的view才有横竖屏的概念"
*> 隐藏HUB时,引出block是在子线程调用的,不能直接刷新UI
*> 接收block的成功登录时,切换到主界面,"在切换到主界面前,要清除当前模态窗口" 强调自己写的block引用控制器时,要用__weak 七、使用xmpp框架实现注册功能
*> 先分析注册的步骤,与登录形成一个对比
*> 在AppDelegate中添加用户注册的方法
*> 在AppDelegate中添加一个userRegister的属性
*> "连接服务器,连接成功后判断userRegister在代理中做登录还是注册的操作"
*> 在代理中监听注册成功还是失败,再以block的方式通知"注册控制器"
*> "注册控制器" 再以 "代理的方式" 通知 "登录控制器",并设置label的注册后的帐号
*> 抽取 "其它登录控制器" 登录的代码 到一个父类,实现登录 八、细节
> 用户注销[断开连接,回到登录界面]
*> 通知用户下线、断开连接、显示登录界面 > 用户登录过,未注销,不管是程序在后台还是重新启动,直接来到主界面
> 用户登录过,未注销,退出台后时与服务器断开连接,获取焦点时获取自动
"在UserInfo单例中添加一个login属性来记录登录状态"
> 登录界面设置上次登录的帐号 九、自动登录提示
> 分析自动登录监听中的情况
/*
1.开始连接服务器
2.连接失败
3.登录成功
4.登录失败
*/ > 在历史控制器中添加通知监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(autoLoginStatus:) name:WXAutoLoginStatusNotification object:nil];
> 在APPDelegate中发送通知 > "自动登录时延迟两秒登录,好演示效果,连接的主机用域名比较慢" > 转圈圈指示器是否转还是停止,应该放在主线程中 十、socket后台支持
/*
* 注 iOS8不用写支持也可以后台支持
* iOS7 和 iOS8 下都要演示
*/
> "Required background modes"的key,值设置为voip,来指定类型
> xmppStream.enableBackgroundingOnSocket = YES
> xmpp代理接收到消息时,如果不在前台实现本地通知
[UIApplication sharedApplication] applicationState] != UIApplicationStateActive
设置本地通知的内容(用户名\n内容前多少个字) 声音(default) > 在iOS8要注册通知类型registerUserNotificationSettings
//模块

一、自动连接模块
> 当用户网络不稳定时,如果断线,自动连接
> 打开自动连接模块在xmppframework.h文件中打开XMPPReconncet
> 在设置xmppStream时,开始自动连接并"激活"
> "引用官方示例程序的teardown方法" 释放资源 二、电子名片模块与头像模块
> "查看电子名片的模型文件,数据结构"
> 什么是电子名片模块/头像模块
> 在xmppframework.h中打开电子名片模块/头像模块的头文件
> 在设置xmppStream中,设置电子名片模块/头像模块并激活,
"获取用户的个人信息,里面是不是有头像,也一并获取"
> 在teardownxmppStream做相应的资源释放
> 在 "Me"中打印 doc,不要使用SimPhodlers
> 在document看CoreData生成的数据库,用SQLiteManager查看
> 在"我" 中添加静态单元格,显示图片与账号
/*
》XMPPvCardTemp *myvCard = xmppDelegate.vCardModule.myvCardTemp;
》warning 看PPT,查看有些数据是没有解析的
》取消头像,显示日志,使用XMLJSON格式化工具格式化,解释电子名片的电话未解析
*/ 三、电子名片详细页面进行设置
> 进入详细页面进行静态表格的排版
> 绑定数据
> 如果识别不同类型cell的点击,设置每个cell的tag不同
> 点击cell,取消选择中、进行头相选择
> "编辑信息界面,传一个cell到编辑控制控制器,在调用代理时时调用
[self.profileCell layoutSubviews];//重新刷新cell就会显示detailTextLabel,因为没文件,默认是不会创建label"
> 保存数据 四、获取好友列表(花名册)
> "查看花名册的模型文件,数据结构"
> 在xmppframework中打开花名册模块
> setupXmppStream中添加花名册模块
> teardown中释放花名删模块
> 在联系人控制串获取好友列表
/**
* 获取好友列表时,一定要添加过滤条件?,因为多人登录,可能用同一个数据库?
* 答案不会,演示数据,每次登录会清除以前的好友,做得不够好,实际开发自己创建数据库来管理
*/
> "使用CoreData的普通方式获取好友列表"
> 使用NSFetchedResultsController 获取好友列表
> "在cell中演示sectionNum的在线状态,然后在排序中多添加个sectionNum的升序",从而演示出NSFetchedResultsController的作用 > 获取头像 自定联系人Cell
if (friend.photo) {
cell.imageView.image = friend.photo;
}else{
NSData *data = [xmppDelegate.vCardAvatarModule photoDataForJID:friend.jid];
if (data) {
cell.imageView.image = [UIImage imageWithData:data];
}else{
cell.imageView.image = [UIImage imageNamed:@"login_defaultAvatar"];
}
} 五、添加好友+删除好友
> TextField左边的图片放在分类里
> 是否添加为手机号友
/**注:写在分类UITextField里
NSString *telRegex = @"^1[3578]\\d{9}$";
NSPredicate *prediate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", telRegex];
return [prediate evaluateWithObject:self.text];
*/ > 不能添加自己为好友
> 添加的好友已经存在
[xmppDelegate.rosterStorage userExistsWithJID:friendJid xmppStream:xmppDelegate.xmppStream]
[xmppDelegate.roster subscribePresenceToUser:friendJid]; > 删除好友
[xmppDelegate.roster removeUser:friend.jid] 六、聊天界面排版
> 使用VFL排行聊天表格与输入框
tableViewHConst "H:|-0-[tableView]-0-|"
inputViewHConst "H:|-0-[inputView]-0-|"
vConst "V:|-0-[tableView]-0-[inputView(50)]-0-|" > 键盘监听,判断iphone还是ipad 再判断ipad的是横屏还是竖屏
UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
#define iSiPhoneDevice ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
"重点"
> 返回按钮监听
*> 设置textfiel的代理 实现textViewDidChange
*> 判断是否有换行符 "\n"
*> 有就去除掉首尾的空白字符和换行字符
[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; // 七、获取聊天消息+发送聊天消息
"聊天消息模块:什么是聊天消息模块,xmpp帮我们做数据存储 查看0135模块的数据结构"
> xmppframework.h中打开消息归档模块与消息数据存储
> 在setupXmppStream中消息归档模块与消息数据存储
> 在teardown中释放消息归档模块与消息数据存储
> 在通讯录控制器传递好友jid到聊天控制器
> 从数据库加载聊天数据,一次性加载全部"使用NSFecthResultsController"
"强调:查询时要带条件,一定要属于当前登录用户与好友的聊天记录"
> 发送消息
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
[message addBody:msg];
[xmppDelegate.xmppStream sendElement:message]; > 聊天数据滚动到底部
> 讲解怎么判断自己发送的消息还是别人发的消息 八、实现输入框随文字的伸缩 九、实现图片的发送级语音发送的原理
#pragma mark 发送图片
-(void)sendImage:(UIImage *)image{
XMPPMessage *msg = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
NSData *data = UIImagePNGRepresentation(image);
[msg addBody:@"image"];
XMPPElement *attachment = [XMPPElement elementWithName:@"attachment" stringValue:[data base64EncodedStringWithOptions:]];
[msg addChild:attachment]; [[WXXMPPTools sharedWXXMPPTools].xmppStream sendElement:msg];
} #parm mark cell显示
XMPPMessage *xmppMsg = msg.message;
chatCell.imageView.image = nil;
if ([msg.body isEqual:@"image"]) {
NSArray *child = xmppMsg.children;
for (XMPPElement *node in child) {
if([[node name] isEqualToString:@"attachment"]){
NSString *base64 = [node stringValue];
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64 options:];
chatCell.imageView.image = [UIImage imageWithData:imageData];
} } } 第二种
[message addAttributeWithName:@"bodyType" stringValue:@"image"];
[xmppMsg attributeStringValueForName:@"bodyType"] 邮箱解析
NSArray *emailEles = [self elementsForName:@"EMAIL"];
if (emailEles.count != ) {
NSXMLElement *email = emailEles[];
NSXMLElement *userID = [email elementForName:@"USERID"];
return @[[userID stringValue]];
} NSArray *emailEles = [self elementsForName:@"EMAIL"];
if (emailEles.count != && emails.count!=) {
NSXMLElement *email = emailEles[];
NSXMLElement *userID = [NSXMLElement elementWithName:@"USERID" stringValue:emails[] ];
[email removeElementForName:@"USERID"];
[email addChild:userID];
}

IOS XMPP总结的更多相关文章

  1. iOS XMPP 通信协议实现 图形化直观感受

    第一次随笔,实在不知写点什么有用的东西,那就分享一下本人最近的研究所得吧! 是关于iOS-XMPP-通信协议的实现,具体代码比较复杂,三言两句也实在难表达清楚,网上已有很多关于iOS XMPP协议的讲 ...

  2. ios xmpp开发应用后台模式接收聊天信息处理方案

    ios xmpp开发应用后台模式接收聊天信息 最近在使用xmppframwork来实现一个聊天应用,碰到了一个问题,应用进入后台以后,就接收不到消息了: 怎么样才能使应用被切到后台时,应用中的网络连接 ...

  3. iOS xmpp协议实现聊天之openfire的服务端配置(一)

    今天弄这个openfire服务端的配置直接苦了一逼,只是好在最后最终配置好了.首先感谢@月光的尽头的博客给了我莫大的帮助. 切入正题,首先说一下iOS xmpp协议实现聊天openfireserver ...

  4. ios xmpp 发送语音图片解决方案

    ios xmpp 发送语音,图片解决方案,有需要的朋友可以参考下. 目前做IM多是用的xmpp. 因为项目需求需要实现语音和图片的发送. 发送语音图片有三种方法. 1,xmpp smack.文件传输方 ...

  5. iOS XMPP Framework 中文概述

    本篇文章翻译XMPP Framework中的Overview of the XMPP Framework部分 介绍 The framework is divided into 2 parts: 1. ...

  6. iOS - XMPP 的使用

    1.XMPP XMPP 是一个基于 Socket 通信的即时通讯的协议,它规范了即时通信在网络上数据的传输格式,比如登录,获取好友列表等等的格式.XMPP 在网络传输的数据是 XML 格式. 开发架构 ...

  7. iOS - XMPP Openfire 服务器的搭建

    前言 提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提前准备好的软件: jdk-8u91-macosx-x64.dmg mysql-5.7 ...

  8. 【iOS XMPP】使用XMPPFramewok(五):好友列表

    转自:http://www.cnblogs.com/dyingbleed/archive/2013/05/17/3082226.html 好友列表 好友列表,在 XMPP 中被称为 roster,花名 ...

  9. 【iOS XMPP】使用XMPPFramewok(四):收发消息

    转自:http://www.cnblogs.com/dyingbleed/archive/2013/05/16/3075105.html 收发消息 接收消息 通过实现 - (void)xmppStre ...

  10. 【iOS XMPP】使用XMPPFramewok(二):用户登录

    转自:http://www.cnblogs.com/dyingbleed/archive/2013/05/10/3069397.html 用户登录 准备工作 比较知名的开源XMPP服务器:一个是Ope ...

随机推荐

  1. 泛型委托Func<T>

    Func<T>——委托只有泛型版本的,接受参数个数可以是若干个,也可以没有,但是必须是有返回值的方法. Func<TResult>——这个表示没有参数,只有返回值TResult ...

  2. Jsp&Servlet入门级项目全程实录第1讲

    惯例广告一发,对于初学真,真的很有用www.java1234.com,去试试吧! 1.jdbc数据库连接(略) 2.登录表单 2.1设置内边距 <dir style="padding- ...

  3. Docker学习(五): 仓库与数据管理

    特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! =============系列文章============= 1 ...

  4. 使用sql语句备份一张表

    如何使用sql语句复制一张表? 方法一:第一步:先建一张新表,新表的结构与老表相等. create table newtable like oldtable; 第二步:将老表中的值复制到新标中. in ...

  5. K:双栈法求算术表达式的值

    相关介绍:  该算法用于求得一个字符串形式的表达式的结果.例如,计算1+1+(3-1)*3-(21-20)/2所得的表达式的值,该算法利用了两个栈来计算表达式的值,为此,称为双栈法,其实现简单且易于理 ...

  6. RequireJS 是一个JavaScript模块加载器

    RequireJS 是一个JavaScript模块加载器.它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJ ...

  7. 关于StringBuffe()长度和初始化长度的问题归纳

    晚上做一个习题,发现了一个关于StringBuffer()长度的问题 根据理解大致可以归为以下知识. 直接上代码分析吧 public class StringBuffer_length_capacit ...

  8. Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程

    前言 在本系列的上一篇文章中,我们学习了WMS的诞生,WMS被创建后,它的重要的成员有哪些?Window添加过程的WMS部分做了什么呢?这篇文章会给你解答. 1.WMS的重要成员 所谓WMS的重要成员 ...

  9. python item repr doc format slots doc module class 析构 call 描述符

    1.item # __getitem__ __setitem__ __delitem__ obj['属性']操作触发 class Foo: def __getitem__(self, item): r ...

  10. BigInteger方法总结

    BigInteger 可以用来解决数据的溢出问题. 下面我总结几种关于BigInteger的常用用法: 1.probablePrime和nextprobablePrime.(判断质数,并返回) Big ...