ios xcode swift3 mpmediaplayercontroller
www.NextCoInc.com/public/junkplayer.zip

ios - Al salir de la aplicación se produce el error "Mensaje del depurador: finalizado debido a la señal 9"



xcode swift3 (2)

Estoy escribiendo una aplicación de reproductor de música básica, pero tengo algunos problemas a la hora de manejar las transiciones de estado de la aplicación.

Estoy usando Swift 3 y MPMusicPlayerController.systemMusicPlayer ()

El objetivo es este:

1) Mantenga la reproducción de música cuando el usuario toque el botón Inicio y la aplicación ingrese a bg (funciona)

2) Detenga el reproductor (myMP.stop ()) si el usuario sale de la aplicación (funciona a veces, produce un error otras veces)

Rastreé los flujos utilizando declaraciones impresas basadas en posibles acciones y obtuve esto:

El flujo 2 es lo que esperaría, pero el flujo 1 produce un error cuando se cierra la aplicación. Espero que "termine aquí".

EDITAR: El problema principal es que al salir de la aplicación usando el Flujo 1, "se terminará" nunca se llama, por lo tanto, "myMP.stop ()" nunca se llama y el jugador continúa jugando después de que la aplicación haya salido.

Hay una diferencia distinta en el comportamiento si hace clic en Inicio una vez (Flujo 1) o doble (Flujo 2) mientras la aplicación está activa.

¿Por qué obtengo dos respuestas diferentes de lo que deberían ser las mismas acciones?

EDITAR: Lo más importante, ¿cómo detengo el MediaPlayer para el Flujo 1 si nunca llega a "terminará"?

EDITAR:

Aquí hay un código de ejemplo que replica el problema:

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() } }

Descargue el proyecto aquí: www.NextCoInc.com/public/junkplayer.zip


El mensaje "finalizado debido a la señal 9" simplemente significa que su aplicación fue terminada por una señal SIGKILL. El sistema operativo envía esa señal cada vez que su aplicación se termina involuntariamente, ya sea debido a la presión de la memoria (o por varias otras razones que no son relevantes para esta discusión), o si el usuario lo mata explícitamente al presionar dos veces el botón de Inicio y al deslizarlo.

En su caso, el usuario está matando explícitamente su aplicación, por lo que se espera completamente el mensaje "Terminado debido a la señal 9". Si su aplicación es la aplicación de primer plano actual, se llamará al método de su applicationWillTerminate , como se muestra en el esquema de flujo lógico anterior (Flujo 2). Si su aplicación NO es la aplicación de primer plano actual (Flujo 1), NO se llamará al método ApplicationWillTerminate si su aplicación está suspendida. Este es el comportamiento esperado. También tenga en cuenta la distinción entre "estado de fondo" y "estado suspendido". No son lo mismo .

Entonces, si te estoy entendiendo correctamente, parece que el problema es que el audio continúa reproduciéndose después de que el usuario finalice tu aplicación (Flujo 1). Eso significa que está haciendo algo incorrecto en su manejo del MPMusicPlayerController , porque debería manejar esa transición de estado automáticamente.

Asegúrese de haber configurado el UIBackgroundMode correcto para su aplicación. Configurar el modo de fondo incorrecto puede hacer que su aplicación se comporte mal porque el sistema operativo solo permite ciertas operaciones mientras está en segundo plano, dependiendo del modo de fondo que haya configurado. Configurar el modo incorrecto (o intentar hacer cosas que están explícitamente deshabilitadas en el modo que has establecido) hará que tu aplicación se suspenda o se cierre.

Asegúrese de que ha configurado su sesión de audio correctamente.

Asegúrese de que está respondiendo correctamente a las notificaciones del reproductor de música , en particular, asegúrese de llamar a beginGeneratingPlaybackNotifications y endGeneratingPlaybackNotifications adecuada, y de que está manejando esas notificaciones correctamente. Revisa los manejadores de notificaciones para asegurarte de que no estás haciendo nada tonto allí. Asegúrese de que su controlador no quede fuera del alcance o se libere antes de que haya llamado a endGeneratingPlaybackNotifications .

Si has hecho todo lo demás correctamente, un MPMusicPlayerController maneja solo, por lo que no deberías tener que hacer nada especial para que funcione cuando tu aplicación pasa a segundo plano (aparte de configurar el modo UIBackgroundMode correcto, por supuesto). Como último recurso, comience a comentar el código hasta que su aplicación sea simplemente una aplicación "abra-un-archivo-de-audio-y-juegue" de barebones, y vea si sale correctamente. Si lo hace, puede comenzar a descomentar el código pieza por pieza hasta que falle; entonces sabrá qué parte de su aplicación está causando el problema y puede reducirlo desde allí.


Tenía tres tareas de fondo para la aplicación.

<key>UIBackgroundModes</key> <array> <string>bluetooth-central</string> <string>location</string> <string>remote-notification</string> </array>

Message from debugger: Terminated due to signal 9 Este mensaje aparece cuando la aplicación se está ejecutando en segundo plano y consume más memoria que la memoria asignada por el sistema operativo de un iPhone para las aplicaciones que se ejecutan en segundo plano.

En mi caso, estaba actualizando la ubicación del Usuario y ejecutando la api de ubicación del usuario al servidor continuamente. Estaba consumiendo mucha memoria. Debido a esta razón, OS mató la aplicación.

Recibimos este mensaje debido a la presión de la memoria en el sistema operativo y eliminamos la aplicación en segundo plano.

Optimicé el código y cada vez que necesitamos actualizar la ubicación del usuario, solo disparamos la API de ubicación al servidor. También allowsBackgroundLocationUpdates enable / disable la bandera allowsBackgroundLocationUpdates

if #available(iOS 9.0, *) { coreLocationManager.allowsBackgroundLocationUpdates = false } acuerdo con nuestra necesidad. funcionó bien