Swift类的Objective-c协议。无法识别的方法

时间:2023-01-15 17:47:46

I'm trying to migrate some code from Objective-c to Swift, but i have problems at the beggining when i want to conform a Swift class with a Objective-c protocol and access this class from a objetive-c class. I'm doing something wrong, but i don't see it.

我正在尝试将一些代码从Objective-c迁移到Swift,但是当我想要使用Objective-c协议符合Swift类并从objetive-c类访问此类时,我在开始时遇到问题。我做错了什么,但我没有看到。

Objective-c protocol and obj-c class for testing (test_class.h)

Objective-c协议和用于测试的obj-c类(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 implementation

Objective-c实施

#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

Objetive-c brigde file

Objetive-c brigde文件

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

#import "test_class.h"

Swift file (FirstViewController.swift)

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


}

Finally the error compile gives me

最后错误编译给了我

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'

This code, using only Obj-c classes works fine. What I'm doing wrong?

这个代码,只使用Obj-c类工作正常。我做错了什么?

Using Xcode 6.1.1 and deployment target iOS 8.0

使用Xcode 6.1.1和部署目标iOS 8.0

Thank you in advance.

先谢谢你。

UPDATE: Swift has a weird behaviour when implement some method from a objective-c protocol: param's name must start with a tiny letter at the the begginig, else, compiler give you a compile-time error, and if not, give you a runtime error.

更新:当从Objective-c协议实现一些方法时,Swift有一个奇怪的行为:param的名称必须以begginig上的一个小字母开头,否则,编译器会给你一个编译时错误,如果没有,给你一个运行时错误。

The unique solution I've found, is modify objective-c protocol method definition this way:

我发现的独特解决方案是以这种方式修改objective-c协议方法定义:

@protocol test_delegate

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

to:

至:

@protocol test_delegate

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

Doing this change, it runs perfectly.

做这个改变,它完美运行。

If anyone has an answer for this behaviour, is welcome to post and explain why this happens.

如果有人对此行为有答案,欢迎发布并解释为什么会发生这种情况。

UPDATE 2: Thank you to @Adam Freeman to point out another weird issue of Swift with classes names and variables names. Copied (with his permission) the code here:

更新2:感谢@Adam Freeman用类名和变量名来指出Swift的另一个奇怪问题。复制(在他允许的情况下)代码:

Another thing to watch out for that is if your protocol delegate method takes its class as one of its parameters. Using this example:

另外需要注意的是,如果您的协议委托方法将其类作为其参数之一。使用此示例:

#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

This will cause problems with TestClass being found in your Swift code. The fix is:

这将导致在Swift代码中找到TestClass的问题。修复是:

#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

Incidentally the Swift spec states that such things as classes and delegates should start with an upper case letter and methods and parameter names should start with a lower case letter.

顺便提一下,Swift规范指出类和委托之类的东西应该以大写字母开头,方法和参数名称应该以小写字母开头。

2 个解决方案

#1


6  

Change:

更改:

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

to

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

and it should work. You use a capital letter in inMethod.

它应该工作。你在inMethod中使用大写字母。

#2


1  

Another thing to watch out for that I ran into and this post helped me fix (thanX!) and that others may run into is if your protcol delegate method takes its class as one of its parameters. Such as ==>

另外需要注意的是我遇到了这个帖子,这个帖子帮助我解决了(比起X!)而其他人可能遇到的问题是你的protcol委托方法将其类作为其参数之一。比如==>

#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

This will cause problems with TestClass being found in your Swift code. The fix is:

这将导致在Swift代码中找到TestClass的问题。修复是:

#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

Incidentally the Swift spec states that such things as classes and delegates should start with an upper case letter and methods and parameter names should start with a lower case letter. I know this is nit-picky but test_class really should be TestClass according to Apple's spec.

顺便提一下,Swift规范指出类和委托之类的东西应该以大写字母开头,方法和参数名称应该以小写字母开头。我知道这是挑剔的,但test_class根据Apple的规范确实应该是TestClass。

#1


6  

Change:

更改:

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

to

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

and it should work. You use a capital letter in inMethod.

它应该工作。你在inMethod中使用大写字母。

#2


1  

Another thing to watch out for that I ran into and this post helped me fix (thanX!) and that others may run into is if your protcol delegate method takes its class as one of its parameters. Such as ==>

另外需要注意的是我遇到了这个帖子,这个帖子帮助我解决了(比起X!)而其他人可能遇到的问题是你的protcol委托方法将其类作为其参数之一。比如==>

#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

This will cause problems with TestClass being found in your Swift code. The fix is:

这将导致在Swift代码中找到TestClass的问题。修复是:

#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

Incidentally the Swift spec states that such things as classes and delegates should start with an upper case letter and methods and parameter names should start with a lower case letter. I know this is nit-picky but test_class really should be TestClass according to Apple's spec.

顺便提一下,Swift规范指出类和委托之类的东西应该以大写字母开头,方法和参数名称应该以小写字母开头。我知道这是挑剔的,但test_class根据Apple的规范确实应该是TestClass。