2015-01-27 11 views
6

Sto provando a migrare del codice da Objective-c a Swift, ma ho problemi all'inizio quando voglio conformare una classe Swift con un protocollo Objective-c e accedere a questa classe da una classe objetive-c . Sto facendo qualcosa di sbagliato, ma non lo vedo.Protocollo Objective-c per classe Swift. metodo non riconosciuto

Objective-c protocollo e obj-c della classe per il test (test_class.h)

#import <Foundation/Foundation.h> 

@protocol test_delegate 

-(void)returnData:(NSString*)data InMethod:(NSString*)method; 
@end 

@interface test_class : NSObject 

@property (weak, nonatomic) id<test_delegate> delegate; 
-(void)sendData:(NSString *)data; 
@end 

Objective-C implementazione

#import "test_class.h" 

@implementation test_class 

-(id) init{ 
    self = [super init]; 
    if (self != nil){ 
     self.delegate= nil; 
    } 
    return self; 
} 
-(id) initWithDelegate:(id<test_delegate>) delegate{ 
    self = [super init]; 
    if (self != nil){ 
     self.delegate = delegate; 

    } 
    return self; 
} 


-(void)sendData:(NSString *)data{ 

    [self.delegate returnData:data InMethod:@"method test"]; 
} 
@end 

file di Brigde-c scopo principale

// 
// Use this file to import your target's public headers that you would like to expose to Swift. 
// 

#import "test_class.h" 

File Swift (FirstViewController.swift)

import UIKit 

class FirstViewController: UIViewController, test_delegate { 

    var test : test_class! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     test = test_class() 
     test.delegate=self 
     test.sendData("show in log") 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func returnData(data: String!, inMethod method: String!) { 
     NSLog(data) 
    } 


} 

Infine la compilazione errore mi

2015-01-27 08:21:05.787 Test[4566:51164] -[Test.FirstViewController returnData:InMethod:]: unrecognized selector sent to instance 0x7fa6abd0aa20 
2015-01-27 08:21:05.792 Test[4566:51164] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Test.FirstViewController returnData:InMethod:]: unrecognized selector sent to instance 0x7fa6abd0aa20' 

dà Questo codice, utilizzando solo le classi Obj-C funziona bene. Cosa sto facendo di sbagliato?

Utilizzando Xcode 6.1.1 e destinazione di distribuzione iOS 8.0

Grazie in anticipo.

UPDATE: Swift ha un comportamento strano quando implementare un metodo da un protocollo di Objective-C: il nome di param deve iniziare con una piccola lettera al The begginig, altrimenti, il compilatore vi darà un errore di compilazione, e in caso contrario, darti un errore di runtime.

L'unica soluzione che ho trovato, è modificare Objective-C metodo di protocollo definizione in questo modo:

@protocol test_delegate 

-(void)returnData:(NSString*)data InMethod:(NSString*)method; 
@end 

a:

@protocol test_delegate 

-(void)returnData:(NSString*)data inMethod:(NSString*)method; 
@end 

Facendo questo cambiamento, funziona perfettamente.

Se qualcuno ha una risposta per questo comportamento, è il benvenuto per pubblicare e spiegare perché questo accade.

UPDATE 2: Grazie a @Adam Freeman a sottolineare un altro aspetto strano di Swift con classi nomi e nomi di variabili. Copiato (con il suo permesso) il codice qui:

Un'altra cosa a cui prestare attenzione è se il metodo delegato del protocollo prende la sua classe come uno dei suoi parametri. Utilizzando questo esempio:

#import <Foundation/Foundation.h> 

@class TestClass; 
@protocol TestDelegate 
-(void)TestClass:(TestClass*)TestClass returnData:(NSString*)data inMethod:(NSString*)method; 
@end 

@interface TestClass : NSObject 

@property (weak, nonatomic) id<TestDelegate> delegate; 
-(void)sendData:(NSString *)data; 
@end 

Questo può causare problemi con TestClass essere trovati nel codice Swift. La correzione è:

#import <Foundation/Foundation.h> 

@class TestClass; 
@protocol TestDelegate 
-(void)testClass:(TestClass*)testClass returnData:(NSString*)data inMethod:(NSString*)method; 
@end 

@interface TestClass : NSObject 

@property (weak, nonatomic) id<TestDelegate> delegate; 
-(void)sendData:(NSString *)data; 
@end 

inciso la Swift spec afferma che cose come le classi e delegati devono iniziare con una lettera maiuscola e metodi e nomi dei parametri devono iniziare con una lettera minuscola.

+2

Controlla la tua maiuscola di 'InMethod' (Objective-C) contro' inMethod' (Swift). – Grimxn

+0

Thx per la tua risposta grimxn. È vero quello che dici, ma se provi a utilizzare il compilatore inmethod (swift) xcode ti dai un errore. Non c'è altra soluzione che cambiare il metodo del protocollo o creare un oggetto intermedio. Inserirò un aggiornamento nel post principale – Neonamu

risposta

6

Cambio:

func returnData(data: String!, inMethod method: String!) { 

a

func returnData(data: String!, InMethod method: String!) { 

e dovrebbe funzionare. Si utilizza una lettera maiuscola in inMethod.

+0

Stavo avendo lo stesso errore di capitalizzazione .. Grazie, risparmia tempo .. – iCoder86

1

Un'altra cosa a cui fare attenzione è che mi sono imbattuto in questo post e questo post mi ha aiutato a risolvere (thanX!) E che altri potrebbero essere in esecuzione se il metodo protcol delegate prende la sua classe come uno dei suoi parametri. Come ad esempio ==>

#import <Foundation/Foundation.h> 

@class TestClass; 
@protocol TestDelegate 
-(void)TestClass:(TestClass*)TestClass returnData:(NSString*)data inMethod:(NSString*)method; 
@end 

@interface TestClass : NSObject 

@property (weak, nonatomic) id<TestDelegate> delegate; 
-(void)sendData:(NSString *)data; 
@end 

Questo può causare problemi con TestClass essere trovati nel codice Swift. La correzione è:

#import <Foundation/Foundation.h> 

@class TestClass; 
@protocol TestDelegate 
-(void)testClass:(TestClass*)testClass returnData:(NSString*)data inMethod:(NSString*)method; 
@end 

@interface TestClass : NSObject 

@property (weak, nonatomic) id<TestDelegate> delegate; 
-(void)sendData:(NSString *)data; 
@end 

Per inciso Swift spec afferma che cose come le classi e delegati devono iniziare con una lettera maiuscola e metodi e nomi dei parametri devono iniziare con una lettera minuscola. So che questo è nit-picky ma test_class dovrebbe essere davvero TestClass secondo le specifiche di Apple.

+0

Con il tuo permesso, aggiornerò il post principale con i tuoi commenti. Penso che sia un altro caso "strano" per la sintassi Swift come la domanda principale ed è bello sapere di più. Grazie! – Neonamu

+0

@Neonamu provaci! –

+0

ora è nel post principale. Puoi spiegare qui quale versione di sdk, xcode e swift stai usando? per meglio conosciuto di tutti i casi :). Se vuoi cambiare qualcosa, per favore, sentiti libero di dirmelo in questo post e lo aggiornerò (o fallo tu stesso!) – Neonamu