ios 退出应用程序会导致错误“来自调试器的消息:由于信号 9 终止”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42331852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Quitting app causes error "Message from debugger: Terminated due to signal 9"
提问by wayneh
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()
我正在使用 Swift 3 和 MPMusicPlayerController.systemMusicPlayer()
The goal is this:
目标是这样的:
1) Keep music playing when user taps the Home button and app enters bg (works)
1)当用户点击主页按钮并且应用程序进入 bg 时保持音乐播放(有效)
2) Stop the player ( myMP.stop() ) if the user the quits the app (works sometimes, throws error other times)
2)如果用户退出应用程序,则停止播放器( myMP.stop() )(有时有效,有时会引发错误)
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.
Flow 2 是我所期望的,但 Flow 1 在应用程序关闭时会引发错误 - 我希望此处“将终止”。
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.
编辑:主要问题是,当使用 Flow 1 退出应用程序时,永远不会调用“将终止” - 因此永远不会调用“myMP.stop()”并且播放器在应用程序退出后继续播放。
There is a distinct difference in behavior if you click Home once (Flow 1) or double (Flow 2) while the app is active.
如果您在应用程序处于活动状态时单击“主页”一次(流程 1)或双击(流程 2),则行为会有明显差异。
Why do I get two different responses from what should bethe same actions?
为什么我从应该是相同的操作中得到两种不同的响应?
EDIT: Most importantly, how do I stop the MediaPlayer for Flow 1 if it never gets to "will terminate" ?
编辑:最重要的是,如果流 1 的 MediaPlayer 永远不会“将终止”,我该如何停止它?
EDIT:
编辑:
Here is some sample code that replicates the issue:
下面是一些复制问题的示例代码:
AppDelegate.swift
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
视图控制器.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
回答by Jeff Loughlin
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.
“因信号 9 而终止”消息仅表示您的应用程序被 SIGKILL 信号终止。每当您的应用程序非自愿终止时,操作系统都会发送该信号,无论是由于内存压力(或与本讨论无关的其他几个原因),还是用户通过双击主页按钮并将其滑开来明确终止您的应用程序。
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 applicationWillTerminatemethod 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.
在您的情况下,用户明确地终止了您的应用程序,因此完全可以预期“因信号 9 而终止”消息。如果您的应用程序是当前的前台应用程序,您的applicationWillTerminate方法将被调用,如上面的逻辑流程大纲所示(流程 2)。如果您的应用程序不是当前的前台应用程序(流程 1),applicationWillTerminate
并且您的应用程序处于挂起状态,则不会调用您的方法。这是预期的行为。还要注意“后台状态”和“暂停状态”之间的区别。 它们不是一回事。
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.
因此,如果我对您的理解正确的话,听起来问题是在您的应用程序被用户终止后音频继续播放(流程 1)。这意味着您在处理 时做错了MPMusicPlayerController
,因为它应该自动处理该状态转换。
Make sure you've set the correct UIBackgroundModefor 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.
确保您已为您的应用设置了正确的UIBackgroundMode。设置错误的后台模式可能会导致您的应用程序行为异常,因为操作系统仅允许在后台进行某些操作,具体取决于您设置的后台模式。设置错误的模式(或尝试执行您设置的模式中明确禁止的操作)将导致您的应用程序被暂停或终止。
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
.
请确保您正确地响应音乐播放器的通知-特别是,确保你调用beginGeneratingPlaybackNotifications
和endGeneratingPlaybackNotifications
适当的,而且你是正确处理这些通知。检查您的通知处理程序以确保您没有在其中做任何愚蠢的事情。在调用之前,请确保您的控制器没有超出范围或以其他方式被释放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.
如果您已正确完成其他所有操作,则 anMPMusicPlayerController
几乎可以自行管理,因此当您的应用程序进入后台时,您不需要做任何特殊的事情来使其工作(UIBackgroundMode
当然,除了设置正确的 )。作为最后的手段,开始注释代码,直到您的应用程序只是一个准系统的“打开音频文件并播放”应用程序,然后查看它是否正确退出。如果是这样,您可以开始逐段取消注释代码,直到它失败 - 然后您知道应用程序的哪个部分导致了问题,您可以从那里缩小范围。
回答by A. Amini
Fyi: If you make changes in Settings app for app permissions like Camera usage and photo usage, your app will also crash (hard refresh) with this signal.
仅供参考:如果您在“设置”应用中更改相机使用和照片使用等应用权限,您的应用也会因此信号而崩溃(硬刷新)。
回答by Anil Gupta
I was having three background task for the App.
我正在为应用程序执行三个后台任务。
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>location</string>
<string>remote-notification</string>
</array>
Message from debugger: Terminated due to signal 9
This message comes when app is running into the background and it consumes more memory which beyond the allocated memory by the os of a iPhone for Background running apps.
Message from debugger: Terminated due to signal 9
当应用程序运行到后台并且它消耗更多内存时会出现此消息,这超出了 iPhone 操作系统为后台运行应用程序分配的内存。
In my case, I was updating the location of User and executing location api of the user to the server continuously. It was consuming lots of memory. Due to this reason, OS killed the App.
就我而言,我正在更新用户的位置并不断向服务器执行用户的位置 api。它消耗了大量内存。由于这个原因,操作系统杀死了该应用程序。
We got this message due to memory pressure on OS and killed the app in the background.
由于操作系统的内存压力,我们收到此消息并在后台终止了应用程序。
I optimised the code and whenever we need to update location of user then only we fired the location api to server.
I also enable \ disable
the flag allowsBackgroundLocationUpdates
我优化了代码,每当我们需要更新用户的位置时,只有我们将位置 api 发送到服务器。我也是enable \ disable
国旗allowsBackgroundLocationUpdates
if #available(iOS 9.0, *) {
coreLocationManager.allowsBackgroundLocationUpdates = false
}
according to our need.
it worked fine.
if #available(iOS 9.0, *) {
coreLocationManager.allowsBackgroundLocationUpdates = false
}
根据我们的需要。它工作正常。