Objective-C代码可以在Class上调用swift扩展吗?


94

我搜索了一些帖子,我想我不能在swift下编写扩展,然后从Objective-C代码中调用它,对吗?

@objc之类的属性仅支持方法,类,协议?


1
您为什么不尝试一下呢?
2014年

7
ide抱怨错误,但我想得到一个确定的答案。
sprhawk

Answers:


84

您可以编写一个Swift扩展并将其用在Objective-C代码中。使用XCode 6.1.1测试。

您需要做的只是:

  • 在Swift中创建扩展(无@objc注释)

  • #import "ProjectTarget-Swift.h" 在Objective-C类中(其中“ ProjectTarget”表示Swift扩展与之关联的XCode目标)

  • 从Swift扩展中调用方法

更新: 自@Rizwan Ahmed提到的,您需要添加@objc注释:

从Swift 4.0.3开始,如果要在Objective C类文件中使用扩展名,则需要@objc批注。


6
我已经做到了,但这仍然是编译时错误。嗯 编辑:我导入了我的桥接标头,而不是 “ ProjectTarget-Swift.h”。叔叔
Jason Renaldo

两者都是桥接头。区别在于,一个用于在ObjC中使用Swift代码,另一个用于在Swift中使用ObjC代码。Swift标头不可见。另一个,应该由您管理。
marius bardan 2015年

胡力(William Hu),请参阅mclaughlinj的答案!
appleitung '16

39
从Swift 4.0.3开始,如果要在Objective C类文件中使用扩展名,则需要@objc批注。
Rizwan Ahmed

69

我发现在Swift 4.0中,我必须@objc扩展程序的前面添加关键字以使Swift扩展方法对我正在扩展的Objc类的实例可见。

简而言之:

文件配置设置:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

在CustomClassExtension中:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

在我的AppDelegate.m中:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];

2
如果方法使用泛型,那么Objective-C将无法使用它,您需要添加@nonobjc注释。
ThomasW

只是一个旁注,@ objcMembers在这种情况下不起作用。不知道为什么.. :-(
Raunak

46

此解决方案适用于Swift 2.2和Swift 3。请注意,只能从Objective-C访问类的扩展(不适用于结构或枚举)。

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

然后#import“ ProductModuleName-Swift.h”在您的ObjC文件中。

斯威夫特4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

这不是“YourProjectsNameHere ......”,而是“YourTargetsNameHere ...”:到份额的目标,你必须锁定它的名字: dr2050.postach.io/post/...
丹Rosenstark

1
@DanRosenstark你是对的。正如苹果建议的那样,我将其更改为“ ProductModuleName-Swift.h”:developer.apple.com/library/ios/documentation/Swift/Conceptual/…–
Foti Dim

1
工作正常,迅速3.
维克托·库塞拉

public有需要的理由吗?没有public修饰符,对我来说效果很好。我们是否假设扩展名不在同一个项目中,而是从另一个项目中导入的?
李康

我需要使用桥接头吗?
jegadeesh

42

如其他答案所述,在大多数情况下,导入生成的Swift标头即可。

例外是,类别是在桥接类型上定义的(即,扩展名是在String而不是上定义的NSString)。这些类别不会自动桥接到其Objective-C对应项。为了解决这个问题,您要么需要使用Objective-C类型(并使用来转换Swift代码中的返回值as String),要么为Swift和Objective-C类型定义扩展名。


2
除了上述答案外,您还应该将Swift扩展名公开,并将其类型设置为NSString,例如public extension NSString。如果您在编译时遇到无法解析的标识符或类似错误,则可以再次let sVal = self as String将其sVal
强制转换

@RunLoop实际上您不需要public,它将在没有范围说明符的情况下工作。而且它(导出到Obj-C)对字符串不起作用,因为它们是结构,而不是类,并且只能从Swift获得。因此,是的–您可以为NSString编写扩展名并使用mclaughlinj
强制转换

3

在Objective-C文件中导入 “ #import“ ProductModuleName-Swift.h”标头,并在swift文件的扩展名前面添加@objc。在swift 4.2和swift 5中可以正常工作

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.