Saltar al contenido

UIApplication.shared.delegate equivalente para SceneDelegate xcode11?

Después de tanto trabajar hemos encontrado el arreglo de este dilema que muchos lectores de nuestro sitio web presentan. Si tienes algún detalle que aportar no dudes en aportar tu comentario.

Solución:

A partir de iOS 13, UIApplication tiene el connectedScenes propiedad que es Set. Cada una de esas escenas tiene un delegate el cual es un UISceneDelegate. Entonces podría acceder a todos los delegados de esa manera.

Una escena puede gestionar una o más ventanas (UIWindow) y puede obtener una ventana UIScene de su windowScene propiedad.

Si desea el delegado de escena para un controlador de vista específico, tenga en cuenta lo siguiente. A partir de una UIViewController puedes obtener su ventana desde su vista. Desde la ventana puede obtener su escena y, por supuesto, desde la escena puede obtener su delegado.

En resumen, desde un controlador de vista, puede hacer:

let mySceneDelegate = self.view.window.windowScene.delegate

Sin embargo, hay muchas ocasiones en las que un controlador de vista no tiene ventana. Esto sucede cuando un controlador de vista presenta otro controlador de vista de pantalla completa. Esto puede suceder cuando el controlador de vista está en un controlador de navegación y el controlador de vista no es el controlador de vista visible superior.

Esto requiere un enfoque diferente para encontrar la escena del controlador de vista. En última instancia, debe usar una combinación de caminar por la cadena de respuesta y la jerarquía del controlador de vista hasta que encuentre un camino que conduzca a la escena.

La siguiente extensión (puede) obtener una UIScene desde una vista o un controlador de vista. Una vez que tenga la escena, puede acceder a su delegado.

Agregue UIResponder+Scene.swift:

import UIKit

@available(iOS 13.0, *)
extension UIResponder 
    @objc var scene: UIScene? 
        return nil
    


@available(iOS 13.0, *)
extension UIScene 
    @objc override var scene: UIScene? 
        return self
    


@available(iOS 13.0, *)
extension UIView 
    @objc override var scene: UIScene? 
        if let window = self.window 
            return window.windowScene
         else 
            return self.next?.scene
        
    


@available(iOS 13.0, *)
extension UIViewController 
    @objc override var scene: UIScene? 
        // Try walking the responder chain
        var res = self.next?.scene
        if (res == nil) 
            // That didn't work. Try asking my parent view controller
            res = self.parent?.scene
        
        if (res == nil) 
            // That didn't work. Try asking my presenting view controller 
            res = self.presentingViewController?.scene
        

        return res
    

Esto se puede llamar desde cualquier vista o controlador de vista para obtener su escena. Pero tenga en cuenta que solo puede obtener la escena desde un controlador de vista solo después de viewDidAppear ha sido llamado al menos una vez. Si lo intenta antes, es posible que el controlador de vista aún no forme parte de la jerarquía del controlador de vista.

Esto funcionará incluso si la ventana de la vista del controlador de vista es nula, siempre que el controlador de vista sea parte de una jerarquía de controladores de vista y en algún lugar de esa jerarquía, esté adjunto a una ventana.


Aquí hay una implementación de Objective-C de la extensión UIResponder:

UIResponder+Escena.h:

#import 

NS_ASSUME_NONNULL_BEGIN

@interface UIResponder (Scene)

@property (nonatomic, readonly, nullable) UIScene *scene API_AVAILABLE(ios(13.0));

@end

NS_ASSUME_NONNULL_END

UIResponder+Escena.m:

#import "ViewController+Scene.h"

@implementation UIResponder (Scene)

- (UIScene *)scene 
    return nil;


@end

@implementation UIScene (Scene)

- (UIScene *)scene 
    return self;


@end

@implementation UIView (Scene)

- (UIScene *)scene 
    if (self.window) 
        return self.window.windowScene;
     else 
        return self.nextResponder.scene;
    


@end

@implementation UIViewController (Scene)

- (UIScene *)scene 
    UIScene *res = self.nextResponder.scene;
    if (!res) 
        res = self.parentViewController.scene;
    
    if (!res) 
        res = self.presentingViewController.scene;
    

    return res;


@end

Pude hacerlo funcionar usando esto:

let scene = UIApplication.shared.connectedScenes.first
if let sd : SceneDelegate = (scene?.delegate as? SceneDelegate) 
    sd.blah()

JoeGalind Gracias, también lo resolví de manera similar.

// iOS13 or later
if #available(iOS 13.0, *) 
    let sceneDelegate = UIApplication.shared.connectedScenes
        .first!.delegate as! SceneDelegate
    sceneDelegate.window!.rootViewController = /* ViewController Instance */

// iOS12 or earlier
 else 
    // UIApplication.shared.keyWindow?.rootViewController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.window!.rootViewController = /* ViewController Instance */

Al final de la post puedes encontrar las aclaraciones de otros desarrolladores, tú incluso puedes dejar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *