Obj-C iPhone:内存管理

时间:2011-03-02 02:58:35

标签: iphone objective-c memory-management memory-leaks

iPhone初学者在这里,我正在创建一个名为Piano Master的简单音乐iPhone应用程序,当点击一个按钮时会产生声音。

这是我的代码:

MusicViewController.h

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "PianoMasterAppDelegate.h"

@interface MusicViewController : UIViewController
<AVAudioPlayerDelegate> {}

- (IBAction)buttonClick:(id)sender;

@end

MusicViewController.m

#import "MusicViewController.h"

@implementation MusicViewController

- (IBAction)buttonClick:(id)sender
{
      NSString *path = [[NSBundle mainBundle] pathForResource:@"Piano1" ofType:@"wav"];
      AVAudioPlayer *theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL    fileURLWithPath:path error:NULL];
      theAudio.delegate = self;

      [theAudio play];
}

单击按钮时会播放声音,但每次单击该按钮时,都会创建一个新的AVAudioPlayer,有关如何有效管理此内存问题的最佳方法是什么?我曾想过为MusicViewController创建一个AVAudioPlayer实例并使用它,但如果我每次都继续分配一个新的AVAudioPlayer,那么仍然会有内存问题...... 任何帮助都很有用,谢谢。

4 个答案:

答案 0 :(得分:1)

初始化后,将音频播放器保留在其他控制器(MVC)对象中。然后通过从视图控制器调用音频控制器对象来重用现有的。

答案 1 :(得分:0)

hotpaw2的回答是我建议做的。

但是你缺少的一个关键是内存管理。你应该添加:

[theAudio play];
[theAudio release];

你在内存中分配的内容应该释放。所以即使你每次都在创建一个AVAudioPlayer。你将释放使用的内存。所以你不会有任何泄漏。

答案 2 :(得分:0)

MusicViewController.h文件

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "PianoMasterAppDelegate.h"

@interface MusicViewController : UIViewController <AVAudioPlayerDelegate> {
    AVAudioPlayer* _theAudio;
}

- (IBAction)buttonClick: (id)sender;

@end

MusicViewController.m文件

#import "MusicViewController.h"

@implementation MusicViewController

- (void)dealloc {
    [_theAudio release];
    [super dealloc];
}

- (AVAudioPlayer*)theAudio {
    if (_theAudio == nil) {
        NSString* path = [[NSBundle mainBundle] pathForResource: @"Piano1" ofType: @"wav"];
        _theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL: [NSURL fileURLWithPath: path error: nil];
        [_theAudio setDelegate: self];
    }
    return _theAudio;
}

- (IBAction)buttonClick: (id)sender {
    [self.theAudio play];
}

您可能还想在viewDidUnload方法中释放theAudio以释放内存,请确保将指针设置为nil afterword,如下所示:

- (void)viewDidUnload {
    [_theAudio release];
    _theAudio = nil;
}

答案 3 :(得分:0)

假设您想要播放多个不同的音频文件,AVAudioPlayers的字典可以正常工作。例如,第一次请求声音文件时,创建AVAudioPlayer对象并将其放入声音字典中,然后对于每个后续请求,只需从字典中抓取现有的AVAudioPlayer对象。

这是一个简单的实现:

@interface MusicViewController : UIViewController <AVAudioPlayerDelegate> {
    NSMutableDictionary *sounds;
}
- (IBAction)buttonClick:(id)sender;
- (AVAudioPlayer *)playerForSoundFile:(NSString *)fileName;
@end


@implementation MusicViewController

- (id)init
{
    if (! (self = [super init]))
        return nil;

    sounds = [[NSMutableDictionary alloc] init];

    return self;
}

- (void)dealloc
{
    [sounds release];
    [super dealloc];
}

- (AVAudioPlayer *)playerForSoundFile:(NSString *)fileName
{

    AVAudioPlayer *player = [sounds objectForKey:fileName];

    if (! player) {
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName 
                                                         ofType:@"wav"];
        NSURL *url = [NSURL fileURLWithPath:path];
        player = [[[AVAudioPlayer alloc] initWithContentsOfURL:url] autorelease];
        player.delegate = self;

        [sounds setObject:player forKey:fileName];
    }

    return player;
}

- (IBAction)buttonClick:(id)sender
{
    AVAudioPlayer *theAudio = [self playerForSoundFile:@"Piano1"];
    [theAudio play];
}

@end

请注意,AVAudioPlayer是“自动释放”,然后添加到“声音”字典中。这意味着当字典被销毁时,所有AVAudioPlayers也将如此。如果不清楚,您应该阅读Objective-C中的内存管理:http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html