使用 NSOperationQueue 并尝试更改滑块/选择器等时,iPhone 设备上遇到大量泄漏
在使用 NSOperationQueue 并尝试更改滑块/选择器等时,iPhone 设备上遇到大量泄漏。
我可以毫无问题地更改标签,但如果我尝试更改在界面生成器上创建的滑块或选择器,则会出现这些泄漏。
Leaked Object # Address Size Responsible Library Responsible Frame
GeneralBlock-16 0x1b00a0 16 GraphicsServices GetFontNames
GeneralBlock-16 0x1aea90 16 WebCore WebThreadCurrentContext
GeneralBlock-16 0x1aea80 16 GraphicsServices GSFontGetFamilyName
GeneralBlock-64 0x1a7370 64 UIKit GetContextStack
下面的代码
- (void)loadData {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(firstRun)
object:nil];
[queue_ addOperation:operation];
[operation release];
}
- (void)firstRun {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self setSliders];
NSLog(@"firstRun method end");
[pool drain];
}
- (void)setSliders {
NSMutableArray *tempArray = [[[NSMutableArray alloc]init] autorelease];
aquaplannerAppDelegate *appDelegate = (aquaplannerAppDelegate *)[[UIApplication sharedApplication] delegate];
tempArray = appDelegate.settingsValuesArray;
freshMarineSegment.selectedSegmentIndex = [[tempArray objectAtIndex:0]intValue];
for (int i = 1; i <= 20; i++ ) {
UILabel *label = (UILabel *)[self.view viewWithTag:200+i]; // gets label based on tag
UISlider *slider = (UISlider *)[self.view viewWithTag:100+i]; // gets slider based on tag
slider.value = [[tempArray objectAtIndex:i]intValue];
label.text = [[[NSString alloc] initWithFormat:@"%@",[tempArray objectAtIndex:i]] autorelease];
[label release];
[slider release];
}
}
encountering numerous leaks on iphone device when using NSOperationQueue and trying to change sliders / pickers etc.
I am able to change labels without an issue, but if I try to change a slider or picker both created on interface builder I get these leaks.
Leaked Object # Address Size Responsible Library Responsible Frame
GeneralBlock-16 0x1b00a0 16 GraphicsServices GetFontNames
GeneralBlock-16 0x1aea90 16 WebCore WebThreadCurrentContext
GeneralBlock-16 0x1aea80 16 GraphicsServices GSFontGetFamilyName
GeneralBlock-64 0x1a7370 64 UIKit GetContextStack
code below
- (void)loadData {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(firstRun)
object:nil];
[queue_ addOperation:operation];
[operation release];
}
- (void)firstRun {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self setSliders];
NSLog(@"firstRun method end");
[pool drain];
}
- (void)setSliders {
NSMutableArray *tempArray = [[[NSMutableArray alloc]init] autorelease];
aquaplannerAppDelegate *appDelegate = (aquaplannerAppDelegate *)[[UIApplication sharedApplication] delegate];
tempArray = appDelegate.settingsValuesArray;
freshMarineSegment.selectedSegmentIndex = [[tempArray objectAtIndex:0]intValue];
for (int i = 1; i <= 20; i++ ) {
UILabel *label = (UILabel *)[self.view viewWithTag:200+i]; // gets label based on tag
UISlider *slider = (UISlider *)[self.view viewWithTag:100+i]; // gets slider based on tag
slider.value = [[tempArray objectAtIndex:i]intValue];
label.text = [[[NSString alloc] initWithFormat:@"%@",[tempArray objectAtIndex:i]] autorelease];
[label release];
[slider release];
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我假设您在创建 NSOperation 的
setSliders
之前执行其他操作,并且您只是省略了该代码。UIKit 不保证线程安全,您应该只在主线程上访问界面元素。文档中的一些地方提到了这一点,但最有说服力的是《Cocoa 基础指南》:
所以
firstRun
应该看起来更像这样:为什么在
setSliders
中使用NSMutableArray
?您实际上永远不会更改数组,并且可变数据结构可能会对线程编程造成严重破坏。另外,我会将
setSliders
方法重命名为updateSliders
之类的名称。这是一个可可风格的问题。以“set”开头的方法应该用于改变单个实例变量/属性。I'm assuming you're doing something else before
setSliders
for which you created the NSOperation, and you just omitted that code.UIKit is not guaranteed to be thread safe, and you should only access your interface elements on the main thread. This is mentioned in a few places in the docs, but the most telling is in the Cocoa Fundamentals Guide:
So
firstRun
should look more like this:Why are you using an
NSMutableArray
insetSliders
? You're never actually changing the array, and mutable data structures can wreak havoc in threaded programming.Also, I'd rename the
setSliders
method to something likeupdateSliders
. It's a Cocoa style issue. Methods that start with "set" should be used for mutating a single instance variable/property.您正在释放 for 循环中的每个标签和滑块,即使您没有保留它们。这是不正确的。您只需释放已分配、复制或保留的内存。有关详细信息,请参阅内存管理编程指南细节。
我还会更改初始化临时数组的方式。
NSMutableArray
的指定初始值设定项是-initWithCapacity:
,而不是-init
。为了方便起见,还有一个类方法旨在返回自动释放的实例:You are releasing each label and slider in your for loop, even though you have not retained them. This is not correct. You only need to release memory that you have allocated, copied or retained. See the memory management programming guide for more details.
I would also change the way you initialize your temporary array. The designated initializer for
NSMutableArray
is-initWithCapacity:
, not-init
. There is also a class method designed to return an autoreleased instance for convenience: