使用 NSOperationQueue 并尝试更改滑块/选择器等时,iPhone 设备上遇到大量泄漏

发布于 2024-10-11 01:40:23 字数 1909 浏览 6 评论 0原文

在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

追我者格杀勿论 2024-10-18 01:40:23

我假设您在创建 NSOperation 的 setSliders 之前执行其他操作,并且您只是省略了该代码。

UIKit 不保证线程安全,您应该只在主线程上访问界面元素。文档中的一些地方提到了这一点,但最有说服力的是《Cocoa 基础指南》:

所有 UIKit 对象只能在主线程上使用。

所以 firstRun 应该看起来更像这样:

- (void)firstRun {

  NSAutoreleasePool *pool = [NSAutoreleasePool new];

  // Do something important here...

  [self performSelectorOnMainThread:@selector(setSliders) withObject:nil waitUntilDone:NO];

  NSLog(@"firstRun method end");

  [pool drain];

}

为什么在 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:

All UIKit objects should be used on the main thread only.

So firstRun should look more like this:

- (void)firstRun {

  NSAutoreleasePool *pool = [NSAutoreleasePool new];

  // Do something important here...

  [self performSelectorOnMainThread:@selector(setSliders) withObject:nil waitUntilDone:NO];

  NSLog(@"firstRun method end");

  [pool drain];

}

Why are you using an NSMutableArray in setSliders? 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 like updateSliders. It's a Cocoa style issue. Methods that start with "set" should be used for mutating a single instance variable/property.

旧人九事 2024-10-18 01:40:23

您正在释放 for 循环中的每个标签和滑块,即使您没有保留它们。这是不正确的。您只需释放已分配、复制或保留的内存。有关详细信息,请参阅内存管理编程指南细节。

我还会更改初始化临时数组的方式。 NSMutableArray 的指定初始值设定项是 -initWithCapacity:,而不是-init。为了方便起见,还有一个类方法旨在返回自动释放的实例:

NSMutableArray *tempArray = [NSMutableArray arrayWithCapcity:0];

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:

NSMutableArray *tempArray = [NSMutableArray arrayWithCapcity:0];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文