【问题标题】:Fatal Exception: NSRangeException - index 2 beyond bounds [0 .. 1]致命异常:NSRangeException - 索引 2 超出范围 [0 .. 1]
【发布时间】:2018-12-22 19:25:36
【问题描述】:

在我在 swift 项目中使用的一个库中,一行导致应用程序崩溃。我试图理解并修复它,但没有运气。我知道这是由数组索引错误引起的。有人可以帮忙吗?

崩溃报告

Fatal Exception: NSRangeException
0  CoreFoundation                 0x180a42e38 __exceptionPreprocess
1  libobjc.A.dylib                0x1800a7f80 objc_exception_throw
2  CoreFoundation                 0x180922ebc -[__NSArrayM removeObjectAtIndex:]
3                          0x10000ac70 -[ChatSectionManager messageForIndexPath:] (ChatSectionManager.m:435)
4                          0x10001c194 -[Chat tableView:cellForRowAtIndexPath:] (Chat.m:596)
5  UIKit                          0x185ee2f40 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:]
6  UIKit                          0x185ee30a8 -[UITableView _createPreparedCellForGlobalRow:willDisplay:]

ChatSectionManager.m

 - (QBChatMessage *)messageForIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.item == NSNotFound) {
        return nil;
    }

    QMChatSection *currentSection = self.chatSections[indexPath.section];
    //crashes here line 435
    return currentSection.messages[indexPath.item];
}

Chat.m

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.chatSectionManager messagesCountForSectionAtIndex:section];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.chatSectionManager.chatSectionsCount;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {

    QBChatMessage *messageItem = [self.chatSectionManager messageForIndexPath:indexPath];

... 方法包含 removeObjectAtIndex

- (void)deleteMessages:(NSArray *)messages animated:(BOOL)animated {

    dispatch_async(_serialQueue, ^{

        NSMutableArray *messagesIDs = [NSMutableArray array];
        NSMutableArray *itemsIndexPaths = [NSMutableArray array];
        NSMutableIndexSet *sectionsIndexSet = [NSMutableIndexSet indexSet];

        self.editableSections = self.chatSections.mutableCopy;

        for (QBChatMessage *message in messages) {
            NSIndexPath *indexPath = [self indexPathForMessage:message];
            if (indexPath == nil) continue;

            QMChatSection *chatSection = self.chatSections[indexPath.section];
            [chatSection.messages removeObjectAtIndex:indexPath.item];

            if (chatSection.isEmpty) {
                [sectionsIndexSet addIndex:indexPath.section];
                [self.editableSections removeObjectAtIndex:indexPath.section];

                // no need to remove elements whose section will be removed
                NSArray *items = [itemsIndexPaths copy];
                for (NSIndexPath *index in items) {
                    if (index.section == indexPath.section) {
                        [itemsIndexPaths removeObject:index];
                    }
                }
            } else {

                [itemsIndexPaths addObject:indexPath];
            }
        }

        dispatch_sync(dispatch_get_main_queue(), ^{

            self.chatSections = self.editableSections.copy;
            self.editableSections = nil;

            if ([self.delegate respondsToSelector:@selector(chatSectionManager:didDeleteMessagesWithIDs:atIndexPaths:withSectionsIndexSet:animated:)]) {

                [self.delegate chatSectionManager:self didDeleteMessagesWithIDs:messagesIDs atIndexPaths:itemsIndexPaths withSectionsIndexSet:sectionsIndexSet animated:animated];
            }
        });
    });
}

注意:这个崩溃是随机发生的,我不知道为什么

织物崩溃报告 http://crashes.to/s/679e90f0c90

【问题讨论】:

  • 您发布的代码与堆栈跟踪不匹配。崩溃显示您在第 596 行的 ChatSectionManager messageForIndexPath: 方法中通过 NSArray 调用 removeObjectAtIndex:。但是您为 messageForIndexPath: 发布的代码没有调用 removeObjectAtIndex:
  • @maddy 我在 xcode 上发布了我的内容,还有其他地方我应该检查吗??
  • 您基本上发布了写入信息,但由于某种原因它不匹配。你改变messageForIndexPath:的实现了吗?
  • 不,我没有改变任何东西,我应该在这些文件中搜索 removeObjectAtIndex 吗?
  • 应该不用搜索了。堆栈跟踪显示,您将在 ChatSectionManager.m 的第 435 行找到对 removeObjectAtIndex: 的调用。实际上第 435 行的代码是什么?

标签: ios objective-c crash


【解决方案1】:

肯定是deleteMessages有问题,看看你的线程16在哪里崩溃了:

QMChatSectionManager.m 第 228 行 __48-[QMChatSectionManager deleteMessages:animated:]_block_invoke

检查第 228 行到底是哪一行以确定问题所在,但我会在这里冒险并猜测它是什么

[chatSection.messages removeObjectAtIndex:indexPath.item];

所以你要在线程 16 上删除 messageForIndexPath 在主线程上引用的数据结构。正如您所注意到的,这是对几乎不可能按需复制的竞争条件的公开邀请。

解决方法是不要在后台线程中修改chatSection 的内容。看起来您已经有了正确的想法,在主线程上分配已完成的部分列表,

self.chatSections = self.editableSections.copy;

只需将该逻辑应用于部分列表中更改的每个项目,您的随机崩溃就会消失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多