• iOS 环信 集成 详细步骤图文


    环信的教程:

    没有初始化SDK  

    去AppDelegate里面初始化

    密码

    User not exist         ??????????

    每一个应用都有自己的注册用户  去你的后台管理   去看你的注册的用户数   

    为什么demo的可以跑起来????????

    是在它的应用下注册的

    怎么去注册用户  -注册用户

    用户名字可以相同   不同的应用   

    那个打印的loginInfo 是这个字典的也就是用户的登录信息

    你会发现打印的loginInfo上面还有一坨恶心的东西,那个是环信SDK自己打印的日志信息

    SEND   和      RECV    使用的是XMPP协议    所以 数据的格式是XML   一般的HTTP协议的话他就是JSON格式的

    这个是app把客户端登录的信息发给环信服务器后打印出来的日志      是不是很烦

    如何去在哪儿隐藏它的控制台的日志信息 ?????????

    去初始化的时候把它隐藏  有一个otherConfig的东西   右键-jump to Define

    进去瞅瞅--

    复制它的key 给他设置为NO

    这个时候它的控制台的日志信息就被屏蔽了

    跟环信交互的所有类都有这个

    [EaseMob sharedInstance].chatManager

    注册的时候代码:

    如果你把这onQueue改为nil的话他默认也是在主线程的

    然后你在去环信的开发中心刷新IM用户 你会发现他多了一个

    发送给的数据给服务器的时候还是XML格式,里面的SDK帮你封装了,不用你自己去接触

    ---自动登录------------------------------------

    看到它的主界面只有三个tabbar

     进去 mainstoryboard里面 删除原始的viewcontroller  拖入一个 tabbarController     去掉原始的tabbar 的两个子控制器   记得给它的isinitial 那个选项钩上   然后拖入三个navigationcontroller(这个根据你的界面而定)

    选中给每个的Item  的title属性可以更改

    然后在登录成功中写上加载storyboard的方法

       

    你会发现你已经跳转进去

    如何实现自动登录?????????????????

      实现原理:把你的登录信息保存在沙盒中     程序启动时候发送登录请求

      只要你在第一次登录成功后发送环信自带登录的网络请求去实现、

    环信自己帮你实现上面的东西

    具体实现

    在登录成功的下面写上

    [[EaseMob sharedInstance].chatManager  setIsAutoLoginEnabled:YES]

    然后去在AppDelegte里面把他的沙盒路径拿到

    然后再控制台你可以看到这些信息,其中的账号密码信息你会发现他被加密了,有没有?

    如何监听是否是已经处于登录状态了这个地方有个代理  环信的代理方法

    在AppDelegate方法里面进去 在启动方法里面写

    你会发现它的那个啥没有完成界面的跳转    但是控制台却是带那个登陆成功了

    这个时候我们还缺一步骤  之前我们在自动登录时候我们调用的是set方法

    这个时候我们要实现它的 get方法     写在监听登录状态的下面

      //如果登录过直接来到主界面

        if([[EaseMob sharedInstance].chatManager isAutoLoginEnabled]){

            self.window.rootViewController = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;

        }

        

    =------------自动连接--------------------------

    网络通不通的时候类似微信那种网络不通的实现

    去那个main.storyboard里面把那会话的导航控制器跳转的那个类继承改为你自己创建的那个UItableViewController

    1.在会话里面监听的网络的状态  环信的有很多个代理

    去那个.m文件里面去实现

    点击那个EMChatManagerDelegate 里面去实现 EMChatManagerUtilDelegate里面的这个方法就OK了

    - (void)didConnectionStateChanged:(EMConnectionState)connectionState;

    在真机上面测试的时候 网络连接成功不代表客户端和服务器端连接成功

    还有自动连接的状态的监听 也是加上他的代理方法就行了

    --------添加好友请求-----------------------------

    1.是用环信的思想

     所有的网络请求   [EaseMob sharedInstance].chatManager 由这个管理器发起的

    2.所有结果(自动登录 自动连接)通过代理来回调完成

    [EaseMob sharedInstance].chatManager的addDelegate来完成

    3.EMChatManagerBuddyDelegate 这个代理实现了对用户的基本操作

    1.添加好友      2.从本地获取好友      3.从服务器列表获取最新的好友     4.接受好友添加请求

    5.删除好友       6.被好友从名单上面删除  

    navigation  的第二个控制器上面加上一个UIbarbarItem   选择自定义   然后+    

    再去创建一个UIviewController     然后再去实现用个+号去拖一个线  

     可以在上面加上navigationItem 上改为添加好友

    再去新建一个控制器AdressBooking 通讯录  这个类是继承于UIviewController

    是用环信最简单的方法 ,把官方的Demo直接拿过来用   直接跟改它的Appdelegate里面的APPKey

    屏幕快照 2016-03-25 上午1.13.14.png

    这样你就收到了申请    注意   这是最简单的方式

    还有一点 你要在每个控制器里面写上你环信的代理方法

    这样就能保证你下面写的环信 的每一个方法会被自动调用了

    代理方法:

    代理的销毁

    好友请求消息反馈写在什么地方   因为你进去那个会话的控制器里面了的话就会被销毁了。我们可以把它的好友请求写在会话控制器   这样他每个控制器都可以收到了  也没有必要写在AppDelegate里面 可以去尝试一下

    ---------现实好友界面列表------------------

    1.新建一个tableViewcontroller  修改那个tableView的继承

    2.给他的cell添加一个Identifier     

    下面打印的就是他的好友列表

    #pragma mark - Tableview datasource

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

        return self.buddyList.count;

    }

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

        static NSString *ID = @"BuddyCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

        //获取好友列表名称  EMBuddy是环信封装的好友模型

        EMBuddy *buddy = self.buddyList[indexPath.row];

        //显示头像 和名字

        cell.imageView.image = [UIImage imageNamed:@"chatListCellHead"];

        cell.textLabel.text = buddy.username;

        

        return cell;

    }

    注意一个bug在网速很慢的时候话或者用户的手速很快的情况下(遇到单身30年的手速)用户的时候      你会发现好友列表但是没有值的  因为它的好友列表是在你用户登录策划国内恭候才会有值 

    buddyList是从本地获取的数据  本地有个数据库你可以去里面看看  

    // buddyList 

    如果删除了应用或者饿用户第一次登陆的时候 buddyList是没有数据记录的

    就要从服务区获取好友列表纪录

    在网络登陆之前我们去从服务器获取那个 好友列表并把它写到本地的数据库里面去,注意一下这个方法写在哪个地方 切记切记

    ----------------好友请求同意后的列表刷新----------------------------

    当接收到后有的同意后要刷新好友的列表数据   去通讯录控制器监听

    产生了一个问题?

    我发送了请求   对方接受了   没有刷新好友列表

    环信发送的话一定调用了

    #pragma mark-好友列表的请求被更新,然而并没什么卵用

    -(void)didUpdateBuddyList:(NSArray *)buddyList changedBuddies:(NSArray *)changedBuddies isAdd:(BOOL)isAdd{

    //    NSLog(@"好友列表被更新%@", buddyList);

        NSLog(@"%@",buddyList);

        self.buddyList = buddyList;

        [self.tableView reloadData];

        

    }

    加上这句话就可以解决这个问题

    ============删除好友==========================

    获取移除好友的名字

    还有一种删除了是互相删除还是只是将一方的删除

    #pragma mark--删除好友的代理方法

    -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath {

        if(editingStyle == UITableViewCellEditingStyleDelete) {

            //获取要移除的好友的名字

            EMBuddy *buddy =self.buddyList[indexPath.row];

            NSString *deleteusername  = buddy.username;

            

            //删除好友

            [[EaseMob sharedInstance].chatManager removeBuddy:deleteusername removeFromRemote:YES error:nil];

        }

    }

    ———--------被好友删除的监听-----------------------------

    1.在会话里面:

    //被好友删除

    #pragma mark-监听被好友删除

    -(void)didRemovedByBuddy:(NSString *)username {

        NSString *message = [username stringByAppendingString:@"把你删除"];

        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"好友删除提醒" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

        [alert show];

    }

    在同叙录里面:

    //监听被删除去会话里面

    #pragma mark-被好友删除了刷新一遍列表

    -(void)didRemovedByBuddy:(NSString *)username {

        [self loadDataFromServer];

    }

    --------------退出登录--------------------------

    1. 选中table View 的然后给他选static cell

       2.然后连线去实现它的方法

    -重点-------------聊天界面的实现----------------------------

    1.拖入一个UIviewController 在上面在取拖入一个navagationBar 去设置他的标题

    2.把cell的脱线  show

    3.拖入一个View   拖到最下面    你会发现被tabbar 给盖住了   怎么去隐藏他呢?

       选中他   有个 Bottom Bar  改为None   

    4.给这个View设置约束的时候注意  不要给她设置底部距Bottom  选择View

    layout后  选择 Hidden Bottom Bar

    5.往上面添加button    button也要设置约束  要他举例底部的位子不变    

    否者的话  他会随着聊天的界面文字的的增加   而那个上升

    还要加上一个textfield

    通过代码监听键盘    如果底部

    千万不要把键盘关闭了   不然神仙也救不了你

    具体代码:

    -(void)viewDidLoad {

        [super viewDidLoad];

        //1.监听键盘的弹出,把inputToolbar往上移

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

        

        

        

    }

    #pragma mark-键盘显示的时候会触发方法

    -(void)kbWillShow:(NSNotification *)notification {

     //获取键盘的高度

        //1.获取键盘结束的位子

        CGRect kbEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

        CGFloat kbHeight = kbEndFrame.size.height;

        

        //更改inputToolBar的底部约束

        self.inputToolBarBottonConstraint.constant = kbHeight;

        //添加动画

        [UIView animateWithDuration:0.25 animations:^{

            [self.view layoutIfNeeded];

        }];

    }

    //移除通知

    -(void)dealloc {

        [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

    ///////////////////

    再加上一个tableView在它的上面    如何实现在拖动tableview 的时候让键盘隐藏

    或者去监听tableView滚动的方法  

    tableView 有一个属性 Keyboard  Dismiss on drag

    在键盘推出的时候 让inputToolBarView  恢复原位

    也要监听他

    -----------cell有三种类型的 左边  中间   右边 -------------------------

    1.往那个tableView里面去添加cell的时候我们可以 在里面加上图片

    思路:在你设置好了头像之后再去设置文本的时候怎么设置

    UILabel 设置背景图片的时候 我们可以先去给UILabel设置约束

    再去设置那个背景图片,让他去拉伸

    设置约束的时候注意头像要写死  但是lable只需要设置他的左边和  上面就行

    如何加上测试数据:

    1.自定一一个cell   在给他对用的类    和 对应的cell  绑定一个改类名

    1. 在。h文件里面给label加上一个属性 , 在给他的cell绑定一cell
    2. 最后别忘了在给tableview 右键往那个UIviewController上面加上数据源和代理

    也就是自定义cell

    ------如何去让他显示的换行

    1.吧label的Lines设置为0;

    2.设置她的最大宽度:选择  Preferred width 这个选项242;

    ----最后给他设置那个背景图片

    吧那个UIimage添加到那个Label上面 

    如何给那个这个ImageView 和Label  设置左上角对其?????????????

    选中他们两个,然后把选择设置约束右下角的正向第2个  然后把4个Edge选择对其

    最后别忘了去吧label  设置为clear

    怎么去把ImageView的背景图片拉伸???????

    选择背景图片 第4个属性倒立的脚   有一个strecting属性  设置为0.5   0.5  0  0

    那个时候你会发现它的那个啥的没有那个左边图片的角的属性,什么原因呢?

    这是因为你的这个时候的Y值拉升的不够可以把他的Y方向上面改成 0.7

    这个时候还缺最后一步,要把它的那个背景ImagView改动一下,让它在上下左右 都往外面 

    拉伸一下??????//

    可以选中它的那个约束,更改它的那个Constant    左边和上面的都是 加10     下边和右边是减10

     最后别忘了跟新约束

    -----------发送方的cell排布----------------------

    1. 先拖入一tableViewCell 然后改他的名字    在去拖入一个Imageview  在去实现它的那个

    5  5   35 35 

    2.拖入一个Label   上面15 右边20   宽和高就不要添加了

    3.如何让两个自定义的cell指向同一个的cell  新思想 :两个View公用一个cell

      连线的时候又一个选择   选择senderCell   再给SenderCell一个identifier标示符号

    在渲染cell的方法中加入一个加载哪一个cell的判断

    4.最后设置它的Lines = 0  和 那个Preferred Width的宽度  让它实现自动换行

    5.添加一个ImageView然后再去设置它的背景图片和  那个边距的对其

    6.更改Image的Stretching

    7.最后去把ImageView 的各个边距都改一下 上 10   左 10    下 -10  右边  -15 最后跟新

    8  重点----如何去根据label里面的文字的高度去自动计算那个文字的高度?????

    1.实现它的给他添加了一个测试的数据源方法

    9--重点----还有一个问题  怎么去更改的它的自动计算那个行高呢??????

    cell的高度取决于label文字的高度和它的字体的大小决定的、

    思想: 去获取那个cell里面的label的高度再去加上一个固定的高度就是cell的高度了

    怎么去获取那个label的高度呢???

    上面的额头像距上为5 加上那个上面label距离上面的10的高度 再加上label自己      的高度self.label.hight +下面的那个10,再去加上那个固定的高度就是cell的高度了

    10.--重点----我们专门搞一个计算高度的属性(他是一个返回cell的方法,然后去返回cell高度的方法里面去给他完成一下赋值的操作,最后去实现)

      //还少了一步 ,一定要加上去设置那个label的数据

        self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

        return [self.chatCellTool cellHeight];

    /** 计算高度的cell的属性*/

     @property (nonatomic,strong)UXZYChatCell *chatCellTool;

       //给计算cell高度的对象完成一个赋值

        //他返回的是一个cell 这个cell只是在那个返回高度的方法里面去用到了,其他的地方没有用到

    记得最好把它的方法static NSString *Indentifier = @"ReceiveCell";写在那个cell的.h文件中

    tableview记得再拖一次线  为什么任何一个的Identifier:都可以呢?????

    因为你在返回高度的方法里面都是一样的执行的,不获去细分你是哪一个cell的方法 so。。。

        self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:SenderCell];

    --------------发送聊天消息---------------------

    1.首先要做的是把那个 textView的发送框改成send属性 第四个选项里面的有一个

      Return Key 选项 改成那个Send选项

    2.怎么去发送按钮的事件呢?????

    1.把那个textView 的代理的线连上   2.然后去那个tableView里面的那个去遵守textView代理

    在textView的方法里面去监听他最后的字符有没有换行,如果有换行的字符的话我就代表说他是发送sender的按钮]

    3.怎么去发送文字呢???????

    #pragma mark-UITextView的代理

    -(void)textViewDidChange:(UITextView *)textView {

        if([textView.text hasSuffix:@" "] ) {

            NSLog(@"这是一个发送事件");

            //发送文字

            [self sendMessage:textView.text];

            

            //清空文字

            textView.text = nil;

        

        }

    }

    -(void)sendMessage:(NSString *)text {

        //创建一个消息对象实例

        EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:nil bodies:nil];

        //发送消息

        [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

            NSLog(@"消息准备发送");

        } onQueue:nil completion:^(EMMessage *message, EMError *error) {

            NSLog(@"消息完成发送");

        } onQueue:nil];

        

    }

    还缺少一个参数  就是把消息发送给谁? 我们就缺少一个参数传递

    initWithReceiver:要去拿到那个参数好友列表的参数 EMBuddy 

    #warning 每一种消息类型对象不同的消息体

        //EMTextMessageBody

        //EMVoiceMessageBody

        //EMVideoMessageBody

       // EMLocationMessageBody

       // EMImageMessageBody

        

        //创建一个聊天的文本对象

        EMChatText *chatText = [[EMChatText alloc]initWithText:text];

        //创建一个文本消息体

        EMTextMessageBody *textBody = [[EMTextMessageBody alloc]initWithChatObject:chatText];

        

        //创建一个消息对象实例   bodies是一个数组

        EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

        //发送消息

        

        [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {

            NSLog(@"消息准备发送");

        } onQueue:nil completion:^(EMMessage *message, EMError *error) {

            NSLog(@"消息完成发送");

        } onQueue:nil];

    注意点  : 加上一个return;去测试

    把选中的好友列表正向传递进去

    最后别忘了把那个return打开;

        

    --------------显示好友的名字---------------------

    1.在那个聊天的控制器的viewdidload里面写上

    self.titlte = self.buddy.username

    ——————-------加载本地的聊天数据--------------------

    有封装好的东西,先去内存的会话列表中去获取会话  如果没有找到就去数据库中去获取会话

    没有找到就会出发现的会话

    #pragma mark-加载本地的聊天数据 

    -(void)loadLocalChatrecords {

        //获取本地聊天记录 会话对象

       EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.buddy.username conversationType: eConversationTypeChat];

        //加载当前来哦天用户所有的聊天记录

        NSArray *messages = [conversation loadAllMessages];

        

        for(id obj in messages) {

            NSLog(@"%@",[obj class]);

        }

        

        [self.dataSources addObject:messages];

        

    }

      [self.dataSources addObject:messages];加上了就报错了,她的原因是什么呢?

      tableView:heightForRowAtIndexPath 错了

    跳进设置高度的方法里面去 去吧里面改动一下

        //改进后的cell高度的获取

        //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

    //    EMMessage *msg = self.dataSources[indexPath.row];

    //    id body = msg.messageBodies[0];

    //    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

    //        EMTextMessageBody *textBody = body;

    //        cell.messageLabel.text = textBody;

    //    }

    最后是用一个set方法去代替他们

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

        //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

        EMMessage *msg = self.dataSources[indexPath.row];

        //改进后的cell高度的获取

    //    id body = msg.messageBodies[0];

    //    

    //    if([body isKindOfClass:[EMTextMessageBody class]]) {//如果是文本消息

    //        EMTextMessageBody *textBody = body;

    //        cell.messageLabel.text = textBody;

    //    }

        self.chatCellTool.message = msg;

        return [self.chatCellTool cellHeight];

        

        //还少了一步 ,一定要加上去设置那个label的数据

    //    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];

    //    return [self.chatCellTool cellHeight];

    }

    最后别忘了去那个tableviewcell的模型里面去改,

    ————为了计算高度我们建立了一个模型——----------

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

         //改进后的cell高度的获取

        //1.获取消息的模型 这样代码风格不好我们可以去cell的属性里面去创建一个cell的模型

        EMMessage *msg = self.dataSources[indexPath.row];

        

        self.chatCellTool.message = msg;

        

        return [self.chatCellTool cellHeight];

    }

    重写了模型的set方法 ,然后去调用了他的set方法

    最后别忘了在显示的时候去调用他渲染那个方法

    我的这个msg是一个消息模型

    msg.messageBodies[0]

    这样才能拿到消息体

    msg.messageBodies[0].text才正确

    -------------

    Pasted Graphic.tiff

    ----------这样还不对-------------------------

    你会看到你发出去的消息会在左边能看到

    如何让它只能在右边显示呢??????????/

    EMmessage有两个属性 from   to

    from是发送方也就是自己    from是好友的话自己就是接受方

    所以我们得在现实渲染的方法里面去先去获取消息模型

    然后再去做一个from的判断

        UXZYChatCell *cell = nil;

        //先去获取消息模型然后去在去判断是发送方还是接收方

        EMMessage *msg = self.dataSources[indexPath.row];

        if([msg.from isEqualToString:self.buddy.username]) {//自己接收方

           cell = [tableView dequeueReusableCellWithIdentifier:Indentifier];

        }else {

           cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];

        }

    --------怎么让你的消息立马显示-----------------------

    去这个方法里面 

    -(void)sendMessage:(NSString *)text { }

    msgObj是你自己创建一个消息对象实例   bodies是一个数组

     EMMessage *msgObj = [[EMMessage alloc]initWithReceiver:self.buddy.username bodies:@[textBody]];

        //把消息添加到数据源 再刷新表格

        [self.dataSources addObject:msgObj];

        [self.tableView reloadData];

    ------怎么让你的消息自己滚动到最上面的一行----

       

        //4.把消息显示在顶部

        [self scrollToBottom];

    }

    -(void)scrollToBottom {

        //获取最后一行

        if(self.dataSources.count == 0){

            return;

        }

        NSIndexPath *lastIndex = [NSIndexPath indexPathForRow:self.dataSources.count-1 inSection:0];

        

        

        [self.tableView scrollToRowAtIndexPath:lastIndex atScrollPosition:UITableViewScrollPositionBottom animated:YES];

    }

    —————仔细的你到这一步了发没发现你那个你发出去的消息子啊框里面都会多出一行---

    原因:是你在点击发送的时候他换了一下行,换行字符只展占用一个字节

    如何去清除那个换行的字符,在发消息的放里面去实现

            text = [text substringToIndex:text.length-1];

    -----------怎么去监听消息的回复--------------------

    1.设置代理方法  并遵循它的 代理方法

    2.有一个那个mesage的方法去实现一下

    ------对输入框的完善,即在你输入的时候那个输入框的高速会自动增加-------------------------

    1.得定义输入框的一个最小的高度和最大的高度

    2.textView是继承于UIscrollView   scrollView有一个属性 contensize 属性

        这个是计算那个做一个判断 不同情况下面的高度

    3.我们再去拿到那个的InputView 的高度的约束  再去连线使它成为一个属性  然后像之前一样去约束它,找到他,然后给他连线 使它成为一个属性

        //获取contentsize的高度

        CGFloat contentHeight = textView.contentSize.height;

        if (contentHeight <minHeight) {

            textViewH = minHeight;

        }else if (contentHeight >maxHeight) {

            textViewH = maxHeight;

        }else {

            textViewH = contentHeight;

        }

        

        self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

    4.还是有一个问题,就是在你输入完了一之后发送了   之后textView还是有一个换行的空格

    所以还得有一个在发送完了后的判断语句

    if([textView.text hasSuffix:@" "] ) {

            NSLog(@"这是一个发送事件");

            //发送文字

            [self sendMessage:textView.text];

            

            //清空文字

            textView.text = nil;

            

    //        发送时textView的高速为最小的高度

            textViewH = minHeight;

        

        }

        self.inputToolBarHeightConstrains.constant = 5 + 8 + textViewH;

    5.设置textView的背景图片  在SB中去设置 拖入一个IMageView 然后把它拿到那个textView的上面去   然后改透明  设置背景图片    把图片拉伸  streching  别忘了给背景图片加约束 不然的话他会随着那个的高度的增加他不会随着拉伸   最后去加个动画

    6.——————---发送完了后发现光标不见了 发大模拟器看在左上角???

    原因???scrollView有一个contentOffset.y的值会随着你的那个的光标的contensize的而向上拖动而拖送

    NSStringFromCGSize(textView.contentSet)可以打印出来看看

    contentOffset一开始为(0,0)之后它的y值为正数了,为什么呢,因为他要显示的下面的文字内容的话它的那个轴必须下移动 所以为正 

    如何解决  哪次发送完了 让它的contentset恢复到原位

    环信遇到的bug1:真机上面不能跑  模拟器可以

    Pasted Graphic_1.tiff

    把那个bitcode 设置为NO  bitcode是被编译程序的一种中间形式的代码。包含bitcode配置的程序将会在App store上被编译和链接

    默认是yes   

    屏幕快照 2016-04-01 下午4.02.00.png

    屏幕快照 2016-03-31 下午8.19.53.png

    屏幕快照 2016-03-31 下午8.19.18.png

    屏幕快照 2016-03-31 上午1.03.59.png

    屏幕快照 2016-03-31 上午1.13.08.png

    屏幕快照 2016-03-31 上午12.45.38.png

    storyboard作为控制器的复习

    1.拖入一导航控制器 ,更改尺寸    去掉后一个

    2.拖入一个viewControler  然后去把它的那个root viewcontroller  设置一下

    3.创建一个控制器UIviewcontroller     第三个选项 class里面更改继承关系   

    4.拖线 连线        1.去改掉main        2。去那个第4个 is initial  View Controller 的钩上

    登录提供了三种方法

    1.同步     2.block的异步      3.代理的回调

    注释的方法提示在图表

    方式一:/// 点在图标

    方式二: 

     /*!

     *   @brief 点在图标

     */

     
  • 相关阅读:
    一、Dapper基本操作
    Javascript基础--函数(Function对象)
    【Selenium专题】FAQ_浏览器_ChromeDriver版本导致报错
    mvn install 报错Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2 错误: 找不到符号
    Eclipse中mvn install 报错error in opening zip file
    Maven项目编译时报错缺少tools.jar
    maven-compiler-plugin 版本错误解决方法
    【QTP专题-优化】VBS脚本启动QTP并运行测试
    QTP 场景恢复– 函数调用
    达梦数据库(DaMeng)如何删除IDENTITY自增属性字段
  • 原文地址:https://www.cnblogs.com/Ninesday/p/5407566.html
Copyright © 2020-2023  润新知