問(wèn)題原因是有個(gè)點(diǎn)差列表的界面,前期是自己socket工具封裝自己代碼的失誤,造成數(shù)據(jù)源data不斷追加,比較專業(yè)的行情數(shù)據(jù),都會(huì)定義規(guī)范的結(jié)構(gòu)體,會(huì)返回當(dāng)前數(shù)據(jù)包的長(zhǎng)度,次數(shù)在于數(shù)據(jù)處理時(shí)可以處理一部分拋除一部分,但是本人實(shí)際項(xiàng)目中只是簡(jiǎn)單地返回的字符串的data數(shù)據(jù),這樣就算socket斷包,我們也不方便處理,所以就簡(jiǎn)單地每次只處理接受的數(shù)據(jù),(更合理的應(yīng)該是用nsmutabledata不斷的追加拼接數(shù)據(jù),然后解包根據(jù)包頭返回的實(shí)際內(nèi)容的長(zhǎng)度截取處理)
然后由于此列表 (交易商數(shù)*對(duì)應(yīng)的交易品種)比較多,從而造成數(shù)據(jù)變化特別頻繁,從而造成刷新列表的卡頓
主要修改的幾個(gè)地方:
1.主推頻繁,然后每次主推里邊有循環(huán)處理數(shù)據(jù),所以此處將數(shù)據(jù)處理放在了子線程中,數(shù)據(jù)處理好之后用代理或者block返回時(shí)拉回主線程
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
// LOG(@".net行情數(shù)據(jù)~~~~~");
// if(self.socketData == nil){
// self.socketData = [[NSData alloc] init];
// }
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if ([dataStr containsString:@"Heart"]) {
// LOG(@"心跳正常");
}else{
// NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// LOG(@"~~~點(diǎn)差數(shù)據(jù):%@",str);
self.socketData = [NSData dataWithData:data];
}
//常用方式異步并發(fā)+與主線程交互
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//耗時(shí)長(zhǎng)的操作
[self dealWithSocketData];//處理數(shù)據(jù)
[self.socket readDataWithTimeout:10 tag:tag];
});
}
-(void)dealWithSocketData{
if (![_socketData isKindOfClass:[NSData class]]) {
return;
}
if (_socketData.length > 2) {
NSString *dataStr = [[NSString alloc] initWithData:self.socketData encoding:NSUTF8StringEncoding];
NSArray *strArr = [dataStr componentsSeparatedByString:@"#"];
NSMutableArray *strMarry = [NSMutableArray arrayWithArray:strArr];
[strMarry removeLastObject];
NSString *str = strArr[0];
NSString *typeStr = @"";
if (str.length > 2) {
typeStr = [str substringToIndex:2];
}
if (![typeStr isEqualToString:@"01"] && ![typeStr isEqualToString:@"02"]) {
[strMarry removeObjectAtIndex:0];
}
str = strMarry[0];
typeStr = [str substringToIndex:2];
strArr = [NSArray arrayWithArray:strMarry];
if ([typeStr isEqualToString:@"01"]) {
//數(shù)據(jù)格式 點(diǎn)差 點(diǎn)差類型(01)袋倔,交易商Code劫映,品名什燕,點(diǎn)差
// 01,000001674566,EURUSD,2.0
NSMutableArray *xlSocketModelMArr = [NSMutableArray arrayWithCapacity:1];
for (NSString *singleStr in strArr) {
if (singleStr.length > 0) {
NSArray *valuesArr = [singleStr componentsSeparatedByString:@","];
NSString *type = valuesArr[0];
if ([type isEqualToString:@"01"]) {
XLSocketModel *model = [XLSocketModel new];
if (valuesArr.count > 2) {
model.n = valuesArr[2];
}
//此處修改邏輯 2017.12.14 只要符合的三個(gè)點(diǎn)差
if ([model.n isEqualToString:@"EURUSD"] || [model.n isEqualToString:@"XAUUSD"] || [model.n isEqualToString:@"OILUSD"]) {
if (valuesArr.count > 1) {
model.traderCode = valuesArr[1];
}
if (valuesArr.count > 3) {
model.spread = valuesArr[3];
}
[xlSocketModelMArr addObject:model];
// LOG(@"~~~點(diǎn)差數(shù)據(jù):%li~~",xlSocketModelMArr.count);
}else{
continue;
}
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
//主線程界面刷新
if (self.allTraderSpreadDataBlock) {
self.allTraderSpreadDataBlock(xlSocketModelMArr);
}
if (self.singleTraderCodeSpreadDataBlock) {
self.singleTraderCodeSpreadDataBlock(xlSocketModelMArr);
}
});
}else if ([typeStr isEqualToString:@"02"]){
//數(shù)據(jù)格式 行情 行情類型(02)例证,交易商Code,品名涕蜂,買入價(jià)析校,賣出價(jià),點(diǎn)差
// 02,000001674566长酗,EURUSD,2.1345,3.12344,28
NSMutableArray *xlSocketModelMArr = [NSMutableArray arrayWithCapacity:1];
for (NSString *singleStr in strArr) {
if (singleStr.length > 0) {
NSArray *valuesArr = [singleStr componentsSeparatedByString:@","];
NSString *type = valuesArr[0];
if ([type isEqualToString:@"02"]) {
XLSocketModel *model = [XLSocketModel new];
model.traderCode = valuesArr[1];
model.n = valuesArr[2];
model.bid = valuesArr[3];
model.sel = valuesArr[4];
model.spread = valuesArr[5];
[xlSocketModelMArr addObject:model];
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
//主線程界面刷新
if (self.singleTraderMarketDataBlock) {
self.singleTraderMarketDataBlock(xlSocketModelMArr);
}
});
}
}
}
2.限制刷新頻率+只刷新界面上的cell
(1) kPreventRepeatClickTime(0.5);//限制刷新頻率,引起卡頓的問(wèn)題是刷新頻率太快,此處硬代碼處理
// 防止多次調(diào)用
#define kPreventRepeatClickTime(_seconds_) \
static BOOL shouldPrevent; \
if (shouldPrevent) return; \
shouldPrevent = YES; \
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((_seconds_) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ \
shouldPrevent = NO; \
}); \
(2)MessageThrottle,限流控制刷新頻率,參考http://www.reibang.com/p/5dacd8778a5a
-(void)reloadTableViewData{
//(1.)限制刷新頻率,引起卡頓的問(wèn)題是刷新頻率太快,此處硬代碼處理
kPreventRepeatClickTime(0.5);
//(2.)限制刷新的頻率 xinle
[self mt_limitSelector:@selector(tableViewReloadData) oncePerDuration:(0.10)];
if (_isAllowRefresh) {
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *cells = [self.tableView indexPathsForVisibleRows];//取出當(dāng)前界面上的cell
if (cells.count > 0 && self.dataArr.count > 0 && self.dataArr.count >= cells.count) {
//主線程界面刷新
[self.tableView reloadRowsAtIndexPaths:cells withRowAnimation:(UITableViewRowAnimationNone)];
// LOG(@"~~~reloadRowsAtIndexPaths~~~");
}
});
}
}
3.設(shè)置開關(guān),當(dāng)列表拖動(dòng)的時(shí)候不刷新
//開始拖動(dòng)時(shí)禁止刷新
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if ([scrollView class] == [self.tableView class]) {
self.isAllowRefresh = 0;
}
}
//減速完畢
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if ([scrollView class] == [self.tableView class]) {
self.isAllowRefresh = 1;
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if ([scrollView class] == [self.tableView class]) {
if (!decelerate) {
self.isAllowRefresh = 1;
}
[self getAllTraderSPread];
}
}
tableview刷新可以考慮cell通知監(jiān)聽單刷,不用整個(gè)tableview整體刷新