最新環(huán)信V3.3.7單聊集成與使用

architecture.jpg
環(huán)信官網(wǎng):http://www.easemob.com/
開(kāi)發(fā)文檔:http://docs.easemob.com/im/start

一贮泞、前言

在自己做的第三個(gè)項(xiàng)目中畴栖,接觸到了環(huán)信邮丰,原來(lái)沒(méi)有對(duì)環(huán)信接入有些了解,導(dǎo)致在項(xiàng)目中使用遇到了很多的坑范嘱,最新環(huán)信V3.3.7版本也對(duì)iPhone X進(jìn)行了適配趣效,現(xiàn)在自己也有點(diǎn)空閑時(shí)間,對(duì)環(huán)信集成進(jìn)行整理艾帐,方便相關(guān)功能快速開(kāi)發(fā)乌叶,下面開(kāi)始介紹環(huán)信集成與使用吧。

二柒爸、文章介紹內(nèi)容目錄

1准浴、集成主要步驟簡(jiǎn)介

2、項(xiàng)目集成HyphenateSDK

3捎稚、項(xiàng)目集成EaseUI

4乐横、項(xiàng)目具體使用

5、常見(jiàn)問(wèn)題解決

1今野、集成主要步驟簡(jiǎn)介

集成環(huán)信服務(wù)主要有以下三個(gè)步驟

  • 1.1 注冊(cè)

注冊(cè)開(kāi)發(fā)者賬號(hào)并創(chuàng)建應(yīng)用

  • 1.2 服務(wù)器端集成(REST API)

集成用戶和好友體系

  • 1.3 客戶端集成

集成文檔:
Android SDK 集成
iOS SDK 集成
Linux SDK 集成
Web IM SDK 集成
集成用戶和好友體系

2葡公、項(xiàng)目集成HyphenateSDK

  • 2.1 集成 iOS SDK 前的準(zhǔn)備工作

如果你需要用到環(huán)信推送功能,需要按照環(huán)信制作并上傳推送證書申請(qǐng)配置證書条霜,不需要?jiǎng)t跳過(guò)此步驟匾南。

  • 2.2 SDK重要組成部分集成前需了解

demo.png

SDK_Core: 為核心的消息同步協(xié)議實(shí)現(xiàn),完成與服務(wù)器之間的信息交換蛔外。
SDK: 是基于核心協(xié)議實(shí)現(xiàn)的完整的 IM 功能蛆楞,實(shí)現(xiàn)了不同類型消息的收發(fā)、會(huì)話管理夹厌、群組豹爹、好友、聊天室等功能矛纹。
EaseUI: 是一組 IM 相關(guān)的 UI 控件臂聋,旨在幫助開(kāi)發(fā)者快速集成環(huán)信 SDK。

sdk.png

EMClient: 是 SDK 的入口,主要完成登錄孩等、退出艾君、連接管理等功能。也是獲取其他模塊的入口肄方。
EMChatManager: 管理消息的收發(fā)冰垄,完成會(huì)話管理等功能。
EMContactManager: 負(fù)責(zé)好友的添加刪除权她,黑名單的管理虹茶。
EMGroupManager: 負(fù)責(zé)群組的管理,創(chuàng)建隅要、刪除群組蝴罪,管理群組成員等功能。
EMChatroomManager: 負(fù)責(zé)聊天室的管理步清。

上面這些內(nèi)容要门,可以對(duì)環(huán)信SDK組成有一個(gè)大致的理解,在最開(kāi)始接入環(huán)信時(shí)候廓啊,自己沒(méi)有看相關(guān)介紹文檔欢搜,導(dǎo)致自己使用工程中遇到很多坑。

2.3 通過(guò) Cocoapods導(dǎo)入

  • 2.3.1 不包含實(shí)時(shí)語(yǔ)音版本 SDK(HyphenateLite)崖瞭,引用時(shí) #import <HyphenateLite/HyphenateLite.h>
pod 'HyphenateLite'
  • 2.3.2 包含實(shí)時(shí)語(yǔ)音版本 SDK(Hyphenate),引用時(shí) #import <Hyphenate/Hyphenate.h>
pod 'Hyphenate'

2.4 手動(dòng)集成

  • 2.4.1 SDK下載

官方最新SDK+Demo
HyphenateV3.3.7

  • 2.4.2 將ios_IM_sdk_V3.3.7文件下的SDK文件夾拖入到工程撑毛,如下圖所示:
屏幕快照 2018-01-11 下午2.42.24.png
屏幕快照 2018-01-11 下午2.49.43.png
  • 2.4.3 添加依賴庫(kù)
  • 不包含實(shí)時(shí)語(yǔ)音系統(tǒng)依賴庫(kù)

CoreMedia.framework
AudioToolbox.framework
AVFoundation.framework
MobileCoreServices.framework
ImageIO.framework
ibc++.tbd
libz.tbd
libstdc++.6.0.9.tbd
libsqlite3.tbd

  • 包含實(shí)時(shí)語(yǔ)音系統(tǒng)依賴庫(kù)

CoreMedia.framework
AudioToolbox.framework
AVFoundation.framework
MobileCoreServices.framework
ImageIO.framework
libc++.tbd
libz.tbd
libstdc++.6.0.9.tbd
ibsqlite3.tbd
libiconv.tbd

如果使用的是 xcode7以下书聚,后綴為dylib。
Parse.framework藻雌、Bolts.framework: Demo 中的用戶信息存儲(chǔ)在 Parse雌续,這兩個(gè)庫(kù)是 Parse 所需要的庫(kù),開(kāi)發(fā)者如果沒(méi)用 Parse 存儲(chǔ)胯杭,不要復(fù)制到自己項(xiàng)目中驯杜。

  • 2.4.4 因?yàn)镠yphenate是動(dòng)態(tài)庫(kù),需要在Build Phase中 Embedded Binaries添加Hyphenate.framework做个,如下圖所示:
屏幕快照 2018-01-11 下午3.14.39.png
  • 到這里鸽心,SDK已經(jīng)導(dǎo)入到項(xiàng)目中了,commad+R運(yùn)行下工程居暖,沒(méi)有報(bào)錯(cuò)說(shuō)明已成功集成顽频。
  • 這里不得不提醒下自己,在第一次接入環(huán)信的時(shí)候沒(méi)有認(rèn)真閱讀環(huán)信集成文檔太闺,沒(méi)有添加Embedded Binaries糯景,導(dǎo)致能夠正常初始化和登錄,但是不能夠正常接收消息,自己找了好久也沒(méi)有發(fā)現(xiàn)問(wèn)題所在蟀淮。還是怪自己閱讀文檔不認(rèn)真最住,有經(jīng)驗(yàn)的同事很快幫我找到問(wèn)題了。

3怠惶、項(xiàng)目集成EaseUI

具體使用詳情涨缚,請(qǐng)戳:EaseUI使用指南

  • 3.1 EaseUI支持pod導(dǎo)入

//Pod集成EaseUI時(shí),會(huì)同時(shí)通過(guò)Pod集成SDK

//對(duì)應(yīng)Hyphenate SDK(sdk包含實(shí)時(shí)音視頻)
pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git'

//對(duì)應(yīng)HyphenateLite SDK(sdk不包含實(shí)時(shí)音視頻)
pod 'EaseUILite', :git =>'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git'

// 指定版本甚疟,可以在后面添加tag仗岖,例如:導(dǎo)入最新V3.3.7
pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git', :tag => ‘3.3.7’

項(xiàng)目中沒(méi)有用pod方式導(dǎo)入,如果對(duì)UI沒(méi)有太多自定義要求览妖,可以用pod方式導(dǎo)入轧拄,方便版本管理,如果EaseUI不能滿足項(xiàng)目需求讽膏,這時(shí)就要用手動(dòng)導(dǎo)入方式了檩电。不知道pod導(dǎo)入有坑沒(méi)有,哈哈??府树。

  • 3.2 手動(dòng)導(dǎo)入

  • 3.2.1 EaseUI依賴三方庫(kù)

MWPhotoBrowser:圖片處理庫(kù)俐末,瀏覽顯示
MJRefresh:用于頁(yè)面刷新
MBProgressHUD:用于提示加載刷新
libopencore-amrnb.a、libopencore-amrwb.a:用于 amr 與 wav 之間的轉(zhuǎn)換
EMSDWebImage(SDWebImage):圖片下載

  • 3.2.2 對(duì)EaseUI文件夾文件進(jìn)行整理
  • 如果不想使用v3.3.7中的三方依賴庫(kù)(比如說(shuō)MJRefresh庫(kù)更新過(guò)后適配了iPhone X)奄侠,我們想通過(guò)Cocoapods導(dǎo)入相關(guān)依賴庫(kù)卓箫,方便項(xiàng)目對(duì)三方庫(kù)管理。這時(shí)需要對(duì)先關(guān)文件進(jìn)行修改垄潮,但改動(dòng)的也并不是很多烹卒。整理過(guò)后EaseUI目錄如下圖所示:
    屏幕快照 2018-01-11 下午9.54.04.png
  • 3.2.3 這時(shí)依賴庫(kù)通過(guò)Cocoapods導(dǎo)入,在引用到這些庫(kù)頭文件的地方改為import <頭文件名>就好了弯洗,方法調(diào)用修改下:
pod 'MJRefresh','3.1.15.1'
pod 'MBProgressHUD','1.1.0'
pod 'SDWebImage','4.2.3'
  • 3.2.4 創(chuàng)建一個(gè)PCH文件旅急,導(dǎo)入EaseUI頭文件:
#ifdef __OBJC__

#ifndef PrefixHeader_pch
#define PrefixHeader_pch

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "EaseUI.h"
#endif
// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.

#endif /* PrefixHeader_pch */
  • EaseUI.h文件做如下修改:
//#import "UIImageView+EMWebCache.h"
#import <UIImageView+WebCache.h>
  • 最新SDWebImage下載圖片方法名修改一下:
//舊版本
downloadImageWithURL:
//新版本V4.2.3
loadImageWithURL:

整理好的EaseUI最終文件請(qǐng)戳:
V3.3.7 EaseUI

  • 3.2.5 對(duì)V3.3.7Demo中聊天控制器和會(huì)話列表控制器進(jìn)行整理,注釋不必要的文件引用和代碼牡整。我也將整理好的文件貼出來(lái)吧藐吮,請(qǐng)戳:

WBChat

4、項(xiàng)目具體使用

可以封裝一個(gè)工具類來(lái)管理Hyphenate初始化逃贝、登錄等相關(guān)操作谣辞。

  • 4.1 Hyphenate初始化

- (void)initHyphenateSDK {
    EMOptions *options = [EMOptions optionsWithAppkey:@""];
    //        options.apnsCertName = kEasemobSDKPushName;
    EMError *error = nil;
    error =  [[EMClient sharedClient] initializeSDKWithOptions:options];
    if (!error) {
        NSLog(@"環(huán)信初始化成功");
    }
    
    /**  < 注冊(cè)通知 >  */
    [self registerNoti];
}
  • 4.2 登錄&退出登錄

- (void)wb_hyphenateLoginSuccess:(void (^)(void))success failure:(void (^)(void))failure {
    /** <<
     用戶調(diào)用了 SDK 的登出動(dòng)作;
     用戶在別的設(shè)備上更改了密碼沐扳,導(dǎo)致此設(shè)備上自動(dòng)登錄失斄氏小;
     用戶的賬號(hào)被從服務(wù)器端刪除迫皱;
     用戶從另一個(gè)設(shè)備登錄歉闰,把當(dāng)前設(shè)備上登錄的用戶踢出辖众。
     > */
    BOOL isAutoLogin = [EMClient sharedClient].options.isAutoLogin;
    if (!isAutoLogin) {
        EMError *error = [[EMClient sharedClient] loginWithUsername:@"" password:@""];
        if (!error) {
            if (success) {
                success();
            }
            /**  < 設(shè)置是否自動(dòng)登錄 >  */
            [[EMClient sharedClient].options setIsAutoLogin:YES];
            NSLog(@"環(huán)信登錄成功");
        }else {
            if (failure) {
                failure();
            }
             NSLog(@"環(huán)信登錄失敗");
        }
    }
}

- (void)wb_hyphenateLogoutSuccess:(void (^)(void))success failure:(void (^)(void))failure {
    EMError *error = [[EMClient sharedClient] logout:YES];
    if (!error) {
        NSLog(@"環(huán)信退出成功");
        if (success) {
            success();
        }
    }else {
        if (failure) {
            failure();
        }
        NSLog(@"環(huán)信退出失敗");
    }
}
  • 4.3 自動(dòng)登錄

- (void)wb_applicationDidEnterBackground:(UIApplication *)application {
    [[EMClient sharedClient] applicationDidEnterBackground:application];
}

- (void)wb_applicationWillEnterForeground:(UIApplication *)application {
    [[EMClient sharedClient] applicationWillEnterForeground:application];
}

  • 4.4 跳轉(zhuǎn)聊天界面

/**  <
     單聊:EMConversationTypeChat
     Chatter:聊天對(duì)象用戶名
     >  */
    WBChatViewController *vc = [[WBChatViewController alloc]initWithConversationChatter:@"" conversationType:EMConversationTypeChat];
    [self.navigationController pushViewController:vc animated:YES];

主要有以下兩種:

  • 從APP服務(wù)器獲取昵稱和頭像

  • 從消息擴(kuò)展中獲取昵稱和頭像

  • 4.5.2 我在項(xiàng)目中采用的是從消息擴(kuò)展中獲取昵稱和頭像,下面開(kāi)始介紹我的實(shí)現(xiàn)方案吧和敬。
  • 會(huì)話列表處理凹炸,在EaseConversationListViewController.m中的refreshAndSortView加載會(huì)話列表方法,對(duì)發(fā)送方消息擴(kuò)展字段進(jìn)行緩存昼弟,可以用數(shù)據(jù)庫(kù)或者是歸檔等方法啤它,我采用的是歸檔,保存擴(kuò)展消息模型舱痘。
    //緩存發(fā)送方用戶信息到本地

-(void)refreshAndSortView
{
    if ([self.dataArray count] > 1) {
        if ([[self.dataArray objectAtIndex:0] isKindOfClass:[EaseConversationModel class]]) {
            NSArray* sorted = [self.dataArray sortedArrayUsingComparator:
                               ^(EaseConversationModel *obj1, EaseConversationModel* obj2){
                                   EMMessage *message1 = [obj1.conversation latestMessage];
                                   EMMessage *message2 = [obj2.conversation latestMessage];
                                   if(message1.timestamp > message2.timestamp) {
                                       return(NSComparisonResult)NSOrderedAscending;
                                   }else {
                                       return(NSComparisonResult)NSOrderedDescending;
                                   }
                               }];
            [self.dataArray removeAllObjects];
            [self.dataArray addObjectsFromArray:sorted];
            for (EMConversation *conversation in self.dataArray) {
                /**  < 緩存發(fā)送消息者信息 >  */
                /**  < 收到的對(duì)方發(fā)送的最后一條消息变骡,也是會(huì)話里的最新消息 >  */
                EMMessage *lastReceiveMessage = [conversation lastReceivedMessage];
                if (lastReceiveMessage) {
                    NSDictionary *extDic = lastReceiveMessage.ext;
                    HyhenateUserModel *user = [HyhenateUserModel yy_modelWithDictionary:extDic];
                    BOOL res = [[WBConversationManager shareManager] wb_archiveObjectToFileWithConversation_ID:conversation.conversationId archiveData:user];
                    if (res) {
                        NSLog(@"更新聊天對(duì)象信息成功 ");
                    }else {
                        NSLog(@"更新聊天對(duì)象信息失敗 ");
                    }
                }
            }
        }
    }
    [self.tableView reloadData];
}

//在WBConversationListViewController.m讀取緩存

pragma mark ------ < EaseConversationListViewControllerDataSource > ------
#pragma mark
- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
                                    modelForConversation:(EMConversation *)conversation
{
    EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
    if (model.conversation.type == EMConversationTypeChat) {
//        if ([[RobotManager sharedInstance] isRobotWithUsername:conversation.conversationId]) {
//            model.title = [[RobotManager sharedInstance] getRobotNickWithUsername:conversation.conversationId];
//        } else {
//            UserProfileEntity *profileEntity = [[UserProfileManager sharedInstance] getUserProfileByUsername:conversation.conversationId];
//            if (profileEntity) {
//                model.title = profileEntity.nickname == nil ? profileEntity.username : profileEntity.nickname;
//                model.avatarURLPath = profileEntity.imageUrl;
//            }
//        }
        HyhenateUserModel *user = [[WBConversationManager shareManager] wb_unarchiveObjectWithConversation_ID:conversation.conversationId];
        if (user) {
            model.title = user.nick;
            model.avatarURLPath = user.avatar;
        }
    } else if (model.conversation.type == EMConversationTypeGroupChat) {
        NSString *imageName = @"groupPublicHeader";
        if (![conversation.ext objectForKey:@"subject"])
        {
            NSArray *groupArray = [[EMClient sharedClient].groupManager getJoinedGroups];
            for (EMGroup *group in groupArray) {
                if ([group.groupId isEqualToString:conversation.conversationId]) {
                    NSMutableDictionary *ext = [NSMutableDictionary dictionaryWithDictionary:conversation.ext];
                    [ext setObject:group.subject forKey:@"subject"];
                    [ext setObject:[NSNumber numberWithBool:group.isPublic] forKey:@"isPublic"];
                    conversation.ext = ext;
                    break;
                }
            }
        }
        NSDictionary *ext = conversation.ext;
        model.title = [ext objectForKey:@"subject"];
        imageName = [[ext objectForKey:@"isPublic"] boolValue] ? @"groupPublicHeader" : @"groupPrivateHeader";
        model.avatarImage = [UIImage imageNamed:imageName];
    }
    return model;
}

//右滑刪除本地緩存:EaseConversationListViewController.m->deleteCellAction:

- (void)deleteCellAction:(NSIndexPath *)aIndexPath
{
    EaseConversationModel *model = [self.dataArray objectAtIndex:aIndexPath.row];
    [[EMClient sharedClient].chatManager deleteConversation:model.conversation.conversationId isDeleteMessages:YES completion:nil];
    /**  < 刪除用戶信息 >  */
    [[WBConversationManager shareManager] removeArchiveDataAtFilePath:model.conversation.conversationId];
    [self.dataArray removeObjectAtIndex:aIndexPath.row];
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:aIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
  • 聊天界面處理
    //添加用戶信息擴(kuò)展,在EaseMessageViewController.m->_sendMessage方法中添加擴(kuò)展信息
- (void)_sendMessage:(EMMessage *)message
    isNeedUploadFile:(BOOL)isUploadFile
{
    if (self.conversation.type == EMConversationTypeGroupChat){
        message.chatType = EMChatTypeGroupChat;
    }
    else if (self.conversation.type == EMConversationTypeChatRoom){
        message.chatType = EMChatTypeChatRoom;
    }
    
    NSDictionary *ext = message.ext;
    if (ext == nil) {
        /**  <
         發(fā)送消息最終執(zhí)行的方法芭逝,在這里構(gòu)造自己信息擴(kuò)展塌碌,通常用戶信息在本地都有保存,這里只是測(cè)試
         >  */
        NSDictionary *userDict = @{@"nick" : @"test",
                                   @"avatar" : @"imageFile"
                                   };
        message.ext = ext;
    }
    
    __weak typeof(self) weakself = self;
    if (!([EMClient sharedClient].options.isAutoTransferMessageAttachments) && isUploadFile) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"message.autoTransfer", @"Please customize the transfer attachment method") delegate:nil cancelButtonTitle:NSLocalizedString(@"sure", @"OK") otherButtonTitles:nil, nil];
        [alertView show];
    } else {
        [self addMessageToDataSource:message
                            progress:nil];
        
        [[EMClient sharedClient].chatManager sendMessage:message progress:^(int progress) {
            if (weakself.dataSource && [weakself.dataSource respondsToSelector:@selector(messageViewController:updateProgress:messageModel:messageBody:)]) {
                [weakself.dataSource messageViewController:weakself updateProgress:progress messageModel:nil messageBody:message.body];
            }
        } completion:^(EMMessage *aMessage, EMError *aError) {
            if (!aError) {
                [weakself _refreshAfterSentMessage:aMessage];
            }
            else {
                [weakself.tableView reloadData];
            }
        }];
    }
}

//擴(kuò)展信息展示旬盯,在WBChatViewController.m->messageViewController:修改

#pragma mark ------ < EaseMessageViewControllerDataSource > ------
#pragma mark
/** << 設(shè)置頭像台妆、昵稱 > */
- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message
{
    id<IMessageModel> model = nil;
    model = [[EaseMessageModel alloc] initWithMessage:message];
    model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
//    UserProfileEntity *profileEntity = [[UserProfileManager sharedInstance] getUserProfileByUsername:model.nickname];
//    if (profileEntity) {
//        model.avatarURLPath = profileEntity.imageUrl;
//        model.nickname = profileEntity.nickname;
//    }
    if (model.isSender) {
        //直接取出本地用戶信息
        model.nickname = @"本地保存的用戶名";
        model.avatarURLPath = @"本地用戶頭像地址";
    }else {
        NSDictionary *userDict = message.ext;
        HyhenateUserModel *user = [HyhenateUserModel yy_modelWithDictionary:userDict];
        model.nickname = user.nick;
        model.avatarURLPath = user.avatar;
    }
    model.failImageName = @"imageDownloadFail";
    return model;
}

代碼我已托管到碼云上了,詳情請(qǐng)戳:ManageHyphenateSDK
使用demo注意

  • 因?yàn)榄h(huán)信SDK超過(guò)了100M胖翰,我對(duì)其進(jìn)行了忽略接剩,可以將HyphenateFullSDK.zip文件解壓縮重新導(dǎo)入一次。
  • 導(dǎo)入三方庫(kù)萨咳,cd 工程路徑懊缺,執(zhí)行
pod install

完成上述兩個(gè)步驟,就能正常運(yùn)行工程啦~培他,運(yùn)行效果如下圖所示:


Untitled.gif

5鹃两、常見(jiàn)問(wèn)題解決

  • 5.1 image not found

屏幕快照 2018-01-11 下午3.03.57.png

可參考標(biāo)題目錄2.4.4解決,或者
屏幕快照 2018-01-11 下午3.26.40.png

  • 5.2 集成動(dòng)態(tài)庫(kù)上傳AppStore

由于 iOS 編譯的特殊性靶壮,為了方便開(kāi)發(fā)者使用怔毛,我們將 i386 x86_64 armv7 arm64 幾個(gè)平臺(tái)都合并到了一起员萍,所以使用動(dòng)態(tài)庫(kù)上傳appstore時(shí)需要將i386 x86_64兩個(gè)平臺(tái)刪除后腾降,才能正常提交審核
在SDK當(dāng)前路徑下執(zhí)行以下命令刪除i386 x86_64兩個(gè)平臺(tái)
bak文件是備份目錄,上傳appstore之后需要替換回bak目錄下的SDK

  • 實(shí)時(shí)音視頻版本Hyphenate.framework
mkdir ./bak
cp -r Hyphenate.framework ./bak
lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7
lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64
lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate
mv Hyphenate Hyphenate.framework/
  • 不包含實(shí)時(shí)音視頻版本HyphenateLite.framework
mkdir ./bak
cp -r HyphenateLite.framework ./bak
lipo HyphenateLite.framework/HyphenateLite -thin armv7 -output HyphenateLite_armv7
lipo HyphenateLite.framework/HyphenateLite -thin arm64 -output HyphenateLite_arm64
lipo -create HyphenateLite_armv7 HyphenateLite_arm64 -output HyphenateLite
mv HyphenateLite HyphenateLite.framework/

三碎绎、總結(jié)

終于整理完成了螃壤,自己在寫Demo的過(guò)程中,由于git reset命令使用不當(dāng)筋帖,導(dǎo)致整理的文件全部撤銷了奸晴,頓時(shí)都無(wú)語(yǔ)了,不管怎樣日麸,最終還是整理完成了寄啼。在集成EaseUI的時(shí)候逮光,建議還是手動(dòng)集成吧,如果你需要對(duì)其中文件進(jìn)行更改墩划。Demo中導(dǎo)入的EaseUI涕刚,我并不是原樣導(dǎo)入的,如果你不想修改乙帮,可以直接將EaseUI導(dǎo)入到工程杜漠。由于能力有限,有些地方整理的不是很好察净,也可以自行修改驾茴,希望自己以后集成環(huán)信能少遇到一些坑,希望這篇文章也能對(duì)你有所幫助氢卡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锈至,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子异吻,更是在濱河造成了極大的恐慌裹赴,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诀浪,死亡現(xiàn)場(chǎng)離奇詭異棋返,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)雷猪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門睛竣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人求摇,你說(shuō)我怎么就攤上這事射沟。” “怎么了与境?”我有些...
    開(kāi)封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵验夯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我摔刁,道長(zhǎng)挥转,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任共屈,我火速辦了婚禮绑谣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拗引。我一直安慰自己借宵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布矾削。 她就那樣靜靜地躺著壤玫,像睡著了一般豁护。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上欲间,一...
    開(kāi)封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天择镇,我揣著相機(jī)與錄音,去河邊找鬼括改。 笑死腻豌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嘱能。 我是一名探鬼主播吝梅,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惹骂!你這毒婦竟也來(lái)了苏携?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤对粪,失蹤者是張志新(化名)和其女友劉穎右冻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體著拭,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纱扭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了儡遮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乳蛾。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鄙币,靈堂內(nèi)的尸體忽然破棺而出肃叶,到底是詐尸還是另有隱情,我是刑警寧澤十嘿,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布因惭,位于F島的核電站,受9級(jí)特大地震影響绩衷,放射性物質(zhì)發(fā)生泄漏蹦魔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一唇聘、第九天 我趴在偏房一處隱蔽的房頂上張望版姑。 院中可真熱鬧柱搜,春花似錦迟郎、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)表制。三九已至,卻和暖如春控乾,著一層夾襖步出監(jiān)牢的瞬間么介,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工蜕衡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壤短,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓慨仿,卻偏偏與公主長(zhǎng)得像久脯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子镰吆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容