我正在使用TCP短连接将数据发送到主机。当我想向主机发送数据时,我将实例化一个套接字,将套接字实例存储到一个数组中,然后在成功写入数据后再将其删除。

这是我的方法:

- (void)connectAndSendData:(NSData *)data
{
    GCDAsyncSocket *asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

    [_connectionDataToBeSentMap setObject:data forKey:[NSValue valueWithNonretainedObject:asyncSocket]];

    NSError *error;

    if(![asyncSocket connectToHost:_host onPort:TCP_COMMUNICATION_PORT withTimeout:TCP_CONNECTION_TIMEOUT error:&error])
    {
        NSLog(@"TCPShortConnection - failed when attempting to connect to host with IP %@", _host);
    }

    [_connectionList addObject:asyncSocket];
}


写入数据后,我将立即断开套接字。因此,连接将在以后删除:

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    [_connectionList removeObject:sock];

    if(err.code == GCDAsyncSocketConnectTimeoutError)
    {
//        NSLog(@"TCPShortConnection - on connection timed out");

        [_delegate onTCPShortConnectionTimedOut];
    }

    else
    {
//        NSLog(@"TCPShortConnection - on disconnection of socket with host %@", _host);
    }
}


此行[_connectionList removeObject:sock];引发NSRangeException。而且我不知道为什么。因为我通过删除空数组中不存在的对象进行了测试,所以不会引发此类异常。

这是日志:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x258d9b0b 0x25096dff 0x257ea6d3 0x257ff033 0xfae43 0x1ca94d 0x4ccba7 0x4d8eff 0x4d87f1 0x2560ae0d 0x2560a9fc)
libc++abi.dylib: terminating with uncaught exception of type NSException


屏幕截图:

ios - iOS-删除NSMutableArray中的对象会引发NSRangeException-LMLPHP

编辑:

请不要以为这不是100%发生。

最佳答案

猜猜:您正在从不同的线程访问您的NSMutableArray

说明:


NSMutableArray不是线程安全的,并发读写也不安全-如果从GCD并发队列访问数组,可能会发生这种情况。
顾名思义,GCDAsyncSocket使用GCD。特别是,委托调用是在用户设置的GCD队列上调度的,并且此队列可以是并发的。
您正在将全局并发队列之一设置为委托队列。


解决方案:您应该首先确定是否应该使用数组,但我们无法为您确定。如果需要数组,则它必须是线程安全的。一种简单的方法是:


创建阵列时,还要为此阵列创建一个顺序的GCD队列。
要执行从数组读取的数组方法,请对数组的顺序队列执行同步调度。您可以使用__block变量从分派的块中返回结果。
要对阵列执行写操作,请使用异步分派到阵列的队列。


这个简单的模型可确保在阵列上不能同时发生两个操作,并且所有读取和写入均以分派的顺序进行。

正如我在开始时所说的,我猜测对数组的并发访问是您的问题,您需要确定自己。如果是这样,应该修复它。

高温超导

关于ios - iOS-删除NSMutableArray中的对象会引发NSRangeException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39303044/

10-09 16:14
查看更多