我在iOS上开发基于联系人的应用程序。

基本上,我使用NSMutableArray进行人员管理。

这是我的代码。

这段代码有时会发生崩溃。

如果没有崩溃,那么我可以在调试窗口上显示allPeople计数。

当我崩溃时,我只能看到allPeople内存地址。

似乎allPeople已经被释放。

我怎么了

谢谢。

@property (nonatomic, strong) NSMutableArray *allPeople_;

    - (void) C {


     ABAddressBookRequestAccessWithCompletion(addressbookRef, ^(bool granted, CFErrorRef error) {
                if (!granted) {
                    return;
                }

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            [self A];
            [self B];
        });
    }
- (void)A {

@autoreleasepool {

        NSMutableArray *people = [NSMutableArray arrayWithArray:_allPeople_];
        //do something

        [arrayLock lock];
        _allPeople_ = people;
        [arrayLock unlock];
    }
}

- (void)B {

        //Here is crash location.
        NSMutableArray *people = [NSMutableArray arrayWithArray:_allPeople_];
        //do something

        [arrayLock lock];
        _allPeople_ = people;
        [arrayLock unlock];
}


这是崩溃日志。

Fatal Exception: NSRangeException
*** -[__NSArrayM getObjects:range:]: range {0, 3009} extends beyond bounds for empty array

Fatal Exception: NSRangeException
0  CoreFoundation                 0x18d57afe0 __exceptionPreprocess
1  libobjc.A.dylib                0x18bfdc538 objc_exception_throw
2  CoreFoundation                 0x18d45d13c -[__NSArrayM getObjects:range:]
3  CoreFoundation                 0x18d45cc80 -[NSArray initWithArray:range:copyItems:]
4  CoreFoundation                 0x18d45cb74 +[NSArray arrayWithArray:]
5  App                           0x1001f92b4 -[AddressCollector C]

最佳答案

好吧,我认为您已经发布了答案:
[__NSArrayM getObjects:range:]:范围{0,3009}超出了空数组的范围

您正在尝试访问范围远远超出它的空数组:)。 ARC已经为您管理了最有可能的内存。

意见建议:


如果您在主线程上使用此代码,请不要使用锁,请解锁
只要。这没用。
如果您使用多个线程(您未显示
它与您的代码,也没有评论)使用原子的属性。你呢
不需要锁定,解锁(您具有非原子性)
仅使用autoreleasepool
当您创建许多短期对象时。 (例如,许多
NSString的字符串)。记住,使用多线程,您需要
保护数据。
对于后台处理,将更新移动到主线程中是非常有益的,如下所示:
dispatch_async(dispatch_get_main_queue(), ^{ self._allPeople_ = processedAllPeople;//update UI });

您不需要同步,因为所有更新都将在同一线程上。 UI只能在主线程上更新。
如果您的UI在更新过程中使用该数组,请复制数据。您需要深层复制。

07-28 12:47