facebook的socketrocket总结

最近看了开源的网易的demo
[url]https://netease.im/[/url]
关键类
NTESSessionViewController.m
发送函数

#pragma mark - 消息发送时间截获
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error

NIMSessionViewController.m
接收消息函数

//接收消息
- (void)onRecvMessages:(NSArray *)messages



############

ld: warning: directory not found for option

brew install cocoapods


xcode-select --switch /Applications/Xcode.app

pod install


https://stackoverflow.com/questions/24050012/error-library-not-found-for

I had a similar "library not found" issue. However it was because I accidentally was using the .xcodeproj file instead of the .xcworkspace file.


###########
推送问题

Cannot create a iOS App Development provisioning profile for "com.haoning.demo123121".
Your development team, "leaf french", does not support the Push Notifications capability.
把
NIMDev.entitlements
的
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
改成
<dict>
</dict>

[url]https://stackoverflow.com/questions/44568009/how-to-disable-push-notification-capability-in-xcode-project[/url]


Xcode 运行项目时候选择模拟器位置处显示"My Mac" 的处理

1、先关闭Xcode,找到该工程项目目录,找到该项目的***.xcodeproj 文件,然后右键点击选择“显示包内容”;
2、包内容中显示以下三项:project.pbxproj .project.xcworkspace .xcuserdata 接着选择“xcuserdata”这个文件夹,将其整个移到废纸篓,重新打开你的项目,则可使用Simulator;
3、如果上诉方法没有用, 那么找到target->built settings->Architectures->Base SDK.这里改成你需要的iOS版本即可。


iOS 报错:cannot create weak reference in file using
[url]http://blog.youkuaiyun.com/u010545480/article/details/52995908[/url]

[img]http://dl2.iteye.com/upload/attachment/0129/1820/6ac758a3-a7ef-3a97-86a9-6d4e03bc9541.png[/img]

SocketRocket must be compiled with ARC enabled
[url]https://jingyan.baidu.com/article/358570f67babbcce4724fcd8.html[/url]
build settings搜ARC
[img]http://dl2.iteye.com/upload/attachment/0129/1836/87e02fba-ab2e-38ad-9520-19041e52ee5f.png[/img]



#pragma mark - 消息发送时间截获
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error
{
printf("sendMessage---->hello hit me!!\n");
// NSString *message_temp = @"aaa";
//message = mytext.text;
// [_webSocket send:message_temp];

[_webSocket send:message.text];


// printf("------->sendMessage--begin----->\n");
NSLog(@"---NTESSessionViewController-->sendMessage----->>>>>>%@",message);
// printf("------->sendMessage--end----->\n");




1。新建target framework & Library ,选Cocoa Touch Static Library 文字为SocketRocket
2。SRWebSocket.h 和.m覆盖过来
3.编译完SocketRocket的target
4.切换到im的target,爸libsocketrockt.a作为build Phrase的link binary with library引入进来
,还要引入foundtion.framework Security.framework CFNetwork.framework
3.ViewController引入
#import "SRWebSocket.h"
@interface ViewController () <SRWebSocketDelegate>

@end
@implementation ViewController {
SRWebSocket *_webSocket;
NSMutableArray *_messages;
}

报错引入各种接口

- (void)viewDidLoad {
[super viewDidLoad];
printf("haha begin--> \n");
_webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://localhost:3001"]]];

_webSocket.delegate = self;
[_webSocket open];

[NSThread sleepForTimeInterval:0.1f];
printf("haha open--> \n");
NSString *message = @"aaa";
[_webSocket send:message];



[_webSocket close];
printf("haha close--> \n");
printf("haha end--> \n");
// Do any additional setup after loading the view, typically from a nib.
}


4.
Installing (iOS)
----------------
There's a few options. Choose one, or just figure it out

- You can copy all the files in the SocketRocket group into your app.
- Include SocketRocket as a subproject and use libSocketRocket

If you do this, you must add -ObjC to your "other linker flags" option

- For OS X you will have to repackage make a .framework target. I will take
contributions. Message me if you are interested.


Depending on how you configure your project you may need to ``#import`` either
``<SocketRocket/SRWebSocket.h>`` or ``"SRWebSocket.h"``

Framework Dependencies
``````````````````````
Your .app must be linked against the following frameworks/dylibs

- libicucore.dylib
- CFNetwork.framework
- Security.framework
- Foundation.framework



按钮拖拽产生定义事件

[url]https://www.cnblogs.com/foxting/p/SWIFT.html[/url]


node的server代码


"use strict";
process.title = 'node-chat';
var webSocketsServerPort = 3001;
var webSocketServer = require('websocket').server;
var http = require('http');
var history = [ ];
var clients = [ ];
var server = http.createServer(function(request, response) {
// Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " + webSocketsServerPort);
});

var wsServer = new webSocketServer({
httpServer: server
});

wsServer.on('request', function(request) {
console.log((new Date()) + ' Connection from origin ' + request.origin + '.');
var connection = request.accept(null, request.origin);
var index = clients.push(connection) - 1;
console.log((new Date()) + ' Connection accepted.');

// send back chat history
if (history.length > 0) {
connection.sendUTF(JSON.stringify( { type: 'history', data: history} ));
}

// user sent some message
connection.on('message', function(message) {
//connection.sendUTF(JSON.stringify({ type:'color', data: userColor }));
console.log("server receive:"+JSON.stringify(message));
connection.sendUTF("单发 hello:"+message.utf8Data);
});

// user disconnected
connection.on('close', function(connection) {
console.log((new Date()) + " Peer "
+ connection.remoteAddress + " disconnected.");
});

});


h5代码


<html>
<body>
<div id="output"></div>
<script>
function checkBrowser(){
if (window.WebSocket){
log("This browser supports WebSocket!");
} else {
log("This browser does not support WebSocket.");
}
}
function setup(){
//var wsServer = 'ws://13.115.181.153:3001';
var wsServer = 'ws://localhost:3001';
var ws = new WebSocket(wsServer);

ws.onopen = function (e) {
log("Connected to WebSocket server.",e);
sendMessage("hello");
} ;

ws.onclose = function (e) {
log("Disconnected",e);
} ;

ws.onmessage = function(e) {
log("RECEIVED: " + e.data, e);
ws.close();
}

ws.onerror = function (e) {
log('Error occured: ' + e.data,e);
} ;

var sendMessage = function(msg){
ws.send(msg);
log("SEND : "+ msg);
}
}

function log(s,e) {
var output = document.getElementById("output");
var p = document.createElement("p");
p.style.wordWrap = "break-word";
p.style.padding="10px";
p.style.background="#eee";
p.textContent = "LOG : "+s;
output.appendChild(p);
console.log("LOG : "+s, e);
}

checkBrowser();
setup();
</script>
</body>
</html>



ios代码

//
// ViewController.m
// secondim
//
// Created by haoning on 2018/4/3.
// Copyright © 2018年 haoning. All rights reserved.
//

#import "ViewController.h"
#import "SRWebSocket.h"

@interface ViewController () <SRWebSocketDelegate>

@end

@implementation ViewController {
SRWebSocket *_webSocket;
NSMutableArray *_messages;
IBOutlet UIButton *thisbtn;
IBOutlet UILabel *showme;
IBOutlet UITextField *mytext;
}

- (IBAction)hitme:(id)sender {
printf("hello hit me!!\n");
NSString *message = @"aaa";
message = mytext.text;
[_webSocket send:message];
}

- (void)viewDidLoad {
[super viewDidLoad];
printf("haha begin--> \n");
_webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://localhost:3001"]]];

_webSocket.delegate = self;

[_webSocket open];
showme.text = @"haha i am label";
[NSThread sleepForTimeInterval:0.1f];
printf("haha open--> \n");




//[_webSocket close];
printf("haha close--> \n");
printf("haha end--> \n");
// Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}


- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
// NSString *string1 = @"我是甲一号";
//NSLog(@"Received =------>>>>>>>>>>%s \n",@"我是甲一号");
showme.text=message;
}

- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {

}

- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection {

}

- (void)preferredContentSizeDidChangeForChildContentContainer:(nonnull id<UIContentContainer>)container {

}


- (void)systemLayoutFittingSizeDidChangeForChildContentContainer:(nonnull id<UIContentContainer>)container {

}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator {

}

- (void)willTransitionToTraitCollection:(nonnull UITraitCollection *)newCollection withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator {

}

- (void)didUpdateFocusInContext:(nonnull UIFocusUpdateContext *)context withAnimationCoordinator:(nonnull UIFocusAnimationCoordinator *)coordinator {

}

- (void)setNeedsFocusUpdate {

}


- (void)updateFocusIfNeeded {

}

@end



呵呵哒的demo里面的代码

//
// NTESSessionViewController.m
// NIM
//
// Created by amao on 8/11/15.
// Copyright (c) 2015 Netease. All rights reserved.
//

#import "NTESSessionViewController.h"
@import MobileCoreServices;
@import AVFoundation;
#import "Reachability.h"
#import "UIActionSheet+NTESBlock.h"
#import "NTESCustomSysNotificationSender.h"
#import "NTESSessionConfig.h"
#import "NIMMediaItem.h"
#import "NTESSessionMsgConverter.h"
#import "NTESFileLocationHelper.h"
#import "NTESSessionMsgConverter.h"
#import "UIView+Toast.h"
#import "NTESSnapchatAttachment.h"
#import "NTESJanKenPonAttachment.h"
#import "NTESFileTransSelectViewController.h"
#import "NTESAudioChatViewController.h"
#import "NTESWhiteboardViewController.h"
#import "NTESVideoChatViewController.h"
#import "NTESChartletAttachment.h"
#import "NTESGalleryViewController.h"
#import "NTESVideoViewController.h"
#import "NTESFilePreViewController.h"
#import "NTESAudio2TextViewController.h"
#import "NSDictionary+NTESJson.h"
#import "NIMAdvancedTeamCardViewController.h"
#import "NTESSessionRemoteHistoryViewController.h"
#import "NIMNormalTeamCardViewController.h"
#import "UIView+NTES.h"
#import "NTESBundleSetting.h"
#import "NTESPersonalCardViewController.h"
#import "NTESSessionSnapchatContentView.h"
#import "NTESSessionLocalHistoryViewController.h"
#import "NIMContactSelectViewController.h"
#import "SVProgressHUD.h"
#import "NTESSessionCardViewController.h"
#import "NTESFPSLabel.h"
#import "UIAlertView+NTESBlock.h"
#import "NIMKit.h"
#import "NTESSessionUtil.h"
#import "NIMKitMediaFetcher.h"
#import "NIMKitLocationPoint.h"
#import "NIMLocationViewController.h"
#import "NIMKitInfoFetchOption.h"
#import "NTESSubscribeManager.h"
#import "NTESTeamMeetingViewController.h"
#import "NTESTeamMeetingCallerInfo.h"
#import "NIMInputAtCache.h"
#import "NTESRobotCardViewController.h"
#import "NTESRedPacketManager.h"
#import "NTESSessionRedPacketContentView.h"
#import "NTESSessionRedPacketTipContentView.h"
#import "NTESRedPacketAttachment.h"
#import "NTESRedPacketTipAttachment.h"
#import "NTESCellLayoutConfig.h"
#import "NTESTeamReceiptSendViewController.h"
#import "NTESTeamReceiptDetailViewController.h"
#import "SRWebSocket.h"

@interface NTESSessionViewController ()
<UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
NIMSystemNotificationManagerDelegate,
NIMMediaManagerDelegate,
NTESTimerHolderDelegate,
NIMContactSelectDelegate,
NIMEventSubscribeManagerDelegate,SRWebSocketDelegate>

@property (nonatomic,strong) NTESCustomSysNotificationSender *notificaionSender;
@property (nonatomic,strong) NTESSessionConfig *sessionConfig;
@property (nonatomic,strong) UIImagePickerController *imagePicker;
@property (nonatomic,strong) NTESTimerHolder *titleTimer;
@property (nonatomic,strong) UIView *currentSingleSnapView;
@property (nonatomic,strong) NTESFPSLabel *fpsLabel;
@property (nonatomic,strong) NIMKitMediaFetcher *mediaFetcher;
@end


@implementation NTESSessionViewController{

SRWebSocket *_webSocket;

}

- (void)viewDidLoad {
[super viewDidLoad];

_webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://13.115.181.153:3001"]]];

_webSocket.delegate = self;

[_webSocket open];


DDLogInfo(@"---->enter session, id = %@",self.session.sessionId);
_notificaionSender = [[NTESCustomSysNotificationSender alloc] init];
[self setUpNav];
BOOL disableCommandTyping = self.disableCommandTyping || (self.session.sessionType == NIMSessionTypeP2P &&[[NIMSDK sharedSDK].userManager isUserInBlackList:self.session.sessionId]);
if (!disableCommandTyping) {
_titleTimer = [[NTESTimerHolder alloc] init];
[[NIMSDK sharedSDK].systemNotificationManager addDelegate:self];
}

if ([[NTESBundleSetting sharedConfig] showFps])
{
self.fpsLabel = [[NTESFPSLabel alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.fpsLabel];
self.fpsLabel.right = self.view.width;
self.fpsLabel.top = self.tableView.top + self.tableView.contentInset.top;
}

if (self.session.sessionType == NIMSessionTypeP2P && !self.disableOnlineState)
{
//临时订阅这个人的在线状态 haohao
[[NTESSubscribeManager sharedManager] subscribeTempUserOnlineState:self.session.sessionId];
[[NIMSDK sharedSDK].subscribeManager addDelegate:self];
}

//删除最近会话列表中有人@你的标记
[NTESSessionUtil removeRecentSessionAtMark:self.session];

}

- (void)dealloc
{
printf("------dealloc---->\n");
[[NIMSDK sharedSDK].systemNotificationManager removeDelegate:self];
if (self.session.sessionType == NIMSessionTypeP2P && !self.disableOnlineState)
{
[[NIMSDK sharedSDK].subscribeManager removeDelegate:self];
[NTESSubscribeManager sharedManager]unsubscribeTempUserOnlineState:self.session.sessionId];
}
[_fpsLabel invalidate];
}


- (void)viewDidLayoutSubviews{
printf("------viewDidLayoutSubviews---->\n");
[super viewDidLayoutSubviews];
self.fpsLabel.right = self.view.width;
self.fpsLabel.top = self.tableView.top + self.tableView.contentInset.top;
}


- (void)viewWillDisappear:(BOOL)animated{
printf("------viewWillDisappear---->\n");
[super viewWillDisappear:animated];
[[NIMSDK sharedSDK].mediaManager stopRecord];
[[NIMSDK sharedSDK].mediaManager stopPlay];
}

- (id<NIMSessionConfig>)sessionConfig
{
printf("------sessionConfig---->\n");
if (_sessionConfig == nil) {
printf("------sessionConfig-is-nil-->\n");
_sessionConfig = [[NTESSessionConfig alloc] init];
_sessionConfig.session = self.session;
}
return _sessionConfig;
}

#pragma mark - NIMEventSubscribeManagerDelegate
- (void)onRecvSubscribeEvents:(NSArray *)events
{
printf("------onRecvSubscribeEvents---->\n");
for (NIMSubscribeEvent *event in events) {
if ([event.from isEqualToString:self.session.sessionId]) {
[self refreshSessionSubTitle:[NTESSessionUtil onlineState:self.session.sessionId detail:YES]];
}
}
}
#pragma mark - NIMSystemNotificationManagerDelegate
- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification
{
printf("--->onReceiveCustomSystemNotification------------->\n");
if (!notification.sendToOnlineUsersOnly) {
return;
}
NSData *data = [[notification content] dataUsingEncoding:NSUTF8StringEncoding];
if (data) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
if ([dict jsonInteger:NTESNotifyID] == NTESCommandTyping && self.session.sessionType == NIMSessionTypeP2P && [notification.sender isEqualToString:self.session.sessionId])
{
[self refreshSessionTitle:@"正在输入..."];//haohao
[_titleTimer startTimer:5
delegate:self
repeats:NO];
}
}


}

- (void)onNTESTimerFired:(NTESTimerHolder *)holder
{
printf("--->onNTESTimerFired--->\n");
[self refreshSessionTitle:self.sessionTitle];
}


- (NSString *)sessionTitle
{
printf("--->sessionTitle--->\n");
if ([self.session.sessionId isEqualToString:[NIMSDK sharedSDK].loginManager.currentAccount]) {
return @"我的电脑";
}
return [super sessionTitle];
}

- (NSString *)sessionSubTitle
{
printf("------sessionSubTitle---->\n");
if (self.session.sessionType == NIMSessionTypeP2P && ![self.session.sessionId isEqualToString:[NIMSDK sharedSDK].loginManager.currentAccount]) {
return [NTESSessionUtil onlineState:self.session.sessionId detail:YES];
}
return @"";
}

- (void)onTextChanged:(id)sender
{
printf("hello--->onTextChanged--->\n");
[_notificaionSender sendTypingState:self.session];
}

- (void)onSelectChartlet:(NSString *)chartletId
catalog:(NSString *)catalogId
{
printf("hello--->onSelectChartlet--->\n");
NTESChartletAttachment *attachment = [[NTESChartletAttachment alloc] init];
attachment.chartletId = chartletId;
attachment.chartletCatalog = catalogId;
[self sendMessage:[NTESSessionMsgConverter msgWithChartletAttachment:attachment]];
}


#pragma mark - 石头剪子布
- (void)onTapMediaItemJanKenPon:(NIMMediaItem *)item
{
printf("hello--->onTapMediaItemJanKenPon--->\n");
NTESJanKenPonAttachment *attachment = [[NTESJanKenPonAttachment alloc] init];
attachment.value = arc4random() % 3 + 1;
[self sendMessage:[NTESSessionMsgConverter msgWithJenKenPon:attachment]];
}

#pragma mark - 实时语音
- (void)onTapMediaItemAudioChat:(NIMMediaItem *)item
{
printf("------onTapMediaItemAudioChat---->\n");
if ([self checkRTSCondition]) {
//由于音视频聊天里头有音频和视频聊天界面的切换,直接用present的话页面过渡会不太自然,这里还是用push,然后做出present的效果
NTESAudioChatViewController *vc = [[NTESAudioChatViewController alloc] initWithCallee:self.session.sessionId];
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
self.navigationController.navigationBarHidden = YES;
[self.navigationController pushViewController:vc animated:NO];
}
}

#pragma mark - 视频聊天
- (void)onTapMediaItemVideoChat:(NIMMediaItem *)item
{
printf("------onTapMediaItemVideoChat---->\n");
if ([self checkRTSCondition]) {
//由于音视频聊天里头有音频和视频聊天界面的切换,直接用present的话页面过渡会不太自然,这里还是用push,然后做出present的效果
NTESVideoChatViewController *vc = [[NTESVideoChatViewController alloc] initWithCallee:self.session.sessionId];
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
self.navigationController.navigationBarHidden = YES;
[self.navigationController pushViewController:vc animated:NO];
}
}

#pragma mark - 群组会议
- (void)onTapMediaItemTeamMeeting:(NIMMediaItem *)item
{
printf("------onTapMediaItemTeamMeeting---->\n");
if ([self checkRTSCondition])
{
NIMTeam *team = [[NIMSDK sharedSDK].teamManager teamById:self.session.sessionId];
NSString *currentUserID = [[[NIMSDK sharedSDK] loginManager] currentAccount];
NIMContactTeamMemberSelectConfig *config = [[NIMContactTeamMemberSelectConfig alloc] init];
config.teamId = team.teamId;
config.filterIds = @[currentUserID];
config.needMutiSelected = YES;
config.maxSelectMemberCount = 8;
config.showSelectDetail = YES;
NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config];
__weak typeof(self) weakSelf = self;
vc.finshBlock = ^(NSArray * memeber){
NSString *me = [NIMSDK sharedSDK].loginManager.currentAccount;
NTESTeamMeetingCallerInfo *info = [[NTESTeamMeetingCallerInfo alloc] init];
info.members = [@[me] arrayByAddingObjectsFromArray:memeber];
info.teamId = team.teamId;
NTESTeamMeetingViewController *vc = [[NTESTeamMeetingViewController alloc] initWithCallerInfo:info];
[weakSelf presentViewController:vc animated:NO completion:nil];
};;
[vc show];
}
}


#pragma mark - 文件传输
- (void)onTapMediaItemFileTrans:(NIMMediaItem *)item
{
printf("------onTapMediaItemFileTrans---->\n");
NTESFileTransSelectViewController *vc = [[NTESFileTransSelectViewController alloc]
initWithNibName:nil bundle:nil];
__weak typeof(self) wself = self;
vc.completionBlock = ^void(id sender,NSString *ext){
if ([sender isKindOfClass:[NSString class]]) {
[wself sendMessage:[NTESSessionMsgConverter msgWithFilePath:sender]];
}else if ([sender isKindOfClass:[NSData class]]){
[wself sendMessage:[NTESSessionMsgConverter msgWithFileData:sender extension:ext]];
}
};
[self.navigationController pushViewController:vc animated:YES];
}

#pragma mark - 阅后即焚
- (void)onTapMediaItemSnapChat:(NIMMediaItem *)item
{
printf("------onTapMediaItemSnapChat---->\n");
UIActionSheet *sheet;
BOOL isCamraAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
if (isCamraAvailable) {
sheet = [[UIActionSheet alloc] initWithTitle:@"请选择" delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"从相册中选取",@"拍照",nil];
}else{
sheet = [[UIActionSheet alloc] initWithTitle:@"请选择" delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"从相册中选取",nil];
}
__weak typeof(self) wself = self;
[sheet showInView:self.view completionHandler:^(NSInteger index) {
switch (index) {
case 0:{
//相册
[wself.mediaFetcher fetchPhotoFromLibrary:^(NSArray *images, NSString *path, PHAssetMediaType type){
if (images.count) {
[wself sendSnapchatMessage:images.firstObject];
}
if (path) {
[wself sendSnapchatMessagePath:path];
}
}];

}
break;
case 1:{
//相机
[wself.mediaFetcher fetchMediaFromCamera:^(NSString *path, UIImage *image) {
if (image) {
[wself sendSnapchatMessage:image];
}
}];
}
break;
default:
return;
}
}];
}

- (void)sendSnapchatMessagePath:(NSString *)path
{

printf("---->sendSnapchatMessagePath--->\n");
NTESSnapchatAttachment *attachment = [[NTESSnapchatAttachment alloc] init];
[attachment setImageFilePath:path];
[self sendMessage:[NTESSessionMsgConverter msgWithSnapchatAttachment:attachment]];
}

- (void)sendSnapchatMessage:(UIImage *)image
{
printf("---->sendSnapchatMessage--->\n");
NTESSnapchatAttachment *attachment = [[NTESSnapchatAttachment alloc] init];
[attachment setImage:image];
[self sendMessage:[NTESSessionMsgConverter msgWithSnapchatAttachment:attachment]];
}

#pragma mark - 白板
- (void)onTapMediaItemWhiteBoard:(NIMMediaItem *)item
{
printf("------onTapMediaItemWhiteBoard---->\n");
NTESWhiteboardViewController *vc = [[NTESWhiteboardViewController alloc] initWithSessionID:nil
peerID:self.session.sessionId
types:NIMRTSServiceReliableTransfer | NIMRTSServiceAudio
info:@"白板演示"];
[self presentViewController:vc animated:NO completion:nil];
}


#pragma mark - 提示消息
- (void)onTapMediaItemTip:(NIMMediaItem *)item
{
printf("------onTapMediaItemTip---->\n");
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:nil message:@"输入提醒" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert showAlertWithCompletionHandler:^(NSInteger index) {
switch (index) {
case 1:{
UITextField *textField = [alert textFieldAtIndex:0];
NIMMessage *message = [NTESSessionMsgConverter msgWithTip:textField.text];
[self sendMessage:message];

}
break;
default:
break;
}
}];
}

#pragma mark - 红包
- (void)onTapMediaItemRedPacket:(NIMMediaItem *)item
{
printf("------onTapMediaItemRedPacket---->\n");
[[NTESRedPacketManager sharedManager] sendRedPacket:self.session];
}

#pragma mark - 群已读回执
- (void)onTapMediaItemTeamReceipt:(NIMMediaItem *)item
{
printf("------onTapMediaItemTeamReceipt---->\n");
NTESTeamReceiptSendViewController *vc = [[NTESTeamReceiptSendViewController alloc] initWithSession:self.session];
[self.navigationController pushViewController:vc animated:YES];
}


#pragma mark - 消息发送时间截获
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error
{
printf("sendMessage---->hello hit me!!\n");
// NSString *message_temp = @"aaa";
//message = mytext.text;
// [_webSocket send:message_temp];

[_webSocket send:message.text];


// printf("------->sendMessage--begin----->\n");
NSLog(@"---NTESSessionViewController-->sendMessage----->>>>>>%@",message);
// printf("------->sendMessage--end----->\n");
if (error.code == NIMRemoteErrorCodeInBlackList)
{
//消息打上拉黑拒收标记,方便 UI 显示
message.localExt = @{NTESMessageRefusedTag:@(true)};
[[NIMSDK sharedSDK].conversationManager updateMessage:message forSession:self.session completion:nil];

//插入一条 Tip 提示
NIMMessage *tip = [NTESSessionMsgConverter msgWithTip:@"消息已发送,但对方拒收"];
[[NIMSDK sharedSDK].conversationManager saveMessage:tip forSession:self.session completion:nil];
}
[super sendMessage:message didCompleteWithError:error];
}

#pragma mark - 录音事件
- (void)onRecordFailed:(NSError *)error
{
printf("------onRecordFailed---->\n");
[self.view makeToast:@"录音失败" duration:2 position:CSToastPositionCenter];
}

- (BOOL)recordFileCanBeSend:(NSString *)filepath
{
printf("------recordFileCanBeSend---->\n");
NSURL *URL = [NSURL fileURLWithPath:filepath];
AVURLAsset *urlAsset = [[AVURLAsset alloc]initWithURL:URL options:nil];
CMTime time = urlAsset.duration;
CGFloat mediaLength = CMTimeGetSeconds(time);
return mediaLength > 2;
}

- (void)showRecordFileNotSendReason
{
printf("------showRecordFileNotSendReason---->\n");
[self.view makeToast:@"录音时间太短" duration:0.2f position:CSToastPositionCenter];
}

#pragma mark - Cell事件
- (BOOL)onTapCell:(NIMKitEvent *)event
{
printf("----onTapCell----->\n");
BOOL handled = [super onTapCell:event];
NSString *eventName = event.eventName;
if ([eventName isEqualToString:NIMKitEventNameTapContent])
{
NIMMessage *message = event.messageModel.message;
NSDictionary *actions = [self cellActions];
NSString *value = actions[@(message.messageType)];
if (value) {
SEL selector = NSSelectorFromString(value);
if (selector && [self respondsToSelector:selector]) {
SuppressPerformSelectorLeakWarning([self performSelector:selector withObject:message]);
handled = YES;
}
}
}
else if([eventName isEqualToString:NIMKitEventNameTapLabelLink])
{
NSString *link = event.data;
[self openSafari:link];
handled = YES;
}
else if([eventName isEqualToString:NIMDemoEventNameOpenSnapPicture])
{
NIMCustomObject *object = event.messageModel.message.messageObject;
NTESSnapchatAttachment *attachment = (NTESSnapchatAttachment *)object.attachment;
if(attachment.isFired){
return handled;
}
UIView *sender = event.data;
self.currentSingleSnapView = [NTESGalleryViewController alertSingleSnapViewWithMessage:object.message baseView:sender];
handled = YES;
}
else if([eventName isEqualToString:NIMDemoEventNameCloseSnapPicture])
{
//点击很快的时候可能会触发两次查看,所以这里不管有没有查看过 先强直销毁掉
NIMCustomObject *object = event.messageModel.message.messageObject;
UIView *senderView = event.data;
[senderView dismissPresentedView:YES complete:nil];

NTESSnapchatAttachment *attachment = (NTESSnapchatAttachment *)object.attachment;
if(attachment.isFired){
return handled;
}
attachment.isFired = YES;
NIMMessage *message = object.message;
if ([NTESBundleSetting sharedConfig].autoRemoveSnapMessage) {
[[NIMSDK sharedSDK].conversationManager deleteMessage:message];
[self uiDeleteMessage:message];
}else{
[[NIMSDK sharedSDK].conversationManager updateMessage:message forSession:message.session completion:nil];
[self uiUpdateMessage:message];
}
[[NSFileManager defaultManager] removeItemAtPath:attachment.filepath error:nil];
self.currentSingleSnapView = nil;
handled = YES;
}
else if([eventName isEqualToString:NIMKitEventNameTapRobotLink])
{
NSString *link = event.data;
[self openSafari:link];
handled = YES;
}
else if([eventName isEqualToString:NIMDemoEventNameOpenRedPacket])
{
NIMCustomObject *object = event.messageModel.message.messageObject;
NTESRedPacketAttachment *attachment = (NTESRedPacketAttachment *)object.attachment;
[[NTESRedPacketManager sharedManager] openRedPacket:attachment.redPacketId from:event.messageModel.message.from session:self.session];
handled = YES;
}
else if([eventName isEqualToString:NTESShowRedPacketDetailEvent])
{
NIMCustomObject *object = event.messageModel.message.messageObject;
NTESRedPacketTipAttachment *attachment = (NTESRedPacketTipAttachment *)object.attachment;
[[NTESRedPacketManager sharedManager] showRedPacketDetail:attachment.packetId];
handled = YES;
}
if (!handled) {
NSAssert(0, @"invalid event");
}
return handled;
}

- (BOOL)onTapAvatar:(NIMMessage *)message{
printf("------onTapAvatar---->\n");
NSString *userId = [self messageSendSource:message];
UIViewController *vc = nil;
if ([[NIMSDK sharedSDK].robotManager isValidRobot:userId])
{
vc = [[NTESRobotCardViewController alloc] initWithUserId:userId];
}
else
{
vc = [[NTESPersonalCardViewController alloc] initWithUserId:userId];
}

[self.navigationController pushViewController:vc animated:YES];
return YES;
}


- (BOOL)onLongPressAvatar:(NIMMessage *)message
{
printf("------onLongPressAvatar---->\n");
NSString *userId = [self messageSendSource:message];
if (self.session.sessionType == NIMSessionTypeTeam && ![userId isEqualToString:[NIMSDK sharedSDK].loginManager.currentAccount])
{
NIMKitInfoFetchOption *option = [[NIMKitInfoFetchOption alloc] init];
option.session = self.session;
option.forbidaAlias = YES;

NSString *nick = [[NIMKit sharedKit].provider infoByUser:userId option:option].showName;
NSString *text = [NSString stringWithFormat:@"%@%@%@",NIMInputAtStartChar,nick,NIMInputAtEndChar];

NIMInputAtItem *item = [[NIMInputAtItem alloc] init];
item.uid = userId;
item.name = nick;
[self.sessionInputView.atCache addAtItem:item];

[self.sessionInputView.toolBar insertText:text];
}
return YES;
}

- (BOOL)onPressReadLabel:(NIMMessage *)message
{
printf("------onPressReadLabel---->\n");
if (self.session.sessionType == NIMSessionTypeTeam)
{
NTESTeamReceiptDetailViewController *vc = [[NTESTeamReceiptDetailViewController alloc] initWithMessage:message];
[self.navigationController pushViewController:vc animated:YES];
}
return YES;
}


- (NSString *)messageSendSource:(NIMMessage *)message
{
printf("------messageSendSource---->\n");
NSString *from = nil;
if (message.messageType == NIMMessageTypeRobot)
{
NIMRobotObject *object = (NIMRobotObject *)message.messageObject;
if (object.isFromRobot)
{
from = object.robotId;
}
}
if (!from)
{
from = message.from;
}
return from;
}


#pragma mark - Cell Actions
- (void)showImage:(NIMMessage *)message
{
printf("------showImage---->\n");
NIMImageObject *object = message.messageObject;
NTESGalleryItem *item = [[NTESGalleryItem alloc] init];
item.thumbPath = [object thumbPath];
item.imageURL = [object url];
item.name = [object displayName];
item.itemId = [message messageId];
item.size = [object size];

NIMSession *session = [self isMemberOfClass:[NTESSessionViewController class]]? self.session : nil;

NTESGalleryViewController *vc = [[NTESGalleryViewController alloc] initWithItem:item session:session];
[self.navigationController pushViewController:vc animated:YES];
if(![[NSFileManager defaultManager] fileExistsAtPath:object.thumbPath]){
//如果缩略图下跪了,点进看大图的时候再去下一把缩略图
__weak typeof(self) wself = self;
[[NIMSDK sharedSDK].resourceManager download:object.thumbUrl filepath:object.thumbPath progress:nil completion:^(NSError *error) {
if (!error) {
[wself uiUpdateMessage:message];
}
}];
}
}

- (void)showVideo:(NIMMessage *)message
{
printf("------showVideo---->\n");
NIMVideoObject *object = message.messageObject;
NIMSession *session = [self isMemberOfClass:[NTESSessionViewController class]]? self.session : nil;

NTESVideoViewItem *item = [[NTESVideoViewItem alloc] init];
item.path = object.path;
item.url = object.url;
item.session = session;
item.itemId = object.message.messageId;

NTESVideoViewController *playerViewController = [[NTESVideoViewController alloc] initWithVideoViewItem:item];
[self.navigationController pushViewController:playerViewController animated:YES];
if(![[NSFileManager defaultManager] fileExistsAtPath:object.coverPath]){
//如果封面图下跪了,点进视频的时候再去下一把封面图
__weak typeof(self) wself = self;
[[NIMSDK sharedSDK].resourceManager download:object.coverUrl filepath:object.coverPath progress:nil completion:^(NSError *error) {
if (!error) {
[wself uiUpdateMessage:message];
}
}];
}
}

- (void)showLocation:(NIMMessage *)message
{
printf("------showLocation---->\n");
NIMLocationObject *object = message.messageObject;
NIMKitLocationPoint *locationPoint = [[NIMKitLocationPoint alloc] initWithLocationObject:object];
NIMLocationViewController *vc = [[NIMLocationViewController alloc] initWithLocationPoint:locationPoint];
[self.navigationController pushViewController:vc animated:YES];
}

- (void)showFile:(NIMMessage *)message
{
printf("------showFile---->\n");
NIMFileObject *object = message.messageObject;
NTESFilePreViewController *vc = [[NTESFilePreViewController alloc] initWithFileObject:object];
[self.navigationController pushViewController:vc animated:YES];
}

- (void)showCustom:(NIMMessage *)message
{
printf("------showCustom-|haohao|--->\n");
//普通的自定义消息点击事件可以在这里做哦~
}

- (void)openSafari:(NSString *)link
{
printf("------openSafari---->\n");
NSURLComponents *components = [[NSURLComponents alloc] initWithString:link];
if (components)
{
if (!components.scheme)
{
//默认添加 http
components.scheme = @"http";
}
[[UIApplication sharedApplication] openURL:[components URL]];
}
}


#pragma mark - 导航按钮
- (void)enterPersonInfoCard:(id)sender{
printf("------enterPersonInfoCard---->\n");
NTESSessionCardViewController *vc = [[NTESSessionCardViewController alloc] initWithSession:self.session];
[self.navigationController pushViewController:vc animated:YES];
}

- (void)enterRobotInfoCard:(id)sender{
printf("------enterRobotInfoCard---->\n");
NTESRobotCardViewController *vc = [[NTESRobotCardViewController alloc] initWithUserId:self.session.sessionId];
[self.navigationController pushViewController:vc animated:YES];
}

- (void)enterHistory:(id)sender{
printf("------enterHistory---->\n");

[self.view endEditing:YES];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"选择操作" delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"云消息记录",@"搜索本地消息记录",@"清空本地聊天记录", nil];
[sheet showInView:self.view completionHandler:^(NSInteger index) {
switch (index) {
case 0:{ //查看云端消息
NTESSessionRemoteHistoryViewController *vc = [[NTESSessionRemoteHistoryViewController alloc] initWithSession:self.session];
[self.navigationController pushViewController:vc animated:YES];
break;
}
case 1:{ //搜索本地消息
NTESSessionLocalHistoryViewController *vc = [[NTESSessionLocalHistoryViewController alloc] initWithSession:self.session];
[self.navigationController pushViewController:vc animated:YES];
break;
}
case 2:{ //清空聊天记录
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"确定清空聊天记录?" delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:nil, nil];
__weak UIActionSheet *wSheet;
[sheet showInView:self.view completionHandler:^(NSInteger index) {
if (index == wSheet.destructiveButtonIndex) {
BOOL removeRecentSession = [NTESBundleSetting sharedConfig].removeSessionWhenDeleteMessages;
BOOL removeTable = [NTESBundleSetting sharedConfig].dropTableWhenDeleteMessages;
NIMDeleteMessagesOption *option = [[NIMDeleteMessagesOption alloc] init];
option.removeSession = removeRecentSession;
option.removeTable = removeTable;
[[NIMSDK sharedSDK].conversationManager deleteAllmessagesInSession:self.session
option:option];
}
}];
break;
}
default:
break;
}
}];
}

- (void)enterTeamCard:(id)sender{
printf("------enterTeamCard---->\n");
NIMTeam *team = [[NIMSDK sharedSDK].teamManager teamById:self.session.sessionId];
UIViewController *vc;
if (team.type == NIMTeamTypeNormal) {
vc = [[NIMNormalTeamCardViewController alloc] initWithTeam:team];
}else if(team.type == NIMTeamTypeAdvanced){
vc = [[NIMAdvancedTeamCardViewController alloc] initWithTeam:team];
}
[self.navigationController pushViewController:vc animated:YES];
}

#pragma mark - 菜单
- (NSArray *)menusItems:(NIMMessage *)message
{
printf("------menusItems---->\n");
NSMutableArray *items = [NSMutableArray array];
NSArray *defaultItems = [super menusItems:message];
if (defaultItems) {
[items addObjectsFromArray:defaultItems];
}

if ([NTESSessionUtil canMessageBeForwarded:message]) {
[items addObject:[[UIMenuItem alloc] initWithTitle:@"转发" action:@selector(forwardMessage:)]];
}

if ([NTESSessionUtil canMessageBeRevoked:message]) {
[items addObject:[[UIMenuItem alloc] initWithTitle:@"撤回" action:@selector(revokeMessage:)]];
}

if (message.messageType == NIMMessageTypeAudio) {
[items addObject:[[UIMenuItem alloc] initWithTitle:@"转文字" action:@selector(audio2Text:)]];
}

return items;

}

- (void)audio2Text:(id)sender
{//haohao
printf("------audio2Text------>\n");
NIMMessage *message = [self messageForMenu];
__weak typeof(self) wself = self;
NTESAudio2TextViewController *vc = [[NTESAudio2TextViewController alloc] initWithMessage:message];
vc.completeHandler = ^(void){
[wself uiUpdateMessage:message];
};
[self presentViewController:vc
animated:YES
completion:nil];
}


- (void)forwardMessage:(id)sender
{
printf("---->forwardMessage---->\n");
NIMMessage *message = [self messageForMenu];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"选择会话类型" delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"个人",@"群组", nil];
__weak typeof(self) weakSelf = self;
message.setting.teamReceiptEnabled = NO;
[sheet showInView:self.view completionHandler:^(NSInteger index) {
switch (index) {
case 0:{
NIMContactFriendSelectConfig *config = [[NIMContactFriendSelectConfig alloc] init];
config.needMutiSelected = NO;
NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config];
vc.finshBlock = ^(NSArray *array){
NSString *userId = array.firstObject;
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
[weakSelf forwardMessage:message toSession:session];
};
[vc show];
}
break;
case 1:{
NIMContactTeamSelectConfig *config = [[NIMContactTeamSelectConfig alloc] init];
NIMContactSelectViewController *vc = [[NIMContactSelectViewController alloc] initWithConfig:config];
vc.finshBlock = ^(NSArray *array){
NSString *teamId = array.firstObject;
NIMSession *session = [NIMSession session:teamId type:NIMSessionTypeTeam];
[weakSelf forwardMessage:message toSession:session];
};
[vc show];
}
break;
case 2:
break;
default:
break;
}
}];
}


- (void)revokeMessage:(id)sender
{
printf("---------revokeMessage---->\n");
NIMMessage *message = [self messageForMenu];
__weak typeof(self) weakSelf = self;
[[NIMSDK sharedSDK].chatManager revokeMessage:message completion:^(NSError * _Nullable error) {
if (error) {
if (error.code == NIMRemoteErrorCodeDomainExpireOld) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"发送时间超过2分钟的消息,不能被撤回" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}else{
DDLogError(@"revoke message eror code %zd",error.code);
[weakSelf.view makeToast:@"消息撤回失败,请重试" duration:2.0 position:CSToastPositionCenter];
}
}
else
{
NIMMessageModel *model = [self uiDeleteMessage:message];
NIMMessage *tip = [NTESSessionMsgConverter msgWithTip:[NTESSessionUtil tipOnMessageRevoked:nil]];
tip.timestamp = model.messageTime;
[self uiInsertMessages:@[tip]];

tip.timestamp = message.timestamp;
// saveMessage 方法执行成功后会触发 onRecvMessages: 回调,但是这个回调上来的 NIMMessage 时间为服务器时间,和界面上的时间有一定出入,所以要提前先在界面上插入一个和被删消息的界面时间相符的 Tip, 当触发 onRecvMessages: 回调时,组件判断这条消息已经被插入过了,就会忽略掉。
[[NIMSDK sharedSDK].conversationManager saveMessage:tip forSession:message.session completion:nil];
}
}];
}

- (void)forwardMessage:(NIMMessage *)message toSession:(NIMSession *)session
{
printf("---->forwardMessage--->\n");
NSString *name;
if (session.sessionType == NIMSessionTypeP2P)
{
NIMKitInfoFetchOption *option = [[NIMKitInfoFetchOption alloc] init];
option.session = session;
name = [[NIMKit sharedKit] infoByUser:session.sessionId option:option].showName;
}
else
{
name = [[NIMKit sharedKit] infoByTeam:session.sessionId option:nil].showName;
}
NSString *tip = [NSString stringWithFormat:@"确认转发给 %@ ?",name];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"确认转发" message:tip delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"确认", nil];

__weak typeof(self) weakSelf = self;
[alert showAlertWithCompletionHandler:^(NSInteger index) {
if(index == 1)
{
if (message.messageType == NIMMessageTypeRobot)
{
NIMMessage *forwardMessage = [NTESSessionMsgConverter msgWithText:message.text];
[[NIMSDK sharedSDK].chatManager sendMessage:forwardMessage toSession:session error:nil];
}
else
{
[[NIMSDK sharedSDK].chatManager forwardMessage:message toSession:session error:nil];
}
[weakSelf.view makeToast:@"已发送" duration:2.0 position:CSToastPositionCenter];
}
}];
}

#pragma mark - 辅助方法
- (void)sendImageMessagePath:(NSString *)path
{

printf("------sendImageMessagePath---->\n");
[self sendSnapchatMessagePath:path];
}


- (BOOL)checkRTSCondition
{
printf("------checkRTSCondition---->\n");
BOOL result = YES;

if (![[Reachability reachabilityForInternetConnection] isReachable])
{
[self.view makeToast:@"请检查网络" duration:2.0 position:CSToastPositionCenter];
result = NO;
}
NSString *currentAccount = [[NIMSDK sharedSDK].loginManager currentAccount];
if (self.session.sessionType == NIMSessionTypeP2P && [currentAccount isEqualToString:self.session.sessionId])
{
[self.view makeToast:@"不能和自己通话哦" duration:2.0 position:CSToastPositionCenter];
result = NO;
}
if (self.session.sessionType == NIMSessionTypeTeam)
{
NIMTeam *team = [[NIMSDK sharedSDK].teamManager teamById:self.session.sessionId];
NSInteger memberNumber = team.memberNumber;
if (memberNumber < 2)
{
[self.view makeToast:@"无法发起,群人数少于2人" duration:2.0 position:CSToastPositionCenter];
result = NO;
}
}
return result;
}

- (NSDictionary *)cellActions
{
printf("------cellActions---->\n");
static NSDictionary *actions = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
actions = @{@(NIMMessageTypeImage) : @"showImage:",
@(NIMMessageTypeVideo) : @"showVideo:",
@(NIMMessageTypeLocation) : @"showLocation:",
@(NIMMessageTypeFile) : @"showFile:",
@(NIMMessageTypeCustom): @"showCustom:"};
});
return actions;
}

- (NIMKitMediaFetcher *)mediaFetcher
{
printf("------mediaFetcher---->\n");
if (!_mediaFetcher) {
_mediaFetcher = [[NIMKitMediaFetcher alloc] init];
_mediaFetcher.limit = 1;
_mediaFetcher.mediaTypes = @[(NSString *)kUTTypeImage];;;
}
return _mediaFetcher;
}

- (void)setUpNav{
printf("------setUpNav---->\n");
UIButton *enterTeamCard = [UIButton buttonWithType:UIButtonTypeCustom];
[enterTeamCard addTarget:self action:@selector(enterTeamCard:) forControlEvents:UIControlEventTouchUpInside];
[enterTeamCard setImage:[UIImage imageNamed:@"icon_session_info_normal"] forState:UIControlStateNormal];
[enterTeamCard setImage:[UIImage imageNamed:@"icon_session_info_pressed"] forState:UIControlStateHighlighted];
[enterTeamCard sizeToFit];
UIBarButtonItem *enterTeamCardItem = [[UIBarButtonItem alloc] initWithCustomView:enterTeamCard];

UIButton *infoBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[infoBtn addTarget:self action:@selector(enterPersonInfoCard:) forControlEvents:UIControlEventTouchUpInside];
[infoBtn setImage:[UIImage imageNamed:@"icon_session_info_normal"] forState:UIControlStateNormal];
[infoBtn setImage:[UIImage imageNamed:@"icon_session_info_pressed"] forState:UIControlStateHighlighted];
[infoBtn sizeToFit];
UIBarButtonItem *enterUInfoItem = [[UIBarButtonItem alloc] initWithCustomView:infoBtn];

UIButton *historyBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[historyBtn addTarget:self action:@selector(enterHistory:) forControlEvents:UIControlEventTouchUpInside];
[historyBtn setImage:[UIImage imageNamed:@"icon_history_normal"] forState:UIControlStateNormal];
[historyBtn setImage:[UIImage imageNamed:@"icon_history_pressed"] forState:UIControlStateHighlighted];
[historyBtn sizeToFit];
UIBarButtonItem *historyButtonItem = [[UIBarButtonItem alloc] initWithCustomView:historyBtn];


UIButton *robotInfoBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[robotInfoBtn addTarget:self action:@selector(enterRobotInfoCard:) forControlEvents:UIControlEventTouchUpInside];
[robotInfoBtn setImage:[UIImage imageNamed:@"icon_robot_card_normal"] forState:UIControlStateNormal];
[robotInfoBtn setImage:[UIImage imageNamed:@"icon_robot_card_pressed"] forState:UIControlStateHighlighted];
[robotInfoBtn sizeToFit];
UIBarButtonItem *robotInfoButtonItem = [[UIBarButtonItem alloc] initWithCustomView:robotInfoBtn];


if (self.session.sessionType == NIMSessionTypeTeam)
{
self.navigationItem.rightBarButtonItems = @[enterTeamCardItem,historyButtonItem];
}
else if(self.session.sessionType == NIMSessionTypeP2P)
{
if ([self.session.sessionId isEqualToString:[[NIMSDK sharedSDK].loginManager currentAccount]])
{
self.navigationItem.rightBarButtonItems = @[historyButtonItem];
}
else if([[NIMSDK sharedSDK].robotManager isValidRobot:self.session.sessionId])
{
self.navigationItem.rightBarButtonItems = @[historyButtonItem,robotInfoButtonItem];
}
else
{
self.navigationItem.rightBarButtonItems = @[enterUInfoItem,historyButtonItem];
}
}
}

- (BOOL)shouldAutorotate{
printf("------shouldAutorotate---->\n");
return !self.currentSingleSnapView;
}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message_old {
NSLog(@"Received --haha---->>>>>>>>>>%@ \n",message_old);
printf("---->onRecvMessages--->\n");//haohao
// if ([self shouldAddListenerForNewMsg])
// {
NIMMessage *message = [[NIMMessage alloc] init];
// [message setMessageExt:@"7b468318-4c8a-47c6-ac09-81c96bf73324"];
// [message setText:@"可以吧,从新的协议来的"];
[message setText:message_old];
NSArray *messages_new =[[NSArray alloc] initWithObjects:message, nil];

NSLog(@"array:%@",messages_new.debugDescription);//haohao
NSLog(@"one:%@",[messages_new objectAtIndex:0]);//haohao
[self uiAddMessages:messages_new];
//[super.interactor markRead];
// }

}

- (void)didFetchMessageData {

}

- (void)didPullUpMessageData {

}

- (void)didRefreshMessageData {

}

- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {

}

- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection {

}

- (void)preferredContentSizeDidChangeForChildContentContainer:(nonnull id<UIContentContainer>)container {

}


- (void)systemLayoutFittingSizeDidChangeForChildContentContainer:(nonnull id<UIContentContainer>)container {

}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator {

}

- (void)willTransitionToTraitCollection:(nonnull UITraitCollection *)newCollection withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator {

}

- (void)didUpdateFocusInContext:(nonnull UIFocusUpdateContext *)context withAnimationCoordinator:(nonnull UIFocusAnimationCoordinator *)coordinator {

}

- (void)setNeedsFocusUpdate {

}


- (void)updateFocusIfNeeded {

}

@end




效果
[img]http://dl2.iteye.com/upload/attachment/0129/4408/83d44513-61ac-31cf-bfd9-2a743357ba2e.png[/img]
iOS移动端开发中的WebRTC集成指南 在iOS移动端开发中,集成WebRTC可以让应用程序实现实时音视频通话的功能。本文将介绍如何在iOS应用中集成WebRTC,并提供相应的源代码示例。请注意,WebRTC是一个广泛而复杂的主题,本文只涵盖了基本集成步骤。首先,我们导入了WebRTC库,并设置了项目的权限。首先,创建一个新的iOS项目或打开现有的项目。注意:以上代码仅为示例,实际的WebRTC集成可能涉及更多复杂的设置和逻辑,例如信令服务器的使用、音频处理、数据通道等。然后,我们创建了一个。中,并创建了一个远程视频视图来显示远程用户的视频流。 阅读详情

相关推荐

iOS WebRTC 点对点实时音视频流程详解

在Xcode中,选择您的工程目录,然后选择"General"选项卡,向下滚动到"Frameworks, Libraries, and Embedded Content"部分,点击"+“按钮,选择"Add Other…WebRTC(Web实时通信)是一种用于浏览器和移动应用程序的开放式实时通信技术,它允许开发者在不需要插件或第三方软件的情况下,直接在浏览器或移动应用中实现点对点的音视频通信。在本文中,我们将详细介绍在iOS移动端开发中使用WebRTC实现点对点实时音视频通信的流程,并提供相应的源代码。

GexObjectivec的博客 527

WebRTC 在 iOS 端实现一对一通信

WebRTC 在 iOS 端实现一对一通信

ProgramNovice的博客 3334

在iOS上构建WebRTC

在弹出的对话框中,导航到刚才解压的"webrtc"文件夹,并选择其中的"src"文件夹。在"Frameworks, Libraries, and Embedded Content"部分,确保"WebRTC.framework"的"Embed"选项设置为"Embed & Sign"。选择"App"作为项目模板,并点击"Next"。在弹出的对话框中,导航到刚才添加的"webrtc"文件夹,并选择其中的"src"文件夹。在弹出的对话框中,选择"Create groups"选项,并点击"Add"。

UnhcTransforms的博客 357

IOS开发之——does not support the Push Notifications

一 现象 导入友盟分享,运行到真机设备时,出现了如下异常 Code Signing Error: Cannot create a iOS App Development provisioning profile for "com.umeng.UMComDemo". Personal development teams, including "user", do not support the Push Notifications capability. 二 原因 友盟项目,因为其开启了通知, 但是我们的

我的博客 4750

ABAP BOM展开避坑指南:CS_BOM_EXPL_MAT_V2函数参数配置详解

本文深入解析了SAP ABAP开发中用于物料清单展开的核心函数CS_BOM_EXPL_MAT_V2。针对其复杂的参数配置,如CAPID、STLAN、DATUV和MEHRS,提供了详细的避坑指南和最佳实践,帮助开发者避免数据错误与性能陷阱,实现高效、准确的BOM多层展开。

pea55的博客 854

ESP32-S3开发环境避坑指南:VS Code+ESP-IDF离线安装全流程(附国内镜像加速)

本文提供了一份详细的ESP32-S3开发环境离线安装指南,重点解决网络依赖问题。通过整合国内镜像加速,手把手教你完成VS Code、ESP-IDF框架、工具链及Python依赖的本地化部署,实现稳定、可重复的开发环境搭建,大幅提升IoT开发效率。

peach的博客 961

基于Facebook开源框架SocketRocket的即时通讯

  SocketRocket 介绍:   SocketRock 是 Facebook 开源的框架,基于 WebSocket 客户端类库,适用于 iOS、Mac OS、tv OS。GitHub 传送门:https://github.com/facebook/SocketRocket   安装:pod 'SocketRocket'   也可以拖入文件SocketRocket:   ...

436

Win10系统内存占用异常飙升?三步排查法快速定位问题根源

本文针对Win10系统内存占用异常飙升问题,提供了一套三步排查法。首先利用任务管理器和资源监视器进行深度系统体检,定位隐形内存消耗者;其次通过干净启动和禁用非必要后台服务,揪出导致内存泄漏的第三方软件或驱动;最后进行终极深度清理,包括检查内存完整性、调整虚拟内存设置以及更新关键驱动程序,帮助用户快速恢复系统流畅运行。

weixin_29251567的博客 195

iOS基于WebSocket聊天机制(主要运用Facebook第三方SocketRocket)

1、WebSocket 机制 以下简要介绍一下 WebSocket 的原理及运行机制。 WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是: WebSocket 是一种双向通信协议,在建立连接后,WebSocke

dangpf520的博客 4232

P+F--r2000激光雷达slam技术实现

P+F--r2000激光雷达slam技术实现

majingming123的博客 1667

【工具】GitHub学生认证+PyCharm配置Copilot全流程指南

本文提供了一份详细的GitHub学生认证及在PyCharm中配置Copilot的完整指南。通过完成A2F认证、准备有效材料并使用干净网络环境,学生可免费获取GitHub Copilot Pro订阅,极大提升编程学习与开发效率。

w7x8y9z的博客 1457

websocket 学习SocketRocket开源库(三)

http://websocketstest.com/ 打开网页可以查看当前的环境是否支持websocket协议 采用的第三方库:https://github.com/facebook/SocketRocket git下载地址:square/SocketRocket 下载解压文件打开SocketRocket文件夹 E18C88E4-8586-429B-8B69-FC7FE927...

binglan520的专栏 2292

【专栏导引贴】100+智能优化算法:从背景原理到代码实战(持续更新)

本专栏系统整理100+种现代优化算法,涵盖粒子群优化(PSO)、遗传算法(GA)、鲸鱼优化(WOA)等经典方法,以及白鲸优化(BWO)、非洲秃鹫优化(AVOA)等新兴算法。每篇详解包含生物启发原理、数学模型、代码实现及工程应用,采用统一编程风格,提供可直接运行的实例代码。专栏持续更新,旨在为研究者提供系统化的智能优化算法参考资料,实现从理论到实践的完整知识链。目前已收录23种算法,包括蚁群系统(ACS)、蝙蝠算法(BA)、天牛须搜索(BAS)等自然启发式优化方法。

qq_42212808的博客 3652

SocketRocket --- iOS使用篇

开篇语: 很久以前使用的即时通讯工具SocketIO,由于其对websocket进行了深度的封装,它的协议已经变得很复杂,对于大多数开源的Java服务器代码是不兼容的。so,还是回归最原汁原味的websocket类库:SocketRocket 吧! 这个库由Facebook公司开源,可靠性还是有保障的。最近发布的版本是0.5.1,可以通过cocoapods安装。但是,未发布的代码显示,新的文件...

学习小使者 的专栏 9253

3 ATK2(AUTOSAR OS)代码移植-目标硬件及编译环境简介

该部分介绍ATK2代码移植的目标硬件以及编译环境

xiaoduanduansad的博客 718

提示工程从初级到高级:如何评估提示词的鲁棒性?架构师分享测试方法

鲁棒性(Robustness)原本是工程领域的概念,指系统在“非理想条件”下保持性能稳定的能力。输入鲁棒性:面对不规范、有噪音、格式变异的用户输入,提示能否引导模型输出正确结果?模型鲁棒性:同一提示在不同大模型(或同一模型的不同版本)下,输出是否一致?场景鲁棒性:在边界场景(极端case、歧义case、多任务混合)下,提示能否保持逻辑一致性?提示词V1:请将以下用户评论分类为「正面」「中性」或「负面」:{comment}。要求:输出唯一类别,不要额外说明。

小程序开发 496

SocketRocket实现即时通讯

1.可在github上下载,包含了demo和测试地址 https://github.com/facebook/SocketRocket2.遇到的BUG:Connection Failed:Error Domain=SRWebSocketErrorDomain Code=2133 "Invalid Sec-WebSocket-Accept response." UserInfo={NSLocaliz

jacob_ios的博客 5356

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

SocketRocket详解:iOS/macOS/tvOS平台最完整WebSocket客户端库

你还在为移动应用实时通信功能开发烦恼吗?连接不稳定、数据传输延迟、跨平台兼容性差?SocketRocket——这款Facebook开源的WebSocket(套接字)客户端库,将彻底解决你的这些痛点。本文将带你全面了解SocketRocket,掌握其安装配置、核心功能及实战应用,让你轻松实现iOS、macOS和tvOS平台的高效实时通信。 ## 为什么选择SocketRocket? Socket...

gitblog_00475的博客 781

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

SocketRocket详解:iOS/macOS/tvOS最佳WebSocket客户端库实战指南

你是否还在为移动端实时通信功能开发烦恼?Socket(套接字)连接不稳定、证书验证复杂、多平台适配困难?本文将系统介绍SocketRocket——这款由Facebook开源的高性能WebSocket(Web套接字)客户端库,通过实战案例带你掌握iOS/macOS/tvOS平台的实时通信实现方案。读完本文你将获得:SocketRocket核心功能解析、完整集成流程、常见问题解决方案以及性能优化技巧。...

gitblog_00698的博客 912

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

iOS进阶2 -- CocoaAsyncSocket和Websocket框架使用

一、CocoaAsyncSocket部分 本部分转自:http://www.jianshu.com/p/68100d518468 客户端代码地址:https://github.com/edwardGG/SocketClient 服务端代码地址:https://github.com/edwardGG/SocketServer直接看代码:1.客户端代码#import "ViewController

DC_Even的博客 3331

iOS 实现webSocket

闲扯 原文 :http://www.cnblogs.com/oc-bowen/p/6019090.html Facebook 源码地址 :https://github.com/facebook/SocketRocket 今天一个APP需要接websocket了,然后便找到了facebook的 SocketRocket 框架,然后用了一天时间接上了,完成了掉线自动重连,自动重登录,心...

gcs的博客 753

webSocket通讯

1、使用facebook第三方SRWebSocket进行websocket通讯。   pod 'SocketRocket' 2、通讯地址:   ws://192.168.1.128:18882/ws   注意:socket通讯都是用ws开头的 3、初始化   _webSocket = [[SRWebSocketalloc] initWithURL:[NSURLURLWithStr...

weixin_30896511的博客 172

接入WebSocket

WebSocket 以前没用过,之前写过一篇博客是基于原生socket的(查看)比较复杂,慎入。今天另外一个APP需要接websocket了,然后便找到了facebook的 SocketRocket 框架,然后用了一天时间接上了,完成了掉线自动重连,自动重登录,心跳等等功能,用法比原生socket简单(原生socket基于TCP/UDP协议)。为什么用 WebSocket因为APP里面有个聊天功能...

科技区软件类AI博主 🔍 专注 AI 工具测评 / 前沿产品深度拆解 / 行业趋势预判 🚫 拒绝科技玄学,只讲人话干货 —— 从工具使用到商业落地,搭建可复用的 AI 应用框架 80

如何快速掌握SocketRocket跨平台开发:iOS、macOS、tvOS实战指南

SocketRocket是一个完全符合WebSocket RFC 6455标准的Objective-C客户端库,专为iOS、macOS和tvOS平台设计,让你轻松实现跨平台实时通信功能。无论你是开发聊天应用、实时数据推送还是多人协作工具,SocketRocket都能提供稳定高效的WebSocket连接支持。 ## 🎯 为什么选择SocketRocket进行跨平台开发? 在移动应用和桌面应用开

gitblog_00502的博客 471

SocketRocket终极指南:iOS、macOS、tvOS全平台WebSocket开发实战

SocketRocket是一个完全符合WebSocket RFC 6455标准的Objective-C客户端库,专为Apple生态系统打造。无论是iOS应用、macOS桌面程序还是tvOS电视应用,SocketRocket都能提供稳定高效的实时通信能力。作为Facebook开源的高质量项目,它已经通过了Autobahn测试套件的300多项严格测试,性能表现卓越。 ## 🚀 为什么选择Socke

gitblog_00028的博客 571
上一篇: emscripten asm.js的helloworld
下一篇: openresty websocket
linux内核控
博客等级 码龄19年 41粉丝 638原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值