exc_bad_access 在设备上推进模拟时

exc_bad_access when advancing simulation on device

此错误仅发生在实际设备上。在Xcode6的模拟器上运行时,不崩溃。

我正在创建外部 space 并且有随机的流星划过天空。 在场景中,调用 [goToSpace] 设置星场,使用三个 SKEmitterNode 来模拟深度。然后初始化一个定时器,发送星星射击。

在星空的初始化中,需要提前模拟三个SKEmitterNode,才能得到满天的星空。当调用行 [emitterNode1 advanceSimulationTime: lifetime] 时,我得到 exc_bad_access。我按照教程启用了 NSZombie,但没有帮助。

我终其一生都无法弄清楚为什么我会 exc_bad_access。我使用 Parse.com 的崩溃报告,它给出了这个堆栈:

> Stack Trace Thread 0 (crashed) 0 libsystem_platform.dylib
> OSSpinLockLock @ 0x4 1 SpriteKit SKSpinLockSync(int*, void ()
> block_pointer) @ 0x20 2 SpriteKit
> -[SKTexture loadImageData] @ 0xec 3 SpriteKit
> -[SKTexture size] @ 0x28 4 SpriteKit SKCEmitterSprite::update(double) @ 0x117c 5 CorpBoard @ 0x48d44 6 CorpBoard @ 0xfbc50 7 CorpBoard @
> 0xfa6f0 8 CorpBoard @ 0xfa070 9 UIKit
> -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] @ 0x21c 10 UIKit
> -[UITableView _updateVisibleCellsNow:isRecursive:] @ 0x934 11 UIKit
> -[UITableView layoutSubviews] @ 0xa8 12 UIKit
> -[UIView(CALayerDelegate) layoutSublayersOfLayer:] @ 0x238 13 QuartzCore
> -[CALayer layoutSublayers] @ 0xa4 14 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) @ 0x13c 15 QuartzCore
> CA::Layer::layout_and_display_if_needed(CA::Transaction*) @ 0x1c 16
> QuartzCore CA::Context::commit_transaction(CA::Transaction*) @ 0x110
> 17 QuartzCore CA::Transaction::commit() @ 0x1b0 18 QuartzCore
> CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned
> long, void*) @ 0x4c 19 CoreFoundation
> __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ @ 0x1c 20 CoreFoundation
> __CFRunLoopDoObservers @ 0x164 21 CoreFoundation
> __CFRunLoopRun @ 0x340 22 CoreFoundation CFRunLoopRunSpecific @ 0x188 23 GraphicsServices GSEventRunModal @ 0xa4 24 UIKit UIApplicationMain
> @ 0x5cc 25 CorpBoard @ 0x5be80 26 libdyld.dylib start @ 0x0 Thread 1 0
> libsystem_kernel.dylib kevent64 @ 0x8 1 libdispatch.dylib
> _dispatch_mgr_invoke @ 0x110 2 libdispatch.dylib
> _dispatch_mgr_thread @ 0x30 Thread 2 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0 Thread 3 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0 Thread 4 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0 Thread 5 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0 Thread 6 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0 Thread 7 0 libsystem_kernel.dylib mach_msg_trap @ 0x8 1
> libsystem_kernel.dylib mach_msg @ 0x44 2 CoreFoundation
> __CFRunLoopServiceMachPort @ 0xc4 3 CoreFoundation
> __CFRunLoopRun @ 0x3a8 4 CoreFoundation CFRunLoopRunSpecific @ 0x188 5 Foundation
> -[NSRunLoop(NSRunLoop) runMode:beforeDate:] @ 0x138 6 Foundation
> -[NSRunLoop(NSRunLoop) run] @ 0x5c 7 CorpBoard @ 0x206a28 8 Foundation
> __NSThread__main__ @ 0x42c 9 libsystem_pthread.dylib
> _pthread_body @ 0xa0 10 libsystem_pthread.dylib
> _pthread_start @ 0x9c 11 libsystem_pthread.dylib thread_start @ 0x0 Thread 8 0 libsystem_kernel.dylib mach_msg_trap @ 0x8 1
> libsystem_kernel.dylib mach_msg @ 0x44 2 CoreFoundation
> __CFRunLoopServiceMachPort @ 0xc4 3 CoreFoundation
> __CFRunLoopRun @ 0x3a8 4 CoreFoundation CFRunLoopRunSpecific @ 0x188 5 CFNetwork
> +[NSURLConnection(Loader) _resourceLoadLoop:] @ 0x1b4 6 Foundation
> __NSThread__main__ @ 0x42c 7 libsystem_pthread.dylib
> _pthread_body @ 0xa0 8 libsystem_pthread.dylib
> _pthread_start @ 0x9c 9 libsystem_pthread.dylib thread_start @ 0x0 Thread 9 0 libsystem_kernel.dylib
> __select @ 0x8 1 CoreFoundation
> __CFSocketManager @ 0x290 2 libsystem_pthread.dylib
> _pthread_body @ 0xa0 3 libsystem_pthread.dylib
> _pthread_start @ 0x9c 4 libsystem_pthread.dylib thread_start @ 0x0 Thread 10 0 libsystem_kernel.dylib mach_msg_trap @ 0x8 1
> libsystem_kernel.dylib mach_msg @ 0x44 2 CoreFoundation
> __CFRunLoopServiceMachPort @ 0xc4 3 CoreFoundation
> __CFRunLoopRun @ 0x3a8 4 CoreFoundation CFRunLoopRunSpecific @ 0x188 5 CoreFoundation CFRunLoopRun @ 0x6c 6 CoreMotion @ 0x4298c 7
> libsystem_pthread.dylib
> _pthread_body @ 0xa0 8 libsystem_pthread.dylib
> _pthread_start @ 0x9c 9 libsystem_pthread.dylib thread_start @ 0x0 Thread 11 0 libsystem_kernel.dylib
> __workq_kernreturn @ 0x8 1 libsystem_pthread.dylib
> _pthread_wqthread @ 0x3dc 2 libsystem_pthread.dylib start_wqthread @ 0x0

相关代码:

NSTimer *space;

-(void)goToSpace {

    [self shootingStar];

    double lifetime;
    SKEmitterNode *emitterNode1 = [self starFieldEmitter:[SKColor lightGrayColor] starSpeedY:1 starsPerSecond:.1 starScaleFactor:0.08];

    lifetime = self.frame.size.height * [[UIScreen mainScreen] scale] / 1;
    [emitterNode1 advanceSimulationTime:lifetime];
    emitterNode1.zPosition = -10;
    [self addChild:emitterNode1];

    SKEmitterNode *emitterNode2 = [self starFieldEmitter:[SKColor lightGrayColor] starSpeedY:.8 starsPerSecond:.08 starScaleFactor:0.06];
    emitterNode2.zPosition = -11;
    lifetime = self.frame.size.height * [[UIScreen mainScreen] scale] / .8;
    [emitterNode2 advanceSimulationTime:lifetime];
    [self addChild:emitterNode2];

    SKEmitterNode *emitterNode3 = [self starFieldEmitter:[SKColor grayColor] starSpeedY:.5 starsPerSecond:.5 starScaleFactor:0.03];
    emitterNode3.zPosition = -12;
    lifetime = self.frame.size.height * [[UIScreen mainScreen] scale] / .5;
    [emitterNode3 advanceSimulationTime:lifetime];
    [self addChild:emitterNode3];

    space = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(shootingStar) userInfo:nil repeats:YES];

}

-(SKEmitterNode *)starFieldEmitter:(SKColor *)color starSpeedY:(CGFloat)starSpeedY starsPerSecond:(CGFloat)starsPerSecond starScaleFactor:(CGFloat) starScaleFactor {

    SKEmitterNode *emitterNode = [SKEmitterNode node];

    CGFloat lifetime = self.frame.size.height * [[UIScreen mainScreen] scale] / starSpeedY;

    emitterNode.particleTexture = [SKTexture textureWithImage:[UIImage imageNamed:@"stars"]];
    emitterNode.particleBirthRate = starsPerSecond;
    emitterNode.particleColor = [SKColor lightGrayColor];
    emitterNode.particleSpeed = starSpeedY * -1;
    emitterNode.particleScale = starScaleFactor;
    emitterNode.particleColorBlendFactor = 1;
    emitterNode.particleLifetime = lifetime;

    int rndValue = 1 + arc4random() % (45 - 1);
    emitterNode.particleRotation = rndValue;

    emitterNode.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height);
    emitterNode.particlePositionRange = CGVectorMake(self.frame.size.width, self.frame.size.height);
    return emitterNode;
}

-(BOOL) getYesOrNo {

    int tmp = (arc4random() % 30)+1;
    if(tmp % 5 == 0)
        return YES;
    return NO;
}

-(void)shootingStar {

    BOOL left = [self getYesOrNo];
    int xPos = 0;
    int height = self.frame.size.height;
    int yPos = 1 + arc4random() % (height - 1);
    if (left) {
        xPos = -50;
    } else {
        xPos = self.frame.size.width + 50;
    }

    SKEmitterNode *shootingstar = [SKEmitterNode node];
    shootingstar =  [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"spark" ofType:@"sks"]];

    CGPoint xy = CGPointMake(xPos, yPos);
    shootingstar.position = xy;
    shootingstar.name = @"shootingStar";
    shootingstar.zPosition = -2.0;
    shootingstar.targetNode = self.scene;
    [self addChild:shootingstar];

    //make random size to simulate distance
    float val = [self randFloatBetween:.1 and:.5];
    SKAction *scale = [SKAction scaleBy:val duration:0];
    [shootingstar runAction: scale completion:nil];

    //now set speed depending on size (smaller = farther = slower)
    int dur = 0;
    if (val < .2) dur = 5;
    else if (val < .35) dur = 3;
    else dur = 2;

    int moveY = -500 + arc4random() % (500 - -500);
    int moveX;
    if (left) {
        moveX = 500;
    } else {
        moveX = -500;
    }
    SKAction *move = [SKAction moveByX:moveX y:moveY duration:dur];
    int waitDuration = 2 + arc4random() % (5 - 2);
    SKAction *wait = [SKAction waitForDuration:waitDuration];
    SKAction *sequence = [SKAction sequence:@[wait, move]];

    [shootingstar runAction:sequence completion:^{
        [shootingstar removeFromParent];
        //[self shootingStar];
    }];
}

-(float) randFloatBetween:(float)low and:(float)high {

    float diff = high - low;
    return (((float) rand() / RAND_MAX) * diff) + low;
}

我参考了以下几个答案解决了我的问题:this similar question

就我而言,我用于星星的图像 Stars.png 在我的项目目录中。我将其移至 Images.xcassets 并添加了图像的 @2x 和 @3x 版本。这解决了我的问题,虽然我不完全明白为什么。