应用程序在 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 8,Swift 2.3 存档版本在 IOS 9.2.1 -> IOS 9.0 上启动时崩溃