Obj-C iPhone: управление памятью - PullRequest
0 голосов
/ 02 марта 2011

iPhone новичок здесь, я создаю простое музыкальное приложение для iPhone под названием Piano Master, которое производит звук при нажатии кнопки.

Вот мой код:

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. Каковы ваши лучшие идеи о том, как эффективно справиться с этой проблемой памяти? Я думал о создании экземпляра AVAudioPlayer для MusicViewController и использовании этого, но все равно будет проблема с памятью, если я буду продолжать выделять новый AVAudioPlayer каждый раз ... Любая помощь полезна, спасибо.

Ответы [ 4 ]

1 голос
/ 02 марта 2011

Сохраните ваши аудиоплееры в другом объекте контроллера (MVC) где-нибудь после их инициализации. Затем просто повторно используйте существующие, вызывая объект аудиоконтроллера из контроллера представления.

0 голосов
/ 02 марта 2011

Если вы захотите воспроизвести более двух разных аудиофайлов, словарь 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

0 голосов
/ 02 марта 2011

MusicViewController.h file

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

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

- (IBAction)buttonClick: (id)sender;

@end

MusicViewController.m file

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

Возможно, вы также захотите освободить Audio в методе viewDidUnload, чтобы освободить память, убедитесь, что вы установилиуказатель на нулевое послесловие, подобное этому:

- (void)viewDidUnload {
    [_theAudio release];
    _theAudio = nil;
}
0 голосов
/ 02 марта 2011

hotpaw2 ответ, что я бы предложил сделать.

Но главное, чего вам не хватает, - это управления памятью. Вы должны добавить:

[theAudio play];
[theAudio release];

То, что вы выделяете в памяти, вы должны освободить. Таким образом, даже если вы создаете AVAudioPlayer каждый раз. Вы освободите используемую память. Таким образом, вы не получите никаких утечек.

...