Swift API暴露至Objective-C时@objc标记报错的解决方案咨询
解决Swift方法@objc标记因返回结构体报错的问题
这个问题我之前也碰到过,本质是Swift和Objective-C类型系统的核心差异:Objective-C runtime完全不识别Swift结构体类型,哪怕是可选的User?也不行,所以编译器才会抛出那个错误。下面给你几个可行的解决思路:
方案1:把User从结构体改为NSObject子类(最推荐)
Objective-C只能识别继承自NSObject的类,所以把User转换成类并继承NSObject,再通过@objcMembers自动暴露所有成员给Objective-C,就能完美解决问题:
// 把原来的结构体改成NSObject子类 @objcMembers public class User: NSObject { var userId: String init(userId: String) { self.userId = userId super.init() } } // 现在这个方法可以正常标记@objc了 @objc public static func logIn(_ userId: String) -> User? { // 你的登录逻辑,返回User实例或者nil return User(userId: userId) }
@objcMembers会自动将类的所有属性、方法暴露给Objective-C,不用你逐个添加@objc标记,非常方便。
方案2:保留结构体,用Objective-C兼容类型包装返回值
如果因为业务原因不能把User改成类,你可以把结构体的内容打包成Objective-C能识别的类型(比如NSDictionary),或者创建一个中间的Objective-C兼容类来承载结构体数据:
子方案2.1:用NSDictionary包装
// 保留原来的Swift结构体 public struct User { var userId: String // 其他属性 } // 修改方法返回NSDictionary? @objc public static func logIn(_ userId: String) -> NSDictionary? { let user = User(userId: userId) // 把结构体的属性转成字典返回 return ["userId": user.userId] }
Objective-C端拿到字典后,可以自行解析里面的字段。
子方案2.2:创建中间兼容类
// 原来的Swift结构体 public struct User { var userId: String } // 专门给Objective-C用的兼容类 @objcMembers public class OBJCUser: NSObject { let userId: String init(user: User) { self.userId = user.userId super.init() } } // 修改方法返回OBJCUser? @objc public static func logIn(_ userId: String) -> OBJCUser? { let swiftUser = User(userId: userId) return OBJCUser(user: swiftUser) }
这种方式比字典更类型安全,Objective-C端可以直接调用OBJCUser的属性。
方案3:改用回调方式传递结果(适合异步场景)
如果你的登录逻辑是异步的,也可以把返回值改成通过completion handler传递,这样就能避开返回结构体的问题:
public struct User { var userId: String } @objc public static func logIn(_ userId: String, completion: @escaping (NSDictionary?) -> Void) { // 模拟异步登录逻辑 DispatchQueue.main.async { let user = User(userId: userId) completion(["userId": user.userId]) } }
Objective-C端可以通过block接收结果,同样能拿到用户数据。
内容的提问来源于stack exchange,提问作者SriMa
相关产品推荐
相关产品推荐

