es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Llamando a una función asincrónica de Swift desde Objective-C.

Estoy utilizando las nuevas características de Swift 5.5 para crear una función asincrónica:

@MainActor
@objc func updateStatus() async {
    /// hacer cosas asincrónicas...
}

Pero cuando intento llamar a este método desde código Objective-C, no aparece en el autocompletado y da un error de compilación si intento compilarlo:

if (@available(iOS 15.0, *)) {
     CJSubscriptionStatusCheck *backgroundStatusCheck = [[CJSubscriptionStatusCheck alloc] init];
     [backgroundStatusCheck updateStatus]; // No visible @interface for 'CJStatusCheck' declares the selector 'updateStatus'
}

Mi otro código Swift funciona bien con Objective-C, así que la configuración está bien, pero no estoy seguro de cómo se puede utilizar el código “async” (si es que se puede) con Objective-C. No encuentro respuesta a esto en mi investigación.

Gracias.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que Objective-C no admite la nueva declaración de función asincrónica de Swift. Por lo tanto, no se puede llamar directamente a una función asincrónica desde el código Objective-C. Para usar la función en Objective-C, deberá crear una versión sincrónica de la función que se pueda llamar desde Objective-C. Esto se puede hacer utilizando el patrón de controlador de finalización o mediante el uso de la vinculación de Swift para crear un envoltorio separado de Objective-C para la función asincrónica.

    Aquí hay un ejemplo de cómo podría usar un controlador de finalización para hacer que la función asincrónica sea accesible en Objective-C:

    @MainActor
    @objc func updateStatus(completion: @escaping () -> Void) {
        /// hacer cosas asincrónicas ...
        completion()
    }
    

    Y luego llamarlo desde el código Objective-C de esta manera:

    if (@available(iOS 15.0, *)) {
         CJSubscriptionStatusCheck *backgroundStatusCheck = [[CJSubscriptionStatusCheck alloc] init];
         [backgroundStatusCheck updateStatusWithCompletion:^{
             // código a ejecutar después de que se complete la tarea asincrónica
         }];
    }
    

    Alternativamente, podría crear un envoltorio Objective-C que llame a la función asincrónica utilizando la vinculación de Swift. Aquí hay un ejemplo:

    @MainActor
    func updateStatus() async {
        /// hacer cosas asincrónicas ...
    }
    
    // Envoltorio Objective-C
    @objc class SubscriptionStatusCheck: NSObject {
        func updateStatus(completion: @escaping () -> Void) {
            Task.detached {
                await updateStatus()
                completion()
            }
        }
    }
    

    Y luego llamarlo desde el código Objective-C de esta manera:

    if (@available(iOS 15.0, *)) {
         SubscriptionStatusCheck *backgroundStatusCheck = [[SubscriptionStatusCheck alloc] init];
         [backgroundStatusCheck updateStatusWithCompletion:^{
             // código a ejecutar después de que se complete la tarea asincrónica
         }];
    }
    

    ¡Espero que esto ayude!

Comments are closed.