导入 Objective-C 库时报错:找不到 UIAlertViewDelegate
结论
UIAlertViewDelegate 属于 UIKit。在导入第三方 Objective-C 头文件前,编译器必须先加载 UIKit 的声明。最直接的解决办法是在 bridging header 中先导入 UIKit,再导入第三方库:
#import <UIKit/UIKit.h>
#import "ThirdPartyLibrary.h"
更稳妥的做法是在实际使用 UIAlertViewDelegate 的第三方头文件中直接导入 UIKit。
原因
如果 Objective-C 头文件声明了协议遵循:
@interface SomeClass : NSObject <UIAlertViewDelegate>
@end
编译器解析这段代码时,必须已经知道 UIAlertViewDelegate 是什么。该协议声明在 UIKit 中。如果第三方头文件没有导入 UIKit,而 bridging header 又直接导入了这个头文件,就会报错:
error: no type or protocol named 'UIAlertViewDelegate'
Swift 的 bridging header 只负责向 Swift 暴露 Objective-C 声明,不会自动补充第三方头文件依赖的框架。
解决方法
先检查项目的 bridging header,例如:
// ProjectName-Bridging-Header.h
#import <UIKit/UIKit.h>
#import "ThirdPartyLibrary.h"
导入顺序不能颠倒。UIKit 必须放在引用 UIAlertViewDelegate 的第三方头文件之前。
如果可以修改第三方库源码,建议直接在使用该协议的 .h 文件中声明依赖:
#import <UIKit/UIKit.h>
@interface SomeClass : NSObject <UIAlertViewDelegate>
@end
这样该头文件可以独立编译,不必依赖其他文件提前导入 UIKit。
如果只想引入最低限度的依赖,也可以导入更具体的头文件:
#import <UIKit/UIAlertView.h>
不过通常直接使用下面的写法,兼容性和维护性会更好:
#import <UIKit/UIKit.h>
确认 bridging header 配置
还要确认当前 target 已正确配置 bridging header。在 Xcode 的 Build Settings 中找到:
Objective-C Bridging Header
它的值应指向实际文件,例如:
$(SRCROOT)/ProjectName/ProjectName-Bridging-Header.h
同时确认 iOS target 已包含 UIKit。Xcode 7 的 iOS 工程通常会自动链接 UIKit,所以多数情况下只需补上头文件导入,不需要手动添加额外的链接参数。
注意事项
UIAlertView 和 UIAlertViewDelegate 从 iOS 9 开始已被废弃,推荐改用 UIAlertController。但废弃不等于删除。在 Xcode 7.1 的 iOS SDK 中,该协议仍然存在,因此这个错误通常是缺少 UIKit 导入造成的,并非 API 已不可用。
如果第三方库仍依赖 UIAlertViewDelegate,可以先导入 UIKit,让项目恢复编译,再考虑升级第三方库或将相关实现迁移到 UIAlertController。
还要确认这段代码由 iOS target 编译。UIAlertViewDelegate 是 UIKit API。如果第三方头文件被 macOS、watchOS 等不支持该接口的 target 编译,仅添加导入仍可能无法解决问题。这时需要调整 Target Membership,或通过条件编译限制代码的适用范围。
备注:内容仅供参考。
