退出应用程序会导致错误“来自调试器的消息:由于信号 9 终止" [英] Quitting app causes error "Message from debugger: Terminated due to signal 9"

查看:55
本文介绍了退出应用程序会导致错误“来自调试器的消息:由于信号 9 终止"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个基本的音乐播放器应用,但在处理应用状态转换时遇到了一些问题.

我正在使用 Swift 3 和 MPMusicPlayerController.systemMusicPlayer()

目标是这样的:

1) 当用户点击 Home 按钮并且应用进入 bg 时继续播放音乐(有效)

2) 如果用户退出应用程序,则停止播放器( myMP.stop() )(有时有效,有时会引发错误)

我根据可能的操作使用打印语句跟踪流程并得到:

流程 2 是我所期望的,但流程 1 会引发错误当应用程序关闭时 - 我希望在这里将终止".

主要问题是,当使用 Flow 1 退出应用程序时,永远不会调用将终止" - 因此永远不会调用myMP.stop()"并且播放器在应用程序退出后继续播放.

如果您在应用处于活动状态时单击主页"一次(流程 1)或两次(流程 2),则行为会有明显差异.

为什么我会从应该相同的操作中得到两种不同的响应?

最重要的是,如果流 1 的 MediaPlayer 永远不会将终止",我该如何停止它?

以下是一些重现该问题的示例代码:

AppDelegate.swift

<代码>////AppDelegate.swift//巨型播放器//导入 UIKit//导入媒体播放器//在何处声明这无关紧要 - 在这里或在 ViewController 中 - 相同的结果//让 myMP:MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer()@UIApplicationMain类 AppDelegate: UIResponder, UIApplicationDelegate {变量窗口:UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) ->布尔{//在应用程序启动后覆盖自定义点.返回真}func applicationWillResignActive(_ application: UIApplication) {//当应用程序即将从活动状态移动到非活动状态时发送.这可能发生在某些类型的临时中断(例如来电或 SMS 消息)或用户退出应用程序并开始转换到后台状态时.//使用此方法暂停正在进行的任务、禁用计时器并降低 OpenGL ES 帧速率.游戏应该使用这种方法来暂停游戏.打印(applicationWillResignActive")}func applicationDidEnterBackground(_ application: UIApplication) {//使用此方法释放共享资源,保存用户数据,使定时器失效,并存储足够的应用程序状态信息,以在应用程序稍后终止时将其恢复到当前状态.//如果您的应用程序支持后台执行,则在用户退出时调用此方法而不是 applicationWillTerminate:.打印(applicationDidEnterBackground")}func applicationDidReceiveMemoryWarning(_ application: UIApplication) {打印(applicationDidReceiveMemoryWarning")}func applicationWillEnterForeground(_ application: UIApplication) {//作为从后台到活动状态过渡的一部分调用;在这里,您可以撤消在进入后台时所做的许多更改.打印(applicationWillEnterForeground")}func applicationDidBecomeActive(_ application: UIApplication) {//重新启动应用程序处于非活动状态时暂停(或尚未启动)的任何任务.如果应用程序之前在后台,可选择刷新用户界面.打印(applicationDidBecomeActive")}func applicationWillTerminate(_ application: UIApplication) {//当应用程序即将终止时调用.如果合适,保存数据.另请参阅 applicationDidEnterBackground:.打印(applicationWillTerminate")myMP.stop();}}

ViewController.swift

<代码>////视图控制器.swift//垃圾玩家//导入 UIKit导入媒体播放器让 myMP:MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer()类视图控制器:UIViewController {@IBOutlet 弱变量 xxx:UIButton!覆盖 func viewDidLoad() {super.viewDidLoad()//在加载视图后做任何额外的设置,通常是从笔尖.让 qrySongs = MPMediaQuery.songs()myMP.setQueue(with: qrySongs)}@IBAction func playbut(_ sender: UIButton) {我的MP.play()}}

在此处下载项目:www.NextCoInc.com/public/junkplayer.zip

解决方案

由于信号 9 终止"消息仅表示您的应用程序被 SIGKILL 信号终止.每当您的应用非自愿终止时,操作系统都会发送该信号,无论是由于内存压力(或与本讨论无关的其他几个原因),还是用户通过双击主页按钮并将其滑开来明确终止您的应用.

在您的情况下,用户明确地终止了您的应用程序,因此完全可以预期因信号 9 而终止"消息.如果您的应用程序是当前的前台应用程序,您的 applicationWillTerminate 方法将被调用,如上面的逻辑流程大纲所示(流程 2).如果您的应用程序不是当前的前台应用程序(流程 1),并且您的应用程序处于挂起状态,则您的 applicationWillTerminate 方法将不会被调用.这是预期的行为.还要注意后台状态"和暂停状态"之间的区别.它们不是一回事.

因此,如果我对您的理解正确的话,听起来问题在于在您的应用程序被用户终止后音频继续播放(流程 1).这意味着您在处理 MPMusicPlayerController 时做错了,因为它应该自动处理该状态转换.

确保您设置了正确的UIBackgroundMode 适用于您的应用.设置错误的后台模式可能会导致您的应用程序行为异常,因为操作系统仅允许在后台进行某些操作,具体取决于您设置的后台模式.设置错误的模式(或尝试执行您设置的模式中明确禁止的操作)将导致您的应用被暂停或终止.

确保您已正确设置音频会话.

确保您正确响应音乐播放器通知 - 特别是确保您正确调用了 beginGeneratingPlaybackNotificationsendGeneratingPlaybackNotifications,并且您正在正确处理这些通知.检查您的通知处理程序以确保您没有在其中做任何愚蠢的事情.在您调用 endGeneratingPlaybackNotifications 之前,请确保您的控制器没有超出范围或以其他方式被释放.

如果您已正确完成其他所有操作,MPMusicPlayerController 几乎可以自行管理,因此当您的应用程序进入后台时(除了设置正确的UIBackgroundMode,当然).作为最后的手段,开始注释代码,直到您的应用程序只是一个准系统的打开音频文件并播放"应用程序,然后查看它是否正确退出.如果是这样,您可以开始逐段取消注释代码,直到它失败 - 然后您就知道应用的哪个部分导致了问题,您可以从那里缩小范围.

I'm writing a basic music player app but having some problems when it comes to handling the app state transitions.

I'm using Swift 3 and MPMusicPlayerController.systemMusicPlayer()

The goal is this:

1) Keep music playing when user taps the Home button and app enters bg (works)

2) Stop the player ( myMP.stop() ) if the user the quits the app (works sometimes, throws error other times)

I traced the flows using print statements based on possible actions and got this:

Flow 2 is what I would expect, but Flow 1 throws an error when the app is closed - I would expect "will terminate" here.

EDIT: The main issue is that when exiting the app using Flow 1, "will terminate" is never called - therefore "myMP.stop()" is never called and the player continues to play after the app has exited.

There is a distinct difference in behavior if you click Home once (Flow 1) or double (Flow 2) while the app is active.

Why do I get two different responses from what should be the same actions?

EDIT: Most importantly, how do I stop the MediaPlayer for Flow 1 if it never gets to "will terminate" ?

EDIT:

Here is some sample code that replicates the issue:

AppDelegate.swift

//
//  AppDelegate.swift
//  Jumbo Player
//

import UIKit
//import MediaPlayer

//doesn't matter where this is declared - here or in ViewController - same results
//let myMP:MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer()

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        print("applicationWillResignActive")
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        print("applicationDidEnterBackground")
    }

    func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
        print("applicationDidReceiveMemoryWarning")
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        print("applicationWillEnterForeground")
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        print("applicationDidBecomeActive")
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        print("applicationWillTerminate")
        myMP.stop();
    }
}

ViewController.swift

//
//  ViewController.swift
//  junkplayer
//

import UIKit
import MediaPlayer

let myMP:MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer()

class ViewController: UIViewController {

    @IBOutlet weak var xxx: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let qrySongs = MPMediaQuery.songs()
        myMP.setQueue(with: qrySongs)

    }

    @IBAction func playbut(_ sender: UIButton) {
        myMP.play()
    }
}

Download the project here: www.NextCoInc.com/public/junkplayer.zip

解决方案

The "terminated due to signal 9" message just means your app was terminated by a SIGKILL signal. The OS sends that signal whenever your app is terminated involuntarily, whether it's because of memory pressure (or several other reasons not relevant to this discussion), or the user explicitly killing your app by double tapping the Home button and swiping it away.

In your case, the user is explicitly killing your application, so the "Terminated due to signal 9" message is completely expected. If your application is the current foreground application, your applicationWillTerminate method will get called, as shown in your logic flow outline above (Flow 2). If your application is NOT the current foreground application (Flow 1), your applicationWillTerminate method will NOT get called if your application is in a suspended state. This is expected behavior. Also note the distinction between "background state" and "suspended state". They are not the same thing.

So if I'm understanding you correctly, it sounds like the problem is that the audio continues playing after your application is terminated by the user (Flow 1). That means you are doing something wrong in your handling of the MPMusicPlayerController, because it should handle that state transition automatically.

Make sure you've set the correct UIBackgroundMode for your app. Setting the wrong background mode can cause your application to misbehave because the OS only allows certain operations while in background, depending on what background mode you've set. Setting the wrong mode (or trying to do things that are explicitly disallowed in the mode you've set) will cause your app to be suspended or terminated.

Make sure you've set up your audio session correctly.

Make sure you are responding correctly to the music player notifications - in particular, make sure you're calling beginGeneratingPlaybackNotifications and endGeneratingPlaybackNotifications appropriately, and that you are handling those notifications correctly. Check your notification handlers to make sure you aren't doing anything silly in there. Make sure your controller doesn't go out of scope or otherwise get released before you've called endGeneratingPlaybackNotifications.

If you've done everything else correctly, an MPMusicPlayerController pretty much manages itself, so you shouldn't have to do anything special to make it work when your app goes to the background (aside from setting the correct UIBackgroundMode, of course). As a last resort, start commenting out code until your app is just a barebones "open-an-audio-file-and-play-it" application, and see if it exits properly then. If it does, you can start uncommenting code piece-by-piece until it fails - then you know what part of your app is causing the problem and you can narrow it down from there.

这篇关于退出应用程序会导致错误“来自调试器的消息:由于信号 9 终止"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆