Swift与Objective-C交互时返回指针类型不兼容问题咨询
嗨,我来帮你拆解这个类型不兼容的问题~
首先先复现一下你的代码场景:
Swift 代码部分
// 原协议定义 protocol Fruit: NSObjectProtocol { } @objcMembers class Pear: NSObject, Fruit { override init() { super.init() } }
Objective-C 代码部分
@protocol Fruit; - (NSObject<Fruit> *)getFavoriteFruit { return [[Pear alloc] init]; // <- 这里报类型不兼容错误 }
你遇到的错误是:Incompatible pointer types returning 'Pear *' from a function with result type 'NSObject<Fruit> * _Nonnull',核心原因是Objective-C编译器没有正确识别到Pear类和NSObject<Fruit>*类型的兼容性,具体来说有两个关键问题:
1. Swift协议未正确暴露给Objective-C
你的Fruit协议虽然继承了NSObjectProtocol,但没有加上@objc修饰符。这会导致这个协议无法被Objective-C的编译器识别,你在ObjC里写的@protocol Fruit;只是一个无意义的前向声明,编译器不知道它和Swift里的Fruit协议是同一个东西。
2. 未导入Swift生成的Objective-C头文件
Swift项目会自动生成一个名为[你的项目名]-Swift.h的头文件,里面包含了所有暴露给Objective-C的Swift代码定义。你只做了协议的前向声明,没有导入这个头文件,导致Objective-C编译器不知道Pear类实际上遵循了Fruit协议。
解决办法
按以下两步修改即可:
第一步:修改Swift协议,加上@objc修饰
@objc protocol Fruit: NSObjectProtocol { }
这样Fruit协议就会被正确暴露给Objective-C。
第二步:在Objective-C文件中导入Swift自动生成的头文件
替换掉单纯的协议前向声明,导入项目的Swift头文件(注意把YourProjectName换成你实际的项目名称):
#import "YourProjectName-Swift.h" - (NSObject<Fruit> *)getFavoriteFruit { return [[Pear alloc] init]; // 现在不会报错了 }
做完这两步后,Objective-C编译器就能明确知道Pear是遵循Fruit协议的NSObject子类,自然就会认可Pear*到NSObject<Fruit>*的类型转换了。
备注:内容来源于stack exchange,提问作者Brinkster

