【问题标题】:Swift protocol in Objective-C categoryObjective-C 类别中的 Swift 协议
【发布时间】:2016-06-16 00:37:23
【问题描述】:

我在 Swift 中定义了一个协议:

@objc public protocol UploadProtocol: class {
    func isUploaded() -> Bool
    ...
}

我正在将我的ProjectName-Swift.h 文件导入我的ProjectName_Prefix.pch 文件(旧项目)中。

在 Objective-C 中,我在实现协议的类上有一个类别。我试图弄清楚如何让编译器知道该实现。这就是我一直在做的:

// Person+Upload.h
#import "Person.h"

@interface Person (Upload)
- (BOOL)isUploaded;
@end


// Person+Upload.m
#import "Person+Upload.h"
@implementation Person (Upload)
...
@end

这给了我:

找不到“UploadProtocol”的协议定义

我只能想到其他三种设置方法,但它们都有问题。我错过了什么?

第一种方式(Apple 推荐)

在 Using Swift with Cocoa and Objective-C (Swift 2.2) 中,Apple 表示:“Objective-C 类可以在其实现 (.m) 文件中采用 Swift 协议,方法是导入 Xcode 生成的 Swift 代码头文件和使用类扩展。”但是他们的示例是针对标准课程的。如果我尝试对我的类别执行此操作:

// Person+Upload.h
#import "Person.h"

@interface Person (Upload)
- (BOOL)isUploaded;
@end


// Person+Upload.m
#import "Person+Upload.h"

@interface Person (Upload) <UploadProtocol>
@end

@implementation Person (Upload)
...
@end

这会导致:

在“人”界面上重复定义“上传”类别

第二种方式

好的,所以我想避免定义上传类两次。所以我会把它从.h中删除。

// Person+Upload.h
#import "Person.h"

@interface Person ()
- (BOOL)isUploaded;
@end


// Person+Upload.m
#import "Person+Upload.h"

@interface Person (Upload) <UploadProtocol>
@end

@implementation Person (Upload)
...
@end

在这种情况下,我得到:

类别正在实现一个方法,该方法也将由其主类实现

我目前在.h 中声明该方法,以便其他类可以调用其中一些方法,而无需强制转换为协议来访问该方法。

第三条路

如果我在.h 中保留类别名称,但在.m 中删除它

// Person+Upload.h
#import "Person.h"

@interface Person (Upload)
- (BOOL)isUploaded;
@end


// Person+Upload.m
#import "Person+Upload.h"

@interface Person () <UploadProtocol>
@end

@implementation Person (Upload)
...
@end

然后我得到:

类别正在实现一个方法,该方法也将由其主类实现


是否每次都将其转换为协议的唯一解决方案?在多个地方添加这种类型的行似乎是代码异味:

Person <Upload> *s = (Person <Upload> *)self;

还有其他解决方案吗?

【问题讨论】:

    标签: objective-c swift swift-protocols


    【解决方案1】:

    感谢您提出有趣的问题!

    您的初始方法实际上将通过添加协议的前向声明来工作:

    // Person+Upload.h
    #import "Person.h"
    
    @protocol UploadProtocol; // NOTE THIS!!!
    
    @interface Person (Upload) <UploadProtocol>
    //- (BOOL)isUploaded;  // This is not really needed
    @end
    
    
    // Person+Upload.m
    #import "Person+Upload.h"
    #import "...-Swift.h"  // IMPORTANT!!!
    @implementation Person (Upload)
    // HERE you implement isUploaded, of course.
    ...
    @end
    

    这仍然会导致编译器警告Cannot find protocol definition for 'UploadProtocol',但它应该可以工作。

    Apple 推荐的方式也有效,Duplicate definition of category 只是一个警告,但 Person 不会被 Swift 代码识别为符合协议,即使它的一致性会被 Objective-C 识别。最初的方法在 Swift 中也可以。

    【讨论】:

    • 不幸的是,Apple 在书中说:“Swift 类和协议的前向声明只能用作方法和属性声明的类型。”所以在这种情况下它不起作用,它仍然会发出警告。 -Swift.h 文件已经通过我的*_Prefix.pch 文件导入。它确实给了我一个警告,所以它现在在技术上“有效”,但我想删除这些警告。 :)
    • 找不到“...”的协议定义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    相关资源
    最近更新 更多