异步加载viewDidLoad中的声音资源崩溃

时间:2012-02-17 02:40:56

标签: ios multithreading uiviewcontroller exc-bad-access nsblockoperation

所有

我正在尝试在加载UIViewController时异步加载一组声音。几乎在同一时间,我(偶尔)也在我的ViewController层次结构的顶部放置一个UIView来呈现帮助覆盖。当我这样做时,应用程序崩溃与一个坏exec。如果未添加视图,则应用程序不会崩溃。我的ViewController看起来像这样:

- (void)viewDidLoad
{
    [super viewDidLoad];

    __soundHelper = [[SoundHelper alloc] initWithSounds];

    // Other stuff
}

- (void)viewDidAppear:(BOOL)animated
    {
    // ****** Set up the Help Screen
    self.coachMarkView = [[FHSCoachMarkView alloc] initWithImageName:@"help_GradingVC" 
                                                    coveringView:self.view 
                                                     withOpacity:0.9 
                                                    dismissOnTap:YES 
                                                    withDelegate:self];

    [self.coachMarkView showCoachMarkView];
    [super viewDidAppear:animated];
}

SoundHelper的主要异步加载方法(从'initWithSounds'调用)如下所示:

// Helper method that loads sounds as needed
- (void)loadSounds {

    // Run this loading code in a separate thread
    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
    NSBlockOperation *loadSoundsOp = [NSBlockOperation blockOperationWithBlock:^{
        // Find all sound files (*.caf) in resource bundles
        __soundCache = [[NSMutableDictionary alloc]initWithCapacity:0];

        NSString * sndFileName;
        NSArray *soundFiles = [[NSBundle mainBundle] pathsForResourcesOfType:STR_SOUND_EXT inDirectory:nil];

        // Loop through all of the sounds found
        for (NSString * soundFileNamePath in soundFiles) {
            // Add the sound file to the dictionary
            sndFileName = [[soundFileNamePath lastPathComponent] lowercaseString];
            [__soundCache setObject:[self soundPath:soundFileNamePath] forKey:sndFileName];
        }

        // From: https://stackoverflow.com/questions/7334647/nsoperationqueue-and-uitableview-release-is-crashing-my-app
        [self performSelectorOnMainThread:@selector(description) withObject:nil waitUntilDone:NO];
    }];
    [operationQueue addOperation:loadSoundsOp];
}

当块退出时,似乎发生了崩溃。 init的{​​{1}}看起来像这样:

FHSCoachMarkView

我尝试使用- (FHSCoachMarkView *)initWithImageName:(NSString *) imageName coveringView:(UIView *) view withOpacity:(CGFloat) opacity dismissOnTap:(BOOL) dismissOnTap withDelegate:(id<FHSCoachMarkViewDelegate>) delegateID { // Reset Viewed Coach Marks if User Setting is set to show them [self resetSettings]; __coveringView = view; self = [super initWithFrame:__coveringView.frame]; if (self) { // Record the string for later reference __coachMarkName = [NSString stringWithString:imageName]; self.delegate = delegateID; UIImage * image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:@"png"]]; // ****** Configure the View Hierarchy UIImageView *imgView = [[UIImageView alloc] initWithImage:image]; [self addSubview:imgView]; [__coveringView.superview insertSubview:self aboveSubview:__coveringView]; // ****** Configure the View Hierarchy with the proper opacity __coachMarkViewOpacity = opacity; self.hidden = YES; self.opaque = NO; self.alpha = __coachMarkViewOpacity; imgView.hidden = NO; imgView.opaque = NO; imgView.alpha = __coachMarkViewOpacity; // ****** Configure whether the coachMark can be dismissed when it's body is tapped __dismissOnTap = dismissOnTap; // If it is dismissable, set up a gesture recognizer if (__dismissOnTap) { UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(coachMarkWasTapped:)]; [self addGestureRecognizer:tapGesture]; } } return self; } NSBlockOperation同时调用异步块,两者都有相同的结果。另外,我完全删除了aysnch调用并在主线程上加载了声音。这很好。我也尝试过@Jason在NSOperationQueue and UITableView release is crashing my app中提出的解决方案,但同样的事情也发生在那里。

这实际上是在FHSCoachMarkView中添加视图的问题,还是可能与访问dispatch_async的事实有关?我对iOS中的异步编码有点新意,所以我有点亏。任何帮助将不胜感激!

谢谢, 斯科特

1 个答案:

答案 0 :(得分:0)

我想到了这一点:我在SoundHelper对象(NSUserDefaultsDidChangeNotification)上设置了一个侦听器,该对象在NSUserDefaults发生更改时进行了侦听,并在用户默认值指示时加载了声音。 FHSCoachMarkView也在对NSUserDefaults进行更改。在SoundHelper中,我没有正确检查哪些默认值被更改,因此每次进行更改时都会调用异步声音加载方法。因此,多个线程试图修改__soundCache实例变量。它似乎不喜欢那样。

问题:这是回答您自己问题的正确方法吗?或者我应该只是对自己的问题添加评论吗?

感谢。