应用程序在 Xcode 中运行,但存档时崩溃

Posted

技术标签:

【中文标题】应用程序在 Xcode 中运行,但存档时崩溃【英文标题】:App runs in Xcode, but crashes when archived 【发布时间】:2015-08-20 19:33:27 【问题描述】:

我正在归档我的项目,然后使用“导出为 Mac 应用程序”选项。当我尝试运行我导出的独立版本时,它会崩溃!似乎与我的音频有关的一些问题,但我很困惑,因为当我在 Xcode 中运行它时它不会崩溃?有任何想法吗?我的 Xcode 版本是 6.4 顺便说一句。这是崩溃日志的第一部分和最后一部分:

Process:               PianoKeyboardTest [11084]
Path:                  /Users/USER/Desktop/Music Playground.app/Contents/MacOS/PianoKeyboardTest
Identifier:            MikeFenty.PianoKeyboardTest
Version:               1.0 (1)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           PianoKeyboardTest [11084]
User ID:               501

Date/Time:             2015-08-20 15:26:23.107 -0400
OS Version:            Mac OS X 10.10.3 (14D136)
Report Version:        11
Anonymous UUID:        EEE0BF67-07B6-6E29-DF73-5689434AE226

Sleep/Wake UUID:       9511ADBE-72AB-468C-BB96-1A0194562CAA

Time Awake Since Boot: 23000 seconds
Time Since Wake:       14000 seconds

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Application Specific Information:
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: fileURL != nil'
terminating with uncaught exception of type NSException
abort() called

Application Specific Backtrace 1:
0   CoreFoundation                      0x00007fff8a05103c __exceptionPreprocess + 172
1   libobjc.A.dylib                     0x00007fff96b6c76e objc_exception_throw + 43
2   CoreFoundation                      0x00007fff8a050e1a +[NSException raise:format:arguments:] + 106
3   libAVFAudio.dylib                   0x00007fff96de28d8 _Z19AVAE_RaiseExceptionP8NSStringz + 176
4   libAVFAudio.dylib                   0x00007fff96df728a _ZN15AVAudioFileImplC2EP5NSURL19AVAudioCommonFormatbPP7NSError + 220
5   libAVFAudio.dylib                   0x00007fff96df5d25 -[AVAudioFile initForReading:commonFormat:interleaved:error:] + 117
6   PianoKeyboardTest                   0x000000010d298928 PianoKeyboardTest + 137512
7   PianoKeyboardTest                   0x000000010d29834a PianoKeyboardTest + 136010
8   PianoKeyboardTest                   0x000000010d298166 PianoKeyboardTest + 135526
9   PianoKeyboardTest                   0x000000010d29800e PianoKeyboardTest + 135182
10  libdispatch.dylib                   0x00007fff923d1c13 _dispatch_client_callout + 8
11  libdispatch.dylib                   0x00007fff923d1b26 dispatch_once_f + 117
12  PianoKeyboardTest                   0x000000010d297fe6 PianoKeyboardTest + 135142
13  PianoKeyboardTest                   0x000000010d28d47b PianoKeyboardTest + 91259
14  PianoKeyboardTest                   0x000000010d28d3aa PianoKeyboardTest + 91050
15  SpriteKit                           0x000000010d35f2b6 -[SKScene _didMoveToView:] + 76
16  SpriteKit                           0x000000010d32e8f9 -[SKView presentScene:] + 246
17  PianoKeyboardTest                   0x000000010d2941cc PianoKeyboardTest + 119244
18  CoreFoundation                      0x00007fff8a00d45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
19  CoreFoundation                      0x00007fff89efd634 _CFXNotificationPost + 3140
20  Foundation                          0x00007fff887879d1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
21  AppKit                              0x00007fff8fbe1b9b -[NSApplication _postDidFinishNotification] + 291
22  AppKit                              0x00007fff8fbe1906 -[NSApplication _sendFinishLaunchingNotification] + 191
23  AppKit                              0x00007fff8fbdea56 -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 574
24  AppKit                              0x00007fff8fbde495 -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 244
25  Foundation                          0x00007fff887ba748 -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 290
26  Foundation                          0x00007fff887ba5b9 _NSAppleEventManagerGenericHandler + 102
27  AE                                  0x00007fff8aae834c _Z20aeDispatchAppleEventPK6AEDescPS_jPh + 531
28  AE                                  0x00007fff8aae80c9 _ZL25dispatchEventAndSendReplyPK6AEDescPS_ + 31
29  AE                                  0x00007fff8aae7fd3 aeProcessAppleEvent + 295
30  HIToolbox                           0x00007fff8e032c6e AEProcessAppleEvent + 56
31  AppKit                              0x00007fff8fbd7eb2 _DPSNextEvent + 2249
32  AppKit                              0x00007fff8fbd6f68 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 346
33  AppKit                              0x00007fff8fbccbf3 -[NSApplication run] + 594
34  AppKit                              0x00007fff8fb49354 NSApplicationMain + 1832
35  libdyld.dylib                       0x00007fff93ae75c9 start + 1
36  ???                                 0x0000000000000001 0x0 + 1

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff893ad286 __pthread_kill + 10
1   libsystem_c.dylib               0x00007fff92ff7b53 abort + 129
2   libc++abi.dylib                 0x00007fff96f83a21 abort_message + 257
3   libc++abi.dylib                 0x00007fff96fab9d1 default_terminate_handler() + 267
4   libobjc.A.dylib                 0x00007fff96b707d6 _objc_terminate() + 103
5   libc++abi.dylib                 0x00007fff96fa90a1 std::__terminate(void (*)()) + 8
6   libc++abi.dylib                 0x00007fff96fa9113 std::terminate() + 51
7   libobjc.A.dylib                 0x00007fff96b705ff objc_terminate + 9
8   libdispatch.dylib               0x00007fff923d1c27 _dispatch_client_callout + 28
9   libdispatch.dylib               0x00007fff923d1b26 dispatch_once_f + 117
10  MikeFenty.PianoKeyboardTest     0x000000010d297fe6 0x10d277000 + 135142
11  MikeFenty.PianoKeyboardTest     0x000000010d28d47b 0x10d277000 + 91259
12  MikeFenty.PianoKeyboardTest     0x000000010d28d3aa 0x10d277000 + 91050
13  com.apple.SpriteKit             0x000000010d35f2b6 -[SKScene _didMoveToView:] + 76
14  com.apple.SpriteKit             0x000000010d32e8f9 -[SKView presentScene:] + 246
15  MikeFenty.PianoKeyboardTest     0x000000010d2941cc 0x10d277000 + 119244
16  com.apple.CoreFoundation        0x00007fff8a00d45c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
17  com.apple.CoreFoundation        0x00007fff89efd634 _CFXNotificationPost + 3140
18  com.apple.Foundation            0x00007fff887879d1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
19  com.apple.AppKit                0x00007fff8fbe1b9b -[NSApplication _postDidFinishNotification] + 291
20  com.apple.AppKit                0x00007fff8fbe1906 -[NSApplication _sendFinishLaunchingNotification] + 191
21  com.apple.AppKit                0x00007fff8fbdea56 -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 574
22  com.apple.AppKit                0x00007fff8fbde495 -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 244
23  com.apple.Foundation            0x00007fff887ba748 -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 290
24  com.apple.Foundation            0x00007fff887ba5b9 _NSAppleEventManagerGenericHandler + 102
25  com.apple.AE                    0x00007fff8aae834c aeDispatchAppleEvent(AEDesc const*, AEDesc*, unsigned int, unsigned char*) + 531
26  com.apple.AE                    0x00007fff8aae80c9 dispatchEventAndSendReply(AEDesc const*, AEDesc*) + 31
27  com.apple.AE                    0x00007fff8aae7fd3 aeProcessAppleEvent + 295
28  com.apple.HIToolbox             0x00007fff8e032c6e AEProcessAppleEvent + 56
29  com.apple.AppKit                0x00007fff8fbd7eb2 _DPSNextEvent + 2249
30  com.apple.AppKit                0x00007fff8fbd6f68 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 346
31  com.apple.AppKit                0x00007fff8fbccbf3 -[NSApplication run] + 594
32  com.apple.AppKit                0x00007fff8fb49354 NSApplicationMain + 1832
33  libdyld.dylib                   0x00007fff93ae75c9 start + 1

...

编辑:导致错误的代码

-(AVAudioPCMBuffer*) loadSoundIntoBuffer:(NSString *)filename

    // load the collision sound into a buffer
    NSURL *soundFileURL = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:filename ofType:@"mp3"]];
    NSAssert(soundFileURL, @"Error creating URL to sound file");
    NSError *error;
    AVAudioFile *soundFile = [[AVAudioFile alloc] initForReading:soundFileURL commonFormat:AVAudioPCMFormatFloat32 interleaved:NO error:&error];
    NSAssert(soundFile != nil, @"Error creating soundFile, %@", error.localizedDescription);

    AVAudioPCMBuffer *outputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:soundFile.processingFormat frameCapacity:(AVAudioFrameCount)soundFile.length];
    NSAssert([soundFile readIntoBuffer:outputBuffer error:&error], @"Error reading file into buffer, %@", error.localizedDescription);

    return outputBuffer;

编辑: 我用 aiff 文件替换了我的 mp3 文件,最初的问题已经改变。该应用程序仍然在 Xcode 之外崩溃,但不再在主线程上崩溃,如下所示。这与音频有关。下面是处理音频的类的代码。

AudioEngine.m

#import "AudioEngine.h"
#import <AVFoundation/AVFoundation.h>
#import "GameData.h"

@interface AudioEngine()

@property AVAudioEngine *engine;
@property AVAudioMixerNode *mixer;
@property NSMutableDictionary *musicPlayers;
@property NSMutableDictionary *sfxPlayers;
@property NSMutableDictionary *musicBuffers;
@property NSMutableDictionary *sfxBuffers;

@property float musicVolumePercent;
@property float sfxVolumePercent;
@property float fadeVolume;
@property float timerCount;

@end

@implementation AudioEngine

int const FADE_ITERATIONS = 10;

+(instancetype) sharedData 
    static AudioEngine *sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
        sharedInstance = [[self alloc] init];
        [sharedInstance startEngine];
    );

    return sharedInstance;


-(instancetype) init 
    if (self = [super init]) 
        _engine = [[AVAudioEngine alloc] init];
        _mixer = [_engine mainMixerNode];


        _sfxPlayers = [NSMutableDictionary dictionary];
        _sfxBuffers = [NSMutableDictionary dictionary];

        [self setVolumePercentages];
        [self initMusic];
        //[self initSfx]; //do later after music done
    
    return self;


-(void) initMusic 
    _musicPlayers = [NSMutableDictionary dictionary];
    _musicBuffers = [NSMutableDictionary dictionary];

    NSString *audioInfoPList = [[NSBundle mainBundle] pathForResource: @"AudioInfo" ofType: @"plist"];
    NSDictionary *audioInfoData = [NSDictionary dictionaryWithContentsOfFile:audioInfoPList];

    for (NSString *musicFileName in audioInfoData[@"music"]) 
        AVAudioPCMBuffer *buffer = [self loadSoundIntoBuffer:musicFileName];
        [_musicBuffers setObject:buffer forKey:musicFileName];
        AVAudioPlayerNode *player = [[AVAudioPlayerNode alloc] init];
        [_engine attachNode:player];
        [_engine connect:player to:_mixer format:buffer.format];
        [_musicPlayers setObject:player forKey:musicFileName];
    


-(void) initSfx 
    _sfxPlayers = [NSMutableDictionary dictionary];
    _sfxBuffers = [NSMutableDictionary dictionary];

    NSString *audioInfoPList = [[NSBundle mainBundle] pathForResource: @"AudioInfo" ofType: @"plist"];
    NSDictionary *audioInfoData = [NSDictionary dictionaryWithContentsOfFile:audioInfoPList];

    for (NSString *sfxFileName in audioInfoData[@"sfx"]) 
        AVAudioPCMBuffer *buffer = [self loadSoundIntoBuffer:sfxFileName];
        [_sfxBuffers setObject:buffer forKey:sfxFileName];
        AVAudioPlayerNode *player = [[AVAudioPlayerNode alloc] init];
        [_engine attachNode:player];
        [_engine connect:player to:_mixer format:buffer.format];
        [_sfxPlayers setObject:player forKey:sfxFileName];
    


-(AVAudioPCMBuffer*) loadSoundIntoBuffer:(NSString *)filename

    NSURL *soundFileURL = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:filename ofType:@"aif"]];
    NSAssert(soundFileURL, @"Error creating URL to sound file");
    NSError *error;
    //AVAudioFile *soundFile = [[AVAudioFile alloc] initForReading:soundFileURL commonFormat:AVAudioPCMFormatFloat32 interleaved:NO error:&error];
    AVAudioFile *soundFile = [[AVAudioFile alloc] initForReading:soundFileURL error:&error];
    NSAssert(soundFile != nil, @"Error creating soundFile, %@", error.localizedDescription);

    AVAudioPCMBuffer *outputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:soundFile.processingFormat frameCapacity:(AVAudioFrameCount)soundFile.length];
    NSAssert([soundFile readIntoBuffer:outputBuffer error:&error], @"Error reading file into buffer, %@", error.localizedDescription);

    return outputBuffer;


-(void)startEngine 
    [_engine startAndReturnError:nil];


-(void) playSfxFile:(NSString*)file 
    AVAudioPlayerNode *player = [_sfxPlayers objectForKey:file];
    AVAudioPCMBuffer *buffer = [_sfxBuffers objectForKey:file];
    [player scheduleBuffer:buffer atTime:nil options:AVAudioPlayerNodeBufferInterrupts completionHandler:nil];
    [player setVolume:_sfxVolumePercent];
    [player play];


-(void) playMusicFile:(NSString*)file 
    AVAudioPlayerNode *player = [_musicPlayers objectForKey:file];
    AVAudioPCMBuffer *buffer = [_musicBuffers objectForKey:file];
    [player scheduleBuffer:buffer atTime:nil options:AVAudioPlayerNodeBufferLoops completionHandler:nil];
    [player setVolume:_musicVolumePercent];
    [player play];


-(void) stopMusicFile:(NSString*)file 
    AVAudioPlayerNode *player = [_musicPlayers objectForKey:file];

    if ([player isPlaying]) 
        _timerCount = FADE_ITERATIONS;
        _fadeVolume = _musicVolumePercent;
        [self fadeOutMusicForPlayer:player];
    



-(void) pauseMusic:(NSString*)file 
    AVAudioPlayerNode *player = [_musicPlayers objectForKey:file];
    if ([player isPlaying]) 
        [player pause];
    


-(void) unpauseMusic:(NSString*)file 
    AVAudioPlayerNode *player = [_musicPlayers objectForKey:file];
    [player play];


-(void) fadeOutMusicForPlayer:(AVAudioPlayerNode*)player 
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(handleTimer:) userInfo:player repeats:YES];


-(void) handleTimer:(NSTimer*)timer 
    AVAudioPlayerNode *player = (AVAudioPlayerNode*)timer.userInfo;
    if (_timerCount > 0) 
        _timerCount--;
        AVAudioPlayerNode *player = (AVAudioPlayerNode*)timer.userInfo;
        _fadeVolume = _musicVolumePercent * (_timerCount / FADE_ITERATIONS);
        [player setVolume:_fadeVolume];
    
    else 
        [player stop];
        [player setVolume:_musicVolumePercent];
        [timer invalidate];
    


-(void) setVolumePercentages 
    NSString *musicVolumeString = [[GameData sharedGameData].settings objectForKey:@"musicVolume"];
    _musicVolumePercent = [[[musicVolumeString componentsSeparatedByCharactersInSet:
                             [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
                            componentsJoinedByString:@""] floatValue] / 100;
    NSString *sfxVolumeString = [[GameData sharedGameData].settings objectForKey:@"sfxVolume"];
    _sfxVolumePercent = [[[sfxVolumeString componentsSeparatedByCharactersInSet:
                           [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
                          componentsJoinedByString:@""] floatValue] / 100;

    //immediately sets music to new volume
    for (AVAudioPlayerNode *player in [_musicPlayers allValues]) 
        [player setVolume:_musicVolumePercent];
    


@end

新的崩溃日志

【问题讨论】:

发布目标中可能缺少一个文件。您是否使用多个目标?另请附上处理此文件打开的代码:[AVAudioFile initForReading] 我的部署目标是 OS X 10.10,所以不,我只有一个目标。我已将代码附加到问题的底部。 您附加了调试信息,而不是代码本身。您的 fileURL 似乎在某个地方为零。显示代码如何为音频文件生成路径 我在写完评论后附上了它。我没想到你会这么快检查! 【参考方案1】:

捆绑包中似乎缺少您的一个文件。

转到“构建阶段 -> 复制捆绑资源”并确保所有文件都在那里 - 特别是带有“mp3”扩展名的文件。 还要确保它们有正确的区分大小写的名称。

【讨论】:

是的,在您发表评论后,我又检查了几个小时。我正在从 plist 文件中读取名称。据我所知,所有的名字都匹配。 17 个 .mp3 文件中有 17 个都包含在“复制捆绑资源”部分中。我正在阅读有关更改运行方案的信息,以便它使用Release 构建配置运行,当我这样运行它时它会崩溃。显然,这会导致它以与存档时相同的方式运行。调试器只显示汇编代码,对我来说没用。 我 100% 确定的一件事是我的班级 AudioEngine(这是一个单例)管理音频文件的播放,这是问题所在。我刚刚再次完成了我的项目的归档,并且在加载的第一个场景中删除了对 AudioEngine 的调用,并且应用程序完美运行。即使我将加载限制为仅几个 mp3 文件,它也会崩溃,所以这让我相信我从磁盘加载文件的方式是错误的。它在 Xcode 中工作!这太令人困惑了:( 我决定用 aiff 文件替换我的 mp3 文件。崩溃发生在与以前不同的线程上。我认为错误是格式。它是线程 13 而不是主线程。 我想我找到了问题所在。根据 WWDC 2014 会话 501,演讲者(在 54:17)将音频文件分块读入缓冲区,并使缓冲区帧容量为 128 * 1024L。一旦我将代码转换为以较小的块将文件读入缓冲区,我就不会再崩溃了,但是我遇到了一个新问题,即文件不是从头开始播放,而是从缓冲区最后一帧的开头开始播放。 【参考方案2】:

崩溃的原因是我正在读入AVAudioPCMBuffer 的音乐文件太大。我的解决方案是限制缓冲区的大小,并根据音频文件的帧数使用多个缓冲区。解决方法可以看here

【讨论】:

以上是关于应用程序在 Xcode 中运行,但存档时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 6 在提交存档时崩溃

没有存档的 Xcode 符号

问题 XCode 8,Swift 2.3 存档版本在 IOS 9.2.1 -> IOS 9.0 上启动时崩溃

Xcode 构建和运行应用程序工作但存档失败(颤振)

Fabric Answer 在从 Xcode 10 和 iOS 12 开始时崩溃 iOS 应用程序

从试飞下载时应用程序在启动时崩溃