我遇到RLM异常(可能访问RLMArray导致了它-https://realm.io/docs/objc/latest/api/Classes/RLMObject.html#/c:objc%28cs%29RLMObject%28py%29invalidated)
对象已被删除或无效。
在Bugsnag上的崩溃日志如下:
2光束
RLMObject_Private.hpp:45:9
RLMVerifyAttached
3光束
ChatPeopleViewController.m:270:22
-[ChatPeopleViewController lastMessage:]
4光束
ChatPeopleViewController.m:223:30
-[ChatPeopleViewController tableView:cellForRowAtIndexPath:]
相关源代码:
#import "ChatPeopleViewController.h"
#import "UIImageView+WebCache.h"
#import "ChatPeopleCell.h"
#import "ClientManager.h"
#import "BeamString.h"
#import "ChatViewController.h"
#import "BMAddNewChatViewController.h"
#import "UIFont+Custom.h"
#import "UITabBarItem+CustomBadge.h"
#import "BMTableViewRowActionWithImage.h"
#import "Appirater.h"
#import "BMUserStatusManager.h"
#import "OnlineStatusResponse.h"
#import "NSDate+BMCustom.h"
#import "BMChatSession.h"
#import "BMGroupChatManager.h"
#import "BMGroupMember.h"
#import "BMGroupChatViewController.h"
#import "GroupChatPeopleCell.h"
static NSString * const kCellIdentifier = @"UserCell";
static NSString * const kGroupCellIdentifier = @"UserCell";
@interface ChatPeopleViewController ()<SWTableViewCellDelegate> {
NSMutableArray *friends;
NSArray *reverseChronoArray;
}
@end
@implementation ChatPeopleViewController
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
-(instancetype)init
{
self = [super init];
if (self) {
self.title = NSLocalizedString(@"Beam Chats", nil);
[self customRightBarItem:@selector(btn_rightClicked:) image:[UIImage imageNamed:@"icon_recent"]];
// [BeamAPI updateUserName:@"test2" complete:^(BOOL isSuccess, NSDictionary *responseObject, NSError *err){
// if (isSuccess) {
// }
// // self.onlineIndicator.image = [UIImage imageNamed:@"presence_online"];
// }];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.screenName = @"Chat list";
[self registerCells];
self.extendedLayoutIncludesOpaqueBars = YES;
self.edgesForExtendedLayout = UIRectEdgeBottom|UIRectEdgeLeft|UIRectEdgeRight;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[self.tableView_chat addSubview:refreshControl];
[refreshControl addTarget:self action:@selector(handlePullToRefresh:) forControlEvents:UIControlEventValueChanged];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleProfileUpdate:)
name:friendProfileDidUpdateNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleOnlineStatusUpdate:)
name:kUpdateOnlineStatusNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateBadgeCount:)
name:kUpdateBadgeCountNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(messageRetractedUpdate)
name:kRetractMessageNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reloadForNotification:)
name:kChatViewControllerShouldRefreshNotification
object:nil];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
_tableView_chat.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
_tableView_chat.contentInset = UIEdgeInsetsMake(0.0f,
0.0f,
[[AppDelegate sharedInstance] tabBarHeight],
0.0);
[self sortReverseChronoArray];
[self updateBadgeCount:nil];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.tableView_chat reloadData];
[MBProgressHUD hideAllHUDsForView:self.tabBarController.view animated:YES];
}
-(void)btn_rightClicked:(id)sender
{
// [BeamAPI sendMsgToBotWithVersion:1 scr:@"" cmd:@"" chn:@"" qid:@"" qry:@"" complete:^(BOOL isSuccess, id responseObject, NSError *err){
//
//
// }];
// NSArray *ary = [[BMGroupChatManager sharedManager] getMembersInGroup:@"13"];
// [[BMGroupChatManager sharedManager] createNewGroupWithEmails:@[@"st85368@gmail.com",@"test2@test2.com"] complete:^(NSString *chatID){
// //create group in realm;
// [[ClientManager sharedManager] createDialoguesIfNeeded:chatID isGroup:YES];
//
//
// }];
// BMGroupMember *mem = [[BMGroupMember alloc] initWithString:@"test4@test4.com" topic:@"user/test4@test4.com"];
// [[BMGroupChatManager sharedManager] addMemberToGroupChatID:mem chatID:@"30"];
// [[BMGroupChatManager sharedManager] removeMembersFromGroupChatID:mem chatID:@"13"];
// [BMGroupChatManager sharedManager].getAllGroupChats;
// [BeamAPI getMemberInGroup:@"40" complete:^(BOOL isSuccess, id responseObject, NSError *err){
// NSMutableArray * cityArray = [[NSMutableArray alloc] init];
// NSMutableArray *jsonarry = responseObject[@"response"];
//
// // NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
// // NSMutableArray *testFeeds = [NSJSONSerialization JSONObjectWithData: data options:NSJSONReadingMutableContainers error:nil];
// // [cityArray addObjectsFromArray:testFeeds];
//
//
// }];
BMAddNewChatViewController *vc = [[BMAddNewChatViewController alloc] init];
vc.hidesBottomBarWhenPushed = YES;
self.navigationItem.hidesBackButton = NO;
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[self.navigationController pushViewController:vc animated:YES];
}
- (void)registerCells {
[self.tableView_chat registerNib:[UINib nibWithNibName:@"ChatPeopleCell" bundle:nil]
forCellReuseIdentifier:kCellIdentifier];
// [self.tableView_chat registerClass: [GroupChatPeopleCell class] forCellReuseIdentifier:kGroupCellIdentifier];
}
- (void)registerNibWithTableView:(UITableView *)tableView{
[self.tableView_chat registerNib:[UINib nibWithNibName:@"ChatPeopleCell" bundle:nil]
forCellReuseIdentifier:kCellIdentifier];
}
#pragma mark - Table View Data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [reverseChronoArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *emailAndHistoryDict = reverseChronoArray[indexPath.row];
NSString *friendEmail = [emailAndHistoryDict allKeys][0];
ChatPeopleCell *cell = [self.tableView_chat dequeueReusableCellWithIdentifier:kCellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if ([[BMGroupChatManager sharedManager] isGroupChat: friendEmail]) {
[cell loadUserDataForGroup:friendEmail];
}else{
[cell loadUserDataByEmail:friendEmail];
}
OnlineStatusResponse *userStatus = [[BMUserStatusManager sharedInstance] getUserStatus:friendEmail];
if ([friendEmail isEqualToString:kBeamBotEmail]) {
cell.onlineIndicator.image = [UIImage imageNamed:@"presence_online"];
}else if (userStatus.isOnline) {
cell.onlineIndicator.image = [UIImage imageNamed:@"presence_online"];
}else{
cell.onlineIndicator.image = [UIImage imageNamed:@"presence_offline"];
}
NSUInteger counter = [[ClientManager sharedManager] badgeCountForUser:friendEmail];
if (counter == 0) {
[cell.badgeButton setHidden:YES];
}
else{
[cell.badgeButton setHidden:NO];
[cell.badgeButton setTitle:[@(counter) stringValue] forState:UIControlStateNormal];
}
NSArray *historyMessages = emailAndHistoryDict[friendEmail];
BeamString *lastString = [self lastMessage:historyMessages];
if (lastString) {
NSDate *date = [lastString timestampThatWorks];
cell.timeLabel.text = [date timestampFormat];
cell.statusLabel.textColor = UIColorFromRGB(0x6d6d6d);
if ([lastString isImage]) {
cell.statusLabel.text = NSLocalizedString(@"- Image -", nil);
}else if(lastString.msgType == MSG_TYPE_STICKER){
cell.statusLabel.text = NSLocalizedString(@"- Sticker -", nil);
}else if (lastString.msgType == MSG_TYPE_SMILEYSTICKER){
cell.statusLabel.text = NSLocalizedString(@"- Smiley -", nil);
}else {
cell.statusLabel.attributedText = [self getAttrStrWithEmoji:[lastString string] isBlack:YES];
}
[cell displayReadImage:(lastString.isMine && (lastString.msgStatus == MSG_READ))
delivered:(lastString.isMine && (lastString.msgStatus == MSG_SENT))];
cell.hidden = NO;
}
else {
cell.statusLabel.text = NSLocalizedString(@"(no history available)", nil);
cell.hidden = YES;
}
cell.clipsToBounds = YES;
NSMutableArray *rightUtilityButtons = [NSMutableArray new];
if (![self isFriend:friendEmail]) {
//if his not a friend then add the option
[rightUtilityButtons sw_addUtilityButtonWithColor:
[UIColor whiteColor]
icon:[UIImage imageNamed:@"icon_contacts"]];
}
[rightUtilityButtons sw_addUtilityButtonWithColor:
[UIColor whiteColor]
icon:[UIImage imageNamed:@"chat_cell_delete"]];
cell.rightUtilityButtons = rightUtilityButtons;
// cell.leftUtilityButtons = [self leftButton];
cell.delegate = self;
return cell;
}
- (BeamString *)lastMessage:(NSArray *)messages {
if (messages) {
for (int i = (int)([messages count] - 1); i >= 0; i--) {
BeamString *beam = messages[i];
if (beam.string && beam.string.length > 0) {
return beam;
}
}
}
return nil;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
#pragma mark -SWTableViewDelegate
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index {
NSIndexPath *cellIndexPath = [self.tableView_chat indexPathForCell:cell];
NSDictionary *emailAndHistoryDict = reverseChronoArray[cellIndexPath.row];
NSString *friendEmail = [emailAndHistoryDict allKeys][0];
switch (index) {
case 0:
if (![self isFriend:friendEmail]) {
[self addFriend:friendEmail withTableView:self.tableView_chat];
[self.tableView_chat reloadData];
}
[self deleteChat:cellIndexPath];
break;
case 1:
{
[self deleteChat:cellIndexPath];
break;
}
default:
break;
}
}
- (BOOL)swipeableTableViewCellShouldHideUtilityButtonsOnSwipe:(SWTableViewCell *)cell{
return YES;
}
#pragma mark - helpers
- (BOOL) isFriend:(NSString *)email{
if (![[BMUserManager sharedInstance] isFriend:email] && ![email isEqualToString:kBeamBotEmail]) {
return NO;
}
return YES;
}
- (void)addFriend:(NSString *)friendEmail withTableView:(UITableView *)tableView
{
[[BMUserManager sharedInstance] addFriend:friendEmail];
[tableView setEditing:NO animated:YES];
UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil
message:NSLocalizedString(@"Added friend", nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
style:UIAlertActionStyleDefault
handler:nil];
[controller addAction:action];
[self presentViewController:controller animated:YES completion:nil];
}
- (void)deleteChat:(NSIndexPath *)indexPath
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Confirm", nil)
message:NSLocalizedString(@"Are you sure want to delete this conversation?", nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *delete = [UIAlertAction actionWithTitle:NSLocalizedString(@"Delete", nil)
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * _Nonnull action) {
NSDictionary *emailAndHistoryDict = reverseChronoArray[indexPath.row];
NSString *friend = [emailAndHistoryDict allKeys][0];
NSMutableDictionary *messageDict = [ClientManager sharedManager].chatSessions;
[messageDict removeObjectForKey:friend];
//delete realm record
[[ClientManager sharedManager] deleteDialogues:friend];
NSMutableArray *array = [reverseChronoArray mutableCopy];
[array removeObjectAtIndex:indexPath.row];
reverseChronoArray = array;
[self.tableView_chat deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
self.noChatsMessage.hidden = ([reverseChronoArray count] > 0);
}];
UIAlertAction *keep = [UIAlertAction actionWithTitle:NSLocalizedString(@"Keep", nil)
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {}];
[alert addAction:delete];
[alert addAction:keep];
[self presentViewController:alert animated:YES completion:^{}];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *emailAndHistoryDict = reverseChronoArray[indexPath.row];
NSString *friend = [emailAndHistoryDict allKeys][0];
if (friend == nil) {
return;
}
[BMUserManager sharedInstance].currentChatEmail = friend;
[ClientManager sharedManager].currentFriend = friend;
if (![friend isEqualToString:kBeamBotEmail]) {
[Appirater userDidSignificantEvent:NO];
}
ChatViewController *vc ;
if ([ClientManager sharedManager].curChatSession.isGroup) {
vc = [[BMGroupChatViewController alloc] init];
[[BMGroupChatManager sharedManager] updateGroupMembersForGroupID:friend];
BMGroupChat *gc = [[BMGroupChatManager sharedManager] getGroupChatByID:friend];
((BMGroupChatViewController *)vc).groupChat = gc;
}else{
vc = [[ChatViewController alloc] init];
}
vc.hidesBottomBarWhenPushed = YES;
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[self.navigationController pushViewController:vc animated:YES];
}
-(void)viewDidLayoutSubviews
{
if ([self.tableView_chat respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView_chat setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView_chat respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView_chat setLayoutMargins:UIEdgeInsetsZero];
}
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
- (void)messageRetractedUpdate{
[self.tableView_chat reloadData];
}
- (void)updateBadgeCount:(NSNotification *)note {
[self sortReverseChronoArray];
self.noChatsMessage.hidden = ([reverseChronoArray count] > 0);
[self.tableView_chat reloadData];
NSUInteger totBadge = [[ClientManager sharedManager] totalBadgeCount];
if (totBadge > 0) {
[self.navigationController.tabBarItem setCustomBadgeValue:@(totBadge).stringValue
withFont:[UIFont customAppFontOfSize:11.0]
andFontColor:[UIColor whiteColor]
andBackgroundColor:BEAM_RED];
}
else{
self.navigationController.tabBarItem.badgeValue = nil;
}
}
- (void)reloadForNotification:(NSNotification *)note {
[self sortReverseChronoArray];
self.noChatsMessage.hidden = ([reverseChronoArray count] > 0);
[self.tableView_chat reloadData];
}
#pragma mark - helpers
- (void)sortReverseChronoArray {
//sort it reverse chronologically
NSMutableArray *lastBeamStringsForUsers = [NSMutableArray array];
for ( NSString *key in [ClientManager sharedManager].chatSessions) {
NSArray* tmp =[[ClientManager sharedManager].chatSessions allKeys];
if ([tmp count] > 0) {
BMChatSession *cs = [ClientManager sharedManager].chatSessions[key];
[lastBeamStringsForUsers addObject: @{ key:cs.beamStrings}];
}
}
reverseChronoArray = [lastBeamStringsForUsers sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *beamString1, NSDictionary *beamString2) {
BeamString *friendStrings = [[[beamString1 objectEnumerator] nextObject] lastObject]; //[beamString1[friendEmail1] lastObject];
BeamString *friendStrings2 = [[[beamString2 objectEnumerator] nextObject] lastObject];
if (!friendStrings2 || friendStrings2.invalidated) {
return -1;
}else if (!friendStrings || friendStrings.invalidated){
return nil;
}
return [[friendStrings timestampThatWorks] compare:[friendStrings2 timestampThatWorks]] * -1;
}];
}
- (void)handleProfileUpdate:(NSNotification *)note {
NSString *email = [note object];
if (![email isKindOfClass:[NSString class]]) {
return;
}
for (ChatPeopleCell *cell in [self.tableView_chat visibleCells]) {
if ([cell.loadedEmail isEqualToString:email]) {
[cell loadUserDataByEmail:email];
}
}
}
- (NSMutableAttributedString *) getAttrStrWithEmoji:(NSString *)str isBlack:(BOOL)isBlack{
NSString *orgStr = str;
NSDictionary *attrs = @{ NSForegroundColorAttributeName : [UIColor whiteColor]};
if (isBlack) {
attrs = @{ NSForegroundColorAttributeName : [UIColor grayColor] };
}
NSMutableAttributedString *myString = [[NSMutableAttributedString alloc]initWithString:@"" attributes:attrs];
//NSMutableAttributedString *myString = [[NSMutableAttributedString alloc]init];
NSAttributedString *attachmentString;
NSString *regEx = @"\\[A[0-9]{2}]";
while (orgStr.length > 0) {
NSRange range = [orgStr rangeOfString:regEx options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
NSRange imageNameRange = NSMakeRange(range.location + 1, range.length - 2);
NSString *imageFile =[NSString stringWithFormat:@"%@",[orgStr substringWithRange:imageNameRange]];
NSString *firstPartStr = [orgStr substringToIndex:range.location];
NSAttributedString *firstPartAttStr = [[NSAttributedString alloc] initWithString:firstPartStr attributes:attrs];
[myString appendAttributedString:firstPartAttStr];
orgStr = [orgStr substringFromIndex:(range.location + range.length)];
UIImage *emoji = [UIImage reSizeImage:[UIImage imageNamed:imageFile] toSize:CGSizeMake(15.5, 15.5)];
attachment.image = emoji;
attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
[myString appendAttributedString:attachmentString];
}
else{
NSAttributedString *lastPartAttStr = [[NSAttributedString alloc] initWithString:orgStr attributes:attrs];
[myString appendAttributedString:lastPartAttStr];
break;
}
}
return myString;
}
- (void)handlePullToRefresh:(UIRefreshControl *)sender {
[sender performSelector:@selector(endRefreshing) withObject:nil afterDelay:1.2];
}
- (void)handleOnlineStatusUpdate:(NSNotification *)note {
NSSet *emails = [note object];
for (NSString *email in emails){
if (![email isKindOfClass:[NSString class]]) {
return;
}
for (ChatPeopleCell *cell in [self.tableView_chat visibleCells]) {
if ([email isEqualToString:kBeamBotEmail]) {
cell.onlineIndicator.image = cell.onlineIndicator.image = [UIImage imageNamed:@"presence_online"];
}else if ([cell.loadedEmail isEqualToString:email]) {
OnlineStatusResponse *userStatus = [[BMUserStatusManager sharedInstance] getUserStatus:email];
if (userStatus.isOnline) {
cell.onlineIndicator.image = [UIImage imageNamed:@"presence_online"];
}else{
cell.onlineIndicator.image = [UIImage imageNamed:@"presence_offline"];
}
}
}
}
}
@end
请检查。