|  | @@ -9,6 +9,7 @@
 | 
	
		
			
				|  |  |  #import "TXClassroomVideoListView.h"
 | 
	
		
			
				|  |  |  #import "TXClassroomVideoListCell.h"
 | 
	
		
			
				|  |  |  #import "ClassroomService.h"
 | 
	
		
			
				|  |  | +#import "KSIndexPathValidator.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @interface TXClassroomVideoListView ()<UITableViewDelegate,UITableViewDataSource>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -43,10 +44,15 @@
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)getDataSource {
 | 
	
		
			
				|  |  | +    __weak typeof(self) weakSelf = self;
 | 
	
		
			
				|  |  |      dispatch_async(self.videoListQueue, ^{
 | 
	
		
			
				|  |  | -        MJ_LOCK(self.signalSemaphore);
 | 
	
		
			
				|  |  | +        __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +        if (!strongSelf) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        MJ_LOCK(self.signalSemaphore)
 | 
	
		
			
				|  |  |          NSArray *tempArray = [ClassroomService sharedService].currentRoom.memberList;
 | 
	
		
			
				|  |  |          if (tempArray.count <= 0) {
 | 
	
		
			
				|  |  | +            MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  |              return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          NSSortDescriptor * des = [[NSSortDescriptor alloc] initWithKey:@"joinTime" ascending:YES];
 | 
	
	
		
			
				|  | @@ -93,80 +99,142 @@
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  |          // 移除掉主屏显示成员
 | 
	
		
			
				|  |  |          NSString *display = [ClassroomService sharedService].currentRoom.currentDisplayURI;
 | 
	
		
			
				|  |  | -        for (RoomMember *member in lastArray) {
 | 
	
		
			
				|  |  | +        NSMutableIndexSet *removeIndexes = [[NSMutableIndexSet alloc] init];
 | 
	
		
			
				|  |  | +        [lastArray enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
 | 
	
		
			
				|  |  |              if ([member.userId isEqualToString:display] && [ClassroomService sharedService].currentRoom.currentDisplayType != DisplayWhiteboard) {
 | 
	
		
			
				|  |  | -                [lastArray removeObject:member];
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | +                [removeIndexes addIndex:idx];
 | 
	
		
			
				|  |  | +                *stop = YES;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        [lastArray removeObjectsAtIndexes:removeIndexes];
 | 
	
		
			
				|  |  | +        NSArray *safeData = [lastArray copy]; // 创建不可变副本
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  |          dispatch_async(dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | -            self.videoDataSource = [lastArray mutableCopy];
 | 
	
		
			
				|  |  | -            [self.videoListTableView reloadData];
 | 
	
		
			
				|  |  | +            __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +            if (!strongSelf || !strongSelf.videoListTableView) {
 | 
	
		
			
				|  |  | +                MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  | +            strongSelf.videoDataSource = [safeData mutableCopy];
 | 
	
		
			
				|  |  | +            [strongSelf.videoListTableView reloadData];
 | 
	
		
			
				|  |  | +            MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  | -        MJ_UNLOCK(self.signalSemaphore)
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)updateUserVideo:(NSString *)userId {
 | 
	
		
			
				|  |  | +    __weak typeof(self) weakSelf = self;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      dispatch_async(self.videoListQueue, ^{
 | 
	
		
			
				|  |  | +        __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +        if (!strongSelf) return;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  |          MJ_LOCK(self.signalSemaphore)
 | 
	
		
			
				|  |  | -        NSLog(@"------ unlock---");
 | 
	
		
			
				|  |  | -        for(int i=0;i < self.videoDataSource.count; i++) {
 | 
	
		
			
				|  |  | -            RoomMember *member = self.videoDataSource[i];
 | 
	
		
			
				|  |  | -            if([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  | -                NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
 | 
	
		
			
				|  |  | -                dispatch_async(dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | -                    TXClassroomVideoListCell * cell = [self.videoListTableView cellForRowAtIndexPath:index];
 | 
	
		
			
				|  |  | -                    if (cell) {
 | 
	
		
			
				|  |  | -                        [self.videoListTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | +        NSArray *safeDataSource = [strongSelf.videoDataSource copy];
 | 
	
		
			
				|  |  | +        NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
 | 
	
		
			
				|  |  | +            if ([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  | +                [indexPaths addObject:[NSIndexPath indexPathForRow:idx inSection:0]];
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if (indexPaths.count == 0) {
 | 
	
		
			
				|  |  | +            MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        MJ_UNLOCK(self.signalSemaphore)
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        dispatch_async(dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | +            __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +            if (!strongSelf) {
 | 
	
		
			
				|  |  | +                MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            NSArray *validIPs = [[KSIndexPathValidator validatorWithType:KSScrollViewTypeTableView] validateForTableView:self.videoListTableView indexPaths:indexPaths];
 | 
	
		
			
				|  |  | +            if (validIPs.count) {
 | 
	
		
			
				|  |  | +                [strongSelf.videoListTableView performBatchUpdates:^{
 | 
	
		
			
				|  |  | +                    [strongSelf.videoListTableView reloadRowsAtIndexPaths:indexPaths
 | 
	
		
			
				|  |  | +                                                      withRowAnimation:UITableViewRowAnimationNone];
 | 
	
		
			
				|  |  | +                } completion:^(BOOL finished) {
 | 
	
		
			
				|  |  | +                    MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  | +                }];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                MJ_UNLOCK(strongSelf.signalSemaphore)
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)updateUserQuality:(NSString *)userId netWorkingStatus:(TXNetWorkingStatus)quality {
 | 
	
		
			
				|  |  | +    __weak typeof(self) weakSelf = self;
 | 
	
		
			
				|  |  |      dispatch_async(self.videoListQueue, ^{
 | 
	
		
			
				|  |  | -        MJ_LOCK(self.signalQualitySemaphore)
 | 
	
		
			
				|  |  | -        NSLog(@"------ unlock---");
 | 
	
		
			
				|  |  | -        for(int i = 0;i < self.videoDataSource.count; i++) {
 | 
	
		
			
				|  |  | -            RoomMember *member = self.videoDataSource[i];
 | 
	
		
			
				|  |  | -            if([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  | -                NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +        if (!strongSelf) return;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        MJ_LOCK(strongSelf.signalQualitySemaphore)
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        NSArray *safeDataSource = [strongSelf.videoDataSource copy];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
 | 
	
		
			
				|  |  | +            if ([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  | +                RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
 | 
	
		
			
				|  |  | +                NSIndexPath *index = [NSIndexPath indexPathForRow:idx inSection:0];
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  |                  dispatch_async(dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | -                    TXClassroomVideoListCell * cell = [self.videoListTableView cellForRowAtIndexPath:index];
 | 
	
		
			
				|  |  | +                    __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +                    if (!strongSelf) {
 | 
	
		
			
				|  |  | +                        MJ_UNLOCK(strongSelf.signalQualitySemaphore)
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  | +                    TXClassroomVideoListCell * cell = [strongSelf.videoListTableView cellForRowAtIndexPath:index];
 | 
	
		
			
				|  |  |                      if (cell) {
 | 
	
		
			
				|  |  |                          [cell updateQuality:quality];
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | +                    MJ_UNLOCK(strongSelf.signalQualitySemaphore)
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        MJ_UNLOCK(self.signalQualitySemaphore)
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        MJ_UNLOCK(strongSelf.signalQualitySemaphore)
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)updateMicStatus:(NSString *)userId volume:(NSInteger)volume {
 | 
	
		
			
				|  |  | +    __weak typeof(self) weakSelf = self;
 | 
	
		
			
				|  |  |      dispatch_async(self.videoListQueue, ^{
 | 
	
		
			
				|  |  | -        MJ_LOCK(self.signalVolumeSemaphore)
 | 
	
		
			
				|  |  | -        NSLog(@"------ unlock---");
 | 
	
		
			
				|  |  | -        for(int i = 0;i < self.videoDataSource.count; i++) {
 | 
	
		
			
				|  |  | -            RoomMember *member = self.videoDataSource[i];
 | 
	
		
			
				|  |  | -            if([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  | +        __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +        if (!strongSelf) return;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        MJ_LOCK(strongSelf.signalVolumeSemaphore)
 | 
	
		
			
				|  |  | +        NSArray *safeDataSource = [strongSelf.videoDataSource copy];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
 | 
	
		
			
				|  |  | +            if ([member.userId isEqualToString:userId]) {
 | 
	
		
			
				|  |  |                  RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
 | 
	
		
			
				|  |  | +                NSIndexPath *index = [NSIndexPath indexPathForRow:idx inSection:0];
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  |                  dispatch_async(dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | -                    TXClassroomVideoListCell * cell = [self.videoListTableView cellForRowAtIndexPath:index];
 | 
	
		
			
				|  |  | +                    __strong typeof(weakSelf) strongSelf = weakSelf;
 | 
	
		
			
				|  |  | +                    if (!strongSelf) {
 | 
	
		
			
				|  |  | +                        MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
 | 
	
		
			
				|  |  | +                        return;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  | +                    TXClassroomVideoListCell *cell = [strongSelf.videoListTableView cellForRowAtIndexPath:index];
 | 
	
		
			
				|  |  |                      if (cell) {
 | 
	
		
			
				|  |  |                          [cell updateUserVolume:volume isCloseMic:!currentMember.microphoneEnable];
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | +                    MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        MJ_UNLOCK(self.signalVolumeSemaphore)
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |