我如何管理 NSMutableArray 内存
How can I manage NSMutableArray memory
我正在 iOS 上开发基于联系人的应用程序。
基本上我使用 NSMutableArray 进行人员管理。
这是我的代码。
这段代码有时会崩溃。
如果没有崩溃,那么我可以显示 allPeople 依靠调试 window。
当我崩溃时,我只能看到 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]
尝试复制数组:_allPeople_ = [people copy];
我不确定是否需要自动释放池,内存由 OS 自动管理。
你可以调用
而不是加锁
@synchronized(_allPeople_) {
}
好吧,我认为您已经发布了答案:
[__NSArrayM getObjects:range:]: 范围 {0, 3009} 超出了空数组的范围
您正在尝试访问范围远远超出范围的空数组:)。很可能已经使用 ARC 为您管理了内存。
建议:
- 如果你在主线程上使用这段代码,不要使用锁,解锁
只要。这是没用的。
如果你使用多线程(你没有显示
它与您的代码,也没有评论)使用 属性 是原子的。和你
不需要锁定,解锁(你有非原子)
仅使用自动释放池
当您创建许多短暂的对象时。 (例如许多
带 NSString 的字符串)。请记住,对于多线程,您需要
保护数据。
对于后台处理,将更新移动到主线程是有益的,如下所示:
dispatch_async(dispatch_get_main_queue(), ^{
self._allPeople_ = processedAllPeople;
//update UI
});
您不需要同步,因为所有更新都在同一个线程上。 UI 只能在主线程上更新。
- 如果您的 UI 在更新期间正在使用该数组,请制作一份数据副本。你需要深拷贝。
我正在 iOS 上开发基于联系人的应用程序。
基本上我使用 NSMutableArray 进行人员管理。
这是我的代码。
这段代码有时会崩溃。
如果没有崩溃,那么我可以显示 allPeople 依靠调试 window。
当我崩溃时,我只能看到 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]
尝试复制数组:_allPeople_ = [people copy];
我不确定是否需要自动释放池,内存由 OS 自动管理。
你可以调用
而不是加锁@synchronized(_allPeople_) {
}
好吧,我认为您已经发布了答案: [__NSArrayM getObjects:range:]: 范围 {0, 3009} 超出了空数组的范围
您正在尝试访问范围远远超出范围的空数组:)。很可能已经使用 ARC 为您管理了内存。
建议:
- 如果你在主线程上使用这段代码,不要使用锁,解锁 只要。这是没用的。
如果你使用多线程(你没有显示 它与您的代码,也没有评论)使用 属性 是原子的。和你 不需要锁定,解锁(你有非原子)
仅使用自动释放池 当您创建许多短暂的对象时。 (例如许多 带 NSString 的字符串)。请记住,对于多线程,您需要 保护数据。
对于后台处理,将更新移动到主线程是有益的,如下所示:
dispatch_async(dispatch_get_main_queue(), ^{ self._allPeople_ = processedAllPeople; //update UI });
您不需要同步,因为所有更新都在同一个线程上。 UI 只能在主线程上更新。
- 如果您的 UI 在更新期间正在使用该数组,请制作一份数据副本。你需要深拷贝。