Guideline 2.1 - Performance - App Completeness

Hi,


I uploaded my first game app to review and review result is "rejected". They sent me crash logs but i didn't understand anything. Is it possible to explain me what is the issue here? It works on my device and all of simulator devices.


Guideline 2.1 - Performance - App Completeness

Your app continued to crash on iPad running iOS 12.2 on WiFi when we were playing the game.


Date/Time: 2019-03-28 03:51:34.1797 +0900

Launch Time: 2019-03-28 03:51:25.7709 +0900

OS Version: iPhone OS 12.2 (16E227)

Baseband Version: 7.55.01

Report Version: 104


Exception Type: EXC_BREAKPOINT (SIGTRAP)

Exception Codes: 0x0000000000000001, 0x00000001010f0a4c

Termination Signal: Trace/BPT trap: 5

Termination Reason: Namespace SIGNAL, Code 0x5

Terminating Process: exc handler [1752]

Triggered by Thread: 0


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

Thread 0 Crashed:

0 Save The Princess 0x00000001010f0a4c 0x1010e8000 + 35404

1 Save The Princess 0x00000001010f0a7c 0x1010e8000 + 35452

2 PhysicsKit 0x00000001f8159e48 0x1f8145000 + 85576

3 PhysicsKit 0x00000001f8157e64 0x1f8145000 + 77412

4 SpriteKit 0x00000002046c7a48 0x20468d000 + 240200

5 SpriteKit 0x00000002046ec114 0x20468d000 + 389396

6 SpriteKit 0x00000002046e77f4 0x20468d000 + 370676

7 SpriteKit 0x00000002046e6bf8 0x20468d000 + 367608

8 SpriteKit 0x00000002046e9c54 0x20468d000 + 379988

9 SpriteKit 0x000000020472cc18 0x20468d000 + 654360

10 QuartzCore 0x00000001f1f21194 0x1f1f10000 + 70036

11 IOKit 0x00000001ede1b718 0x1ede16000 + 22296

12 CoreFoundation 0x00000001edb2ad30 0x1edaa7000 + 539952

13 CoreFoundation 0x00000001edb51934 0x1edaa7000 + 698676

14 CoreFoundation 0x00000001edb51080 0x1edaa7000 + 696448

15 CoreFoundation 0x00000001edb4bea4 0x1edaa7000 + 675492

16 CoreFoundation 0x00000001edb4b354 0x1edaa7000 + 672596

17 GraphicsServices 0x00000001efd4b79c 0x1efd41000 + 42908

18 UIKitCore 0x0000000219d0cb68 0x219452000 + 9153384

19 Save The Princess 0x00000001010f10c0 0x1010e8000 + 37056

20 libdyld.dylib 0x00000001ed6118e0 0x1ed610000 + 6368



Thread 1:

0 libsystem_pthread.dylib 0x00000001ed7e2cd0 0x1ed7d4000 + 60624



Thread 2:

0 libsystem_pthread.dylib 0x00000001ed7e2cd0 0x1ed7d4000 + 60624



Thread 3:

0 libsystem_pthread.dylib 0x00000001ed7e2cd0 0x1ed7d4000 + 60624



Thread 4 name: com.apple.uikit.eventfetch-thread

Thread 4:

0 libsystem_kernel.dylib 0x00000001ed7520f4 0x1ed73a000 + 98548

1 libsystem_kernel.dylib 0x00000001ed7515a0 0x1ed73a000 + 95648

2 CoreFoundation 0x00000001edb50cb4 0x1edaa7000 + 695476

3 CoreFoundation 0x00000001edb4bbc4 0x1edaa7000 + 674756

4 CoreFoundation 0x00000001edb4b354 0x1edaa7000 + 672596

5 Foundation 0x00000001ee518fcc 0x1ee511000 + 32716

6 Foundation 0x00000001ee518e5c 0x1ee511000 + 32348

7 UIKitCore 0x0000000219df2540 0x219452000 + 10093888

8 Foundation 0x00000001ee6456e4 0x1ee511000 + 1263332

9 libsystem_pthread.dylib 0x00000001ed7df2c0 0x1ed7d4000 + 45760

10 libsystem_pthread.dylib 0x00000001ed7df220 0x1ed7d4000 + 45600

11 libsystem_pthread.dylib 0x00000001ed7e2cdc 0x1ed7d4000 + 60636



Thread 5 name: JavaScriptCore bmalloc scavenger

Thread 5:

0 libsystem_kernel.dylib 0x00000001ed75cee4 0x1ed73a000 + 143076

1 libsystem_pthread.dylib 0x00000001ed7d7cf8 0x1ed7d4000 + 15608

2 libc++.1.dylib 0x00000001ecd34090 0x1ecd2c000 + 32912

3 JavaScriptCore 0x00000001f4d21238 0x1f4c97000 + 565816

4 JavaScriptCore 0x00000001f4d2522c 0x1f4c97000 + 582188

5 JavaScriptCore 0x00000001f4d249a4 0x1f4c97000 + 580004

6 JavaScriptCore 0x00000001f4d263e4 0x1f4c97000 + 586724

7 libsystem_pthread.dylib 0x00000001ed7df2c0 0x1ed7d4000 + 45760

8 libsystem_pthread.dylib 0x00000001ed7df220 0x1ed7d4000 + 45600

9 libsystem_pthread.dylib 0x00000001ed7e2cdc 0x1ed7d4000 + 60636



Thread 6 name: WebThread

Thread 6:

0 libsystem_kernel.dylib 0x00000001ed7520f4 0x1ed73a000 + 98548

1 libsystem_kernel.dylib 0x00000001ed7515a0 0x1ed73a000 + 95648

2 CoreFoundation 0x00000001edb50cb4 0x1edaa7000 + 695476

3 CoreFoundation 0x00000001edb4bbc4 0x1edaa7000 + 674756

4 CoreFoundation 0x00000001edb4b354 0x1edaa7000 + 672596

5 WebCore 0x00000001f67a5480 0x1f63dc000 + 3970176

6 libsystem_pthread.dylib 0x00000001ed7df2c0 0x1ed7d4000 + 45760

7 libsystem_pthread.dylib 0x00000001ed7df220 0x1ed7d4000 + 45600

8 libsystem_pthread.dylib 0x00000001ed7e2cdc 0x1ed7d4000 + 60636


I didn't copy all logs because it's very long. I hope it's enough.


I think this performance issue is about my enemies. Let me show you how my enemies work:


In didMove() function:

self.run(SKAction.repeatForever(SKAction.sequence([SKAction.run {
            self.spwanEnemies()
            }, SKAction.wait(forDuration: 7)])))


spwanEnemies() function:

func spwanEnemies() {
        let randomEnemyType = Enemies(rawValue: GKRandomSource.sharedRandom().nextInt(upperBound: 4))!
      
        if let newEnemy = createEnemy(type: randomEnemyType) {
            self.addChild(newEnemy)
        }
      
        self.enumerateChildNodes(withName: "ENEMY") { (node: SKNode, nil) in
            if node.position.y < -100 || node.position.y > self.size.height + 100 {
                node.removeFromParent()
            }
        }
    }


createEnemy() function:

func createEnemy(type:Enemies) -> SKSpriteNode? {
        let enemySprite = SKSpriteNode()
        enemySprite.name = "ENEMY"

        switch type {
        case .enemy1:
            enemySprite.texture = SKTexture(imageNamed: "enemy1")
            enemySprite.size = CGSize(width: 41, height: 40)
            enemySprite.position.x = self.size.width / 2;
            enemySprite.position.y = 0;
            enemySprite.physicsBody = SKPhysicsBody(texture: enemySprite.texture!, size: enemySprite.size)
            enemySprite.physicsBody?.velocity = CGVector(dx: Int.random(in: -50 ..< 50), dy: Int.random(in: 50 ..< 60))

            return enemySprite
        case .enemy2:
            enemySprite.texture = SKTexture(imageNamed: "enemy2")
            enemySprite.size = CGSize(width: 38, height: 40)
            enemySprite.position.x = self.size.width / 3;
            enemySprite.position.y = 0;
            enemySprite.physicsBody = SKPhysicsBody(texture: enemySprite.texture!, size: enemySprite.size)
            enemySprite.physicsBody?.velocity = CGVector(dx: Int.random(in: -50 ..< 50), dy: Int.random(in: 50 ..< 60))

            return enemySprite
        case .enemy3:
            enemySprite.texture = SKTexture(imageNamed: "enemy3")
            enemySprite.size = CGSize(width: 46, height: 40)
            enemySprite.position.x = self.size.width / 1.5;
            enemySprite.position.y = 0;
            enemySprite.physicsBody = SKPhysicsBody(texture: enemySprite.texture!, size: enemySprite.size)
            enemySprite.physicsBody?.velocity = CGVector(dx: Int.random(in: -50 ..< 50), dy: Int.random(in: 50 ..< 60))

            return enemySprite
        case .enemy4:
            enemySprite.texture = SKTexture(imageNamed: "enemy4")
            enemySprite.size = CGSize(width: 40, height: 49)
            enemySprite.position.x = self.size.width / 3.5;
            enemySprite.position.y = 0;
            enemySprite.physicsBody = SKPhysicsBody(texture: enemySprite.texture!, size: enemySprite.size)
            enemySprite.physicsBody?.velocity = CGVector(dx: Int.random(in: -50 ..< 50), dy: Int.random(in: 50 ..< 60))

            return enemySprite
        }
    }




Thank you in advance

Replies

Did you also test on a device that was on Wi-Fi?


Which version Xcode are you using?


I think you have a borked dylib issue, which is causing the app to loop, time out and be killed by the system.


You might want to add breakpoints, then test same as app review, and step thru the app until it hangs/crashes/quits. Using Instruments may also help shed light on any performance bottlenecks.


>I didn't copy all logs because it's very long


Thanks...good move!

There's an informal process you can go through here to figure out what went wrong.


1. You were lucky, in a way, because the underlying crash type (EXC_BREAKPOINT) is a very specific error. In Swift code, it's the crash you get if you try to unwrap an optional value that's nil. That means you know what went wrong without having to investigate further. You just don't yet know where or why.


2. Thread 0 crashed, and the top of the backtrace indicates where in the code it was when it crashed:


0   Save The Princess              0x00000001010f0a4c 0x1010e8000 + 35404


This is (apparently) your code, not an iOS framework, so you just need to find out where in your code this happened.


3. To find out, you'll first need to symbolicate your crash log:


https://developer.apple.com/library/archive/technotes/tn2151/_index.html


When you do that, the same backtrace line will tell you the name of the source file and the line number within the file where the crash occurred.


4. Once you know where to look, you can study your code to look for reasons why an optional is unexpectedly nil. If nothing else, you might want to improve a check for nil, so you can log what's going on before you crash.


5. The information that the crash occurred while running on WiFi might or might not be helpful. If your app does something with networking, then obviously there might be a real difference in behavior on WiFi, and you should test that. If your app does nothing directly with networking, then running on WiFi might just change the timing in a way that exposes a bug.


You should at least go through the above steps to try to diagnose your crashing issue.


P.S. Note from the thread 0 backtrace that your code was called from the physics engine in SpriteKit. That means something like a physics-related delegate method of yours. That might help narrow things down a bit more. But the symbolicated crash log is your best friend here!

Hi,


Thank you for the reply.


Symbolicate result is:


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

Thread 0 Crashed:

0 Save The Princess 0x000000010090ca34 GameScene.didBegin(_:) + 35380 (GameScene.swift:281)

1 Save The Princess 0x000000010090ca64 @objc GameScene.didBegin(_:) + 35428 (<compiler-generated>:0)

2 PhysicsKit 0x00000001d9d2de48 0x1d9d19000 + 85576

3 PhysicsKit 0x00000001d9d2be64 0x1d9d19000 + 77412

4 SpriteKit 0x00000001e629ba48 0x1e6261000 + 240200

5 SpriteKit 0x00000001e62c0114 0x1e6261000 + 389396

6 SpriteKit 0x00000001e62bb7f4 0x1e6261000 + 370676

7 SpriteKit 0x00000001e62babf8 0x1e6261000 + 367608

8 SpriteKit 0x00000001e62bdc54 0x1e6261000 + 379988

9 SpriteKit 0x00000001e6300c18 0x1e6261000 + 654360

10 QuartzCore 0x00000001d3af5194 0x1d3ae4000 + 70036

11 IOKit 0x00000001cf9ef718 0x1cf9ea000 + 22296

12 CoreFoundation 0x00000001cf6fed30 0x1cf67b000 + 539952

13 CoreFoundation 0x00000001cf725934 0x1cf67b000 + 698676

14 CoreFoundation 0x00000001cf725080 0x1cf67b000 + 696448

15 CoreFoundation 0x00000001cf71fea4 0x1cf67b000 + 675492

16 CoreFoundation 0x00000001cf71f354 0x1cf67b000 + 672596

17 GraphicsServices 0x00000001d191f79c 0x1d1915000 + 42908

18 UIKitCore 0x00000001fb8e0b68 0x1fb026000 + 9153384

19 Save The Princess 0x000000010090d0a8 main + 37032 (GameScene.swift:13)

20 libdyld.dylib 0x00000001cf1e58e0 0x1cf1e4000 + 6368



I will show crash lines as well:


GameScene.swift:281 => 02. line here

func didBegin(_ contact: SKPhysicsContact) {
        let bodyA = contact.bodyA.node as! SKSpriteNode
        let bodyB = contact.bodyB.node as! SKSpriteNode
       
        if bodyA.name == "princess" && bodyB.name == "target" {
            nextLevel(playerPhysicsBody: contact.bodyA)
        } else if bodyB.name == "princess" && bodyA.name == "target" {
            nextLevel(playerPhysicsBody: contact.bodyB)
        } else if bodyA.name == "princess" && bodyB.name == "ENEMY" {
            gameOver()
        } else if bodyA.name == "ENEMY" && bodyB.name == "princess" {
            gameOver()
        } else if bodyA.name == "prince" && bodyB.name == "ENEMY" {
            self.movePlayerToStart()
        } else if bodyA.name == "ENEMY" && bodyB.name == "prince" {
            self.movePlayerToStart()
        }
    }



GameScene.swift:13 => 05. here

import SpriteKit
import GameplayKit

enum Enemies:Int {
    case enemy1
    case enemy2
    case enemy3
    case enemy4
}



I showed how i call enemies in my first post aswell. I will be very happy if you can help me here because this is my first app and i am very excited 🙂

So it looks like this assignment is failing:


        let bodyA = contact.bodyA.node as! SKSpriteNode


So this will crash if the "as!" operator fails to recognize contact.bodyA.node to a SKSpriteNode. That could happen for a couple of reasons:


1. contact.bodyA.node is nil. Probably not happening in this case, since a contact did happen, and physics bodies are attached to nodes.


2. contact.bodyA.node is a node, but not a SKSpriteNode. That could easily be happening, because you probably have nodes that are not the enemy nodes you showed earlier. (For example, sometimes a SpriteKit app has an edge boundary at the edges of the scene. This is probably attached to a SKNode that isn't a SKSpriteNode.)


You're going to have to do some debugging work to see if you can reproduce the crash yourself, and then to figure out exactly what has gone wrong.

>if you can help me here


Again, as I noted above, you might want to add breakpoints and step thru the app, debugging on your own until it hangs/crashes/quits. Using Instruments may also help shed light on any performance bottlenecks.


If it won't crash for you, consider using a support ticket w/DTS inAccount/Member Center and ask if they can help take a look.


Good luck.