objective c - programar - Protocolo Swift en la clase Objective-C
swift(lenguaje de programación) (6)
Asegúrese de incluir el encabezado Swift generado automáticamente en su archivo ObjectiveC. Tendrá el mismo nombre que su módulo de proyecto seguido de -Swift.h
.
Por ejemplo, si su módulo de proyecto es MyTarget , entonces usaría:
#import "MyTarget-Swift.h"
Si está escribiendo la importación en su archivo Objective C, no se autocompletará. Puede verificar que tiene el archivo correcto al hacer clic con el botón Comando en el encabezado luego de escribirlo.
Escribí SearcherProtocol
en Swift y necesito implementar una clase Objective-C FileSearcher
que tiene que usar este protocolo.
Así que probé esto:
#import <Foundation/Foundation.h>
@interface FileSearcher : NSObject <SearcherProtocol>
// ... class content
@end
El compilador me dice
No se puede encontrar la declaración de protocolo para ''SearcherProtocol''
El archivo de encabezado con puente correspondiente ( modulename-Swift.h
) se está importando dentro de FileSearcher.m
.
La importación de SearcherProtocol
en FileSearcher.h
arroja otro error del compilador: module name-swift.h file not found
¿Alguien tiene alguna pista de lo que estoy haciendo mal?
Estoy usando Xcode 6 Beta 5.
Editar
Aquí está la declaración de protocolo en Swift:
@objc protocol SearcherProtocol
{
var searchNotificationTarget: SearchCompletedProtocol? { get }
var lastSearchResults: [AnyObject] { get set }
func search(searchParam: String, error: NSErrorPointer) -> Bool
}
Y el SearchCompletedProtocol:
@objc protocol SearchCompletedProtocol
{
func searchCompletedNotification(sender: AnyObject!)
}
Cuando tengas
#import "moduleName-Swift.h"
en el archivo .h que desea ser un delegado, y tiene ese archivo .h también en el archivo de encabezados de puente, hay una referencia circular que hace que moduleName-Swift.h falle la compilación. para el proyecto de prueba de @james_alvarez, probablemente esté funcionando porque no necesita incluir TestObjClass.h en el encabezado del puente.
La mejor forma de combinar archivos objc que necesitan ser delegados para una clase escrita de forma rápida, pero que también debe incluirse en el encabezado de conexión para que otros archivos rápidos puedan acceder a esta clase objc, es crear un archivo de protocolo separado en objc:
MyProtocol.h:
@protocol MyDelegate <NSObject>
-(void)didDoThis;
-(void)didDoThat;
@end
ViewController.h:
#import "MyProtocol.h"
@interface ViewController : UIViewController <MyDelegate>
MyProject-Bridging-Header.h
#import "MyProtocol.h"
#import "ViewController.h"
Importar delegado como este en el archivo .h
@protocol AnalyticProtocol;
y agregue esto al archivo .swift
@objc public protocol AnalyticProtocol {
}
Intente agregar #import "Product_Module_Name-Swift.h"
a su archivo Product_Module_Name-Prefix.pch
. Eso lo solucionó para mí, y ahora tendrá acceso a sus archivos rápidos desde cualquier archivo objc.
Sé que esto fue hace mucho tiempo, pero solo tuve problemas con el mismo problema al agregar un protocolo a mi código Swift, y no se agregó al archivo de encabezado -Swift.h, por lo tanto, "No se puede encontrar la declaración de protocolo"
El problema era que mi protocolo no estaba marcado como Público . Cambié mi protocolo de esto:
@objc protocol MyProtocol { //etc.... }
a esto:
@objc public protocol MyProtocol { //etc.... }
Todavía no estoy del todo seguro de por qué necesito ''Público'', pero a nadie más parece, pero bueno, funciona ...
Hay dos razones comunes para que esto ocurra:
- Obteniendo el nombre del módulo incorrecto, mira mi respuesta.
- Tener una referencia circular - ver respuesta mitrenegades a continuación.
1. Obtener el nombre del módulo correcto:
Si tanto el protocolo rápido como el objetivo C están en el mismo proyecto, entonces, de acuerdo con apple , solo debe asegurarse de obtener el nombre correcto del módulo.
Para Xcode6 beta 5, puede encontrarlo en BuildSettings-> Packaging-> Product Module Name
Un error común sería pensar que cada archivo / clase rápida obtiene su propio archivo, pero en su lugar, todos se ponen en uno grande que es el nombre del proyecto.
Otros errores son si el nombre del módulo tiene espacios, estos deben ser reemplazados con guiones bajos.
Editar:
Con su protocolo, creé un proyecto de prueba llamado ''Test'' que compila perfectamente y tiene los archivos:
TestObjClass.h
#import <Foundation/Foundation.h>
#import "Test-Swift.h"
@interface TestObjCClass : NSObject <SearcherProtocol>
@end
TestObjClass.m
#import "TestObjCClass.h"
@implementation TestObjCClass
@end
TestProtocol.swift
import Foundation
@objc protocol SearcherProtocol
{
var searchNotificationTarget: SearchCompletedProtocol? { get }
var lastSearchResults: [AnyObject] { get set }
func search(searchParam: String, error: NSErrorPointer) -> Bool
}
@objc protocol SearchCompletedProtocol
{
func searchCompletedNotification(sender: AnyObject!)
}
2. Evita la referencia circular:
La respuesta de Mitrenegades explica esto, pero si su proyecto necesita usar la clase objc explícita que usa el protocolo rápido, (en lugar de solo usar el protocolo), entonces tendrá problemas de circularidad. La razón es que el protocolo veloz se define para el encabezado swift-objc, luego para su definición de clase obj-c, que luego vuelve al encabezado swift-objc.
La solución de Mitrenegades es usar un protocolo objetivo-c, es de una manera, pero si quiere un protocolo rápido, el otro sería refactorizar el código para no usar directamente la clase objetivo-c, sino usar el protocolo ( por ejemplo, algún patrón de fábrica basado en el protocolo). De cualquier forma, puede ser apropiado para sus propósitos.