5

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];
    }
}
4

2 に答える 2

7

setSlidersNSOperation を作成した前に別のことをしていて、そのコードを省略しただけだと思います。

UIKit はスレッド セーフであることが保証されていないため、メイン スレッドでインターフェイス要素にのみアクセスする必要があります。これはドキュメントのいくつかの場所で言及されていますが、最もわかりやすいのは Cocoa Fundamentals Guide です。

すべての 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];

}

なぜ in を使用しているNSMutableArraysetSlidersですか? 実際に配列を変更することはなく、可変データ構造はスレッド化されたプログラミングで大混乱を引き起こす可能性があります。

また、setSlidersメソッドの名前をupdateSliders. これはココア スタイルの問題です。「set」で始まるメソッドは、単一のインスタンス変数/プロパティを変更するために使用する必要があります。

于 2011-01-07T16:54:54.450 に答える
0

for ループ内の各ラベルとスライダーを保持していなくても解放しています。これは正しくありません。割り当て、コピー、または保持したメモリのみを解放する必要があります。詳細については、メモリ管理プログラミング ガイドを参照してください。

また、一時配列を初期化する方法も変更します。の指定された初期化子はNSMutableArrayis であり-initWithCapacity:、not-initです。便宜上、自動解放されたインスタンスを返すように設計されたクラス メソッドもあります。

NSMutableArray *tempArray = [NSMutableArray arrayWithCapcity:0];
于 2011-01-07T15:42:35.840 に答える