iDevice crashes due to animated sprite - ios

I'm trying to have one of my sprites have an animation when my hero hits it, my app crashes on my iDevice and xCode seems to blame it on the animated SKAction that I made.
This is my code:
var fire: SKSpriteNode! = SKSpriteNode(imageNamed:"1")//I've set this as a universal variable
var anime = SKAction.animateWithTextures([SKTexture(imageNamed: "1"), // apparently this line causes the crash
SKTexture(imageNamed:"2"),
SKTexture(imageNamed:"3"),
SKTexture(imageNamed:"4"),
SKTexture(imageNamed:"5"),
SKTexture(imageNamed:"6"),//this line is also a problem apparently
SKTexture(imageNamed:"7")], timePerFrame: 0.1)
fire.runAction(SKAction.repeatActionForever(anime))
fire.size = CGSize(width: targetSprite.size.width*1.3, height: self.frame.size.height*0.9)
fire.position = targetSprite.position
fire.runAction(SKAction.sequence([fall,kill]))
addChild(fire)
return fire
after the crash xCode points to one of the two lines I've pointed out and says EXC_BAD_ACCESS code=1 and it has no crash message.

Related

Xcode 14 , XCUITests - Tap is not working for WebView default done button

We have started adopting a new version of Xcode 14, and we see many tests failure. Many test failures are mainly those with a web view inside the app. After trying all the different alternatives, we cannot tap on the done button; that's the default button when we open the web view in the app.
Please list the steps you took to reproduce the issue:
Our tests are trying tap on done button that's inside the web view and seeing error (default done button of browsers). We can check the existence of the button that's return true but can't tap on it . see attachment
that's Xcode 14 bug for sure. I also tested previous version of Xcode 13.4.1 and did not see any error
Any alternative way to handle the webview done button
extension XCUIApplication {
func tapCoordinate(at point: CGPoint) {
let normalized = coordinate(withNormalizedOffset: .zero)
let offset = CGVector(dx: point.x, dy: point.y)
let coordinate = normalized.withOffset(offset)
coordinate.tap()
}
}
with help from How to tap on a specific point using Xcode UITests
#Nish answer works fine, so I added a little variation to get the coordinate of the button and tap on it.
(Note: this will work on any screen/simulator size, because it is not dependent on the CGPoint being explicitly passed)
if let doneButton = app.buttons["Done"].waitAndHandleFailure(timeout: JourniTestConstants.asyncTimeout) {
let doneCoordinates = app.coordinate(withNormalizedOffset: .zero).withOffset(.init(dx: doneButton.frame.midX, dy: doneButton.frame.midY))
doneCoordinates.tap()
}

Re-Assigning instance of AVAudioPlayer in iOS13 leads to BAD_ACCESS runtime error

I have an app, that is for many years in the AppStore and runs without any crashes (last deployment target iOS 12.4). I have some code for playing a sound on certain events in the app.
Now I tried to upgrade my app for iOS 13 and without changing any code related to that “playSound” thing, I always get this runtime error, when testing on a real device. Does not happen on simulator.
Thread 1: EXC_BAD_ACCESS (code=1, address=0x48)
PLEASE: Before you mark that question as “duplicate”, consider that this must have something to do with the release of iOS13, because before it didn’t happen and the code is just "usual".
Here is my code, also on gitHub.
I have a property in my ViewController to prevent ARC deallocating my AVAudioPlayer:
private var mySoundPlayer: AVAudioPlayer = AVAudioPlayer()
I have a routine, where the “play sound” should be performed (here happens the error, when assigning a new instance of AVAudioPlayer. The resourceURL is not the problem, the RE-ASSIGNING is the problem, I tested it with a new instance not being assigned and i did not crash.
// -------------------------------------------------
// MARK: Private Methods
// -------------------------------------------------
private func makeSoundEvent(_ soundEvent : SoundEvent) {
guard Settings().getSound() == .soundON else { return }
guard let urlToRessource : URL = soundEvent.getFileURLToSoundRessource() else { return }
do {
mySoundPlayer = try AVAudioPlayer(contentsOf: urlToRessource)
try? AVAudioSession.sharedInstance().setActive(true)
mySoundPlayer.play()
}
catch { print("Could not create AVPlayer for ressource \(urlToRessource)") }
}
And here I have the call of that subroutine, somewhere in my viewDidLoad() with a delay of 2 seconds.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.makeSoundEvent(.startFanfare)
}
I think it somehow does not work because of the async thread. But since it is on the main thread, I thought this should work.
Just remove the initialisation and it will work
private var mySoundPlayer: AVAudioPlayer!
Cheers!!!
private var mySoundPlayer: AVAudioPlayer = AVAudioPlayer()
AVAudioPlayer doesn't have init() listed as a valid initializer. The reference page shows four separate initializers, all of which take at least one parameter. If you were using the line above in code prior to iOS 13.1 without crashing, you were initializing the audio player incorrectly and probably just getting lucky that it wasn't a problem.
I don't know what changed specifically with AVAudioPlayer in iOS 13.1, but the release notes show quite a few audio-related changes, and it seems likely that some change to that class introduced a dependency on something that happens at initialization time.

Thread 1: EXC_BAD_ACCESS (code=1, address=0x8000000000000010)

I have an application which has a collection view full of videos and images. When you tap on one of them you segue to a full screen to view the media. When I tap a image It works as needed. But when I run my application and tap one of those videos I get the error shown bellow:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x8000000000000010)
I get this here:
class AppDelegate: UIResponder, UIApplicationDelegate {
Is this possibly due to memory problems?
What is happening and how do i fix this?
I have looked here but was unable to solve it.
I have found that the fail actually occurs when the bellow function is called.
func getAndShowMedia(post: Post) {
if post.media[numberMedia].image != nil {//here is still works, I am assuming this line is the line which actualy fails
print("imageooooo")//When setting break point here it will crash
mediaView.image = nil
mediaView.image = (post.media[numberMedia].image)!
} else {
mediaView.layer.removeFromSuperlayer()
let videoURL = post.media[numberMedia].videoURL
let player = AVPlayer(url: videoURL! as URL)
let playerLayer = AVPlayerLayer(player: player)
print("videooooooo")
playerLayer.frame = mediaView.bounds
mediaView.layer.addSublayer(playerLayer)
player.play()
}
}
Here:
func loadOtherData() {
getAndShowMedia(post: selectedPost!)
}
Please check your code and tell me where be crash.
I read your code and assume happening crash, i write be below point and check the debug mode.
post.media[numberMedia].image you check is not nil please there case use if let statement.
post.media[numberMedia].videoURL is geting in your model URL object that will happening crash.
mediaView.layer.removeFromSuperlayer() i don't understand this code you have remove layer but you add sublayer mediaView.layer.addSublayer(playerLayer) then remove sublayer. Check your sublayer is available then remove sublayer, not remove mediaView layer.
use this code remove layer.
mediaView.layer.sublayers?.forEach({ $0.removeFromSuperlayer() })
I hope this code will be work.
From the Breakpoint menu in Xcode, press the '+' button at the bottom left then add an exception breakpoint. This will show you exactly where your app is crashing and you'll be able to debug it properly.
You have a few forced unwraps there that may be nil, you should avoid that.

iOS crash: MTLRenderPassDescriptor null after rotation

I'm writing a iOS app using Metal. At some point during the MTKViewDelegate draw, I create a render pass descriptor and render things on screen,
let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
encoder.setViewport(camera.viewport)
encoder.setScissorRect(camera.scissorRect)
At the beginning of my draw function, I have a semaphore, the same code found in the Metal game template found in Xcode, and then a check to verify that the view hasn't changed size. If it has, I recreate my buffers,
let w = _gBuffer?.width ?? 0
let h = _gBuffer?.height ?? 0
if let metalLayer = view.layer as? CAMetalLayer {
let size = metalLayer.drawableSize
if w != Int(size.width) || h != Int(size.height ){
_gBuffer = GBuffer(device: device, size: size)
}
}
Everything works fine, and rotation was working fine on my iPhone6. However, when I tried on an iPad Pro, it always generate a SIGABRT when I try to rotate the device. The debugger tells me the encoder is null. I also get this exception in the console,
MTLDebugRenderCommandEncoder.mm:2028: failed assertion `(rect.x(1024) + rect.width(1024))(2048) must be <= 1536'
The exception must occur because I'm updating "camera" inside mtkView,
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
camera.setBounds(view.bounds)
}
When I run without the debugger attached, it doesn't crash.
I guess mtkView is called asynchronously and I should do something to stop the rendering midway through when mtkView is called, but the mutex should be in the library, not in my code? Although both draw and mtkView are being called from the same thread (Thread 1 in the debugger)... If I step-debug putting breakpoints in draw and mtkView, it seems I manually sync'ing and it doesn't crash. I'm a bit lost...
The full source code is here: https://github.com/endavid/VidEngine
Any ideas?
The exception message was the hint. I got distracted by the encoder being null. I guess it becomes null once the exception is thrown, but the problem wasn't in the encoder.
The code in camera.setBounds(view.bounds) wasn't updating the scissorRect...
I have a CADisplayLink that updates the CPU objects at a different rate, and the scissorRect was being updated there when it detected a change.
I've added a call to the full camera update inside mtkView() and the crash is gone now :)
I can resolve this, unchecking "Debug executable" in the Scheme

iOS SpriteKit - countdown before game starts?

Just getting into SpriteKit on iOS using Swift. I have a 'Breakout' game from a tutorial and I want to implement a countdown before every ball launches, by putting an SKLabel in the middle of the screen which counts down from 5 to 1 before removing itself and the game starting. Whilst the countdown is going on, you can see the full games screen with the wall, stationary ball etc.
I can't work out where in the game loop to do this. If I do the countdown in didMoveToView (where I create the wall and initialise the ball and paddle), I never see it, but I see my debugging messages in the log. I guess that didMoveToView is called before the SKScene is presented.
I tried to use a flag to call the countdown function the first time 'Update' is called, but again I saw the countdown executed before anything appeared on screen - i think 'update' is called initially before the scene is rendered.
I could implement a 'Tap screen to start' screen in a another SKScene, but I really wanted a countdown on the screen with the wall and the (stationary) ball ready to go. I could create this countdown scene using a background image of the game screen, but this seems awkward.
Any suggestions gratefully received,
Steve
Added these functions and a call to countdown(5) at the end of didMoveToView
func countdown(count: Int) {
countdownLabel.horizontalAlignmentMode = .Center
countdownLabel.verticalAlignmentMode = .Baseline
countdownLabel.position = CGPoint(x: size.width/2, y: size.height*(1/3))
countdownLabel.fontColor = SKColor.whiteColor()
countdownLabel.fontSize = size.height / 30
countdownLabel.zPosition = 100
countdownLabel.text = "Launching ball in \(count)..."
addChild(countdownLabel)
let counterDecrement = SKAction.sequence([SKAction.waitForDuration(1.0),
SKAction.runBlock(countdownAction)])
runAction(SKAction.sequence([SKAction.repeatAction(counterDecrement, count: 5),
SKAction.runBlock(endCountdown)]))
}
func countdownAction() {
count--
countdownLabel.text = "Launching ball in \(count)..."
}
func endCountdown() {
countdownLabel.removeFromParent()
ball.physicsBody!.applyImpulse(CGVectorMake(20, 20))
}
So I create and set up the text of the countdown and then create and run an SKAction that waits for 1 second before decrementing the countdown and updating the label. It repeats this 5 times and then removes the countdown label before finally giving the ball an impulse to start it moving and so the game proper can start.
Seems to work ok...
This is where NSTimers really come in handy. An NSTimer basically activates a function every so often (you specify how often).
Update: Sometimes it's better not to use an NSTimer; see here: https://stackoverflow.com/a/24950982/5700898
Here's a code sample, using NSTimer:
class ViewController: UIViewController {
var countdownTime = 5
var countdownTimer = NSTimer()
// above, setting your timer and countdown time as global variables so they can be accessed in multiple functions.
func PlayerPressesStart() {
countdownTime = 5
countdownTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "Countdown", userInfo: nil, repeats: true) // calls the function "Countdown" every second.
}
func Countdown() { // this is the function called by the timer every second, which causes your "countdownTime" to go down by 1. When it reaches 0, it starts the game.
countdownTime--
if countdownTime > 0 {
countdownTimer.invalidate()
placewhereyoudisplaycountdown.text = String(countdownTime)
}
if countdownTime == 0 {
// call the function where game action begins here, or call the function that makes the game begin here.
}
} // closing bracket for the View Controller, don't include this if you're copying and pasting to your already existing View Controller.

Resources