在Swift中,如何调用Objective-C代码?

苹果提到它们可以共存于一个应用程序中,但这是否意味着人们可以在技术上重用Objective-C中创建的旧类,同时在Swift中构建新类?


当前回答

在Swift中使用Objective-C类

如果您有一个想要使用的现有类,请执行步骤2,然后跳到步骤5。(在某些情况下,我必须在旧的Objective-C文件中添加显式的#import <Foundation/Foundation.h。)

步骤1:添加Objective-C实现——.m

向类中添加一个.m文件,并将其命名为CustomObject.m。

步骤2:添加桥接头

当添加你的.m文件时,你可能会看到这样的提示:

单击Yes !

如果你没有看到提示,或者不小心删除了桥接头,添加一个新的。h文件到你的项目,并命名为<#YourProjectName#>-Bridging-Header.h。

在某些情况下,特别是在使用Objective-C框架时,你没有显式地添加Objective-C类,Xcode就找不到链接器。在这种情况下,创建如上所述的.h文件,然后确保将其路径链接到目标项目设置中,如下所示:

注意:

使用$(SRCROOT)宏链接您的项目是最好的做法,这样如果您移动您的项目,或使用远程存储库与他人一起处理它,它仍然可以工作。$(SRCROOT)可以被认为是包含.xcodeproj文件的目录。它可能是这样的:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

步骤3:添加Objective-C Header——.h

添加另一个.h文件并将其命名为CustomObject.h。

步骤4:构建Objective-C类

在CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

在CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

步骤5:添加类到桥接头

在YourProject-Bridging-Header.h:

#import "CustomObject.h"

第六步:使用你的对象

在SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

不需要显式地导入;这就是桥接头的作用。

在Objective-C中使用Swift类

步骤1:创建新的Swift类

添加一个.swift文件到你的项目中,并将其命名为MySwiftObject.swift。

在MySwiftObject.swift:

import Foundation

@objc(MySwiftObject)
class MySwiftObject : NSObject {

    @objc
    var someProperty: AnyObject = "Some Initializer Val" as NSString

    init() {}

    @objc
    func someFunction(someArg: Any) -> NSString {
        return "You sent me \(someArg)"
    }
}

步骤2:将Swift文件导入ObjC类

在SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

文件:<#YourProjectName#>-Swift.h应该已经在你的项目中自动创建了,即使你看不到它。

第三步:利用你的课程

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];

NSLog(@"RetString: %@", retString);

注:

If Code Completion isn't behaving as you expect, try running a quick build with ⌘⇧R to help Xcode find some of the Objective-C code from a Swift context and vice versa. If you add a .swift file to an older project and get the error dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, try completely restarting Xcode. While it was originally possible to use pure Swift classes (Not descendents of NSObject) which are visible to Objective-C by using the @objc prefix, this is no longer possible. Now, to be visible in Objective-C, the Swift object must either be a class conforming to NSObjectProtocol (easiest way to do this is to inherit from NSObject), or to be an enum marked @objc with a raw value of some integer type like Int. You may view the edit history for an example of Swift 1.x code using @objc without these restrictions.

其他回答

在Swift中使用Objective-C类

如果您有一个想要使用的现有类,请执行步骤2,然后跳到步骤5。(在某些情况下,我必须在旧的Objective-C文件中添加显式的#import <Foundation/Foundation.h。)

步骤1:添加Objective-C实现——.m

向类中添加一个.m文件,并将其命名为CustomObject.m。

步骤2:添加桥接头

当添加你的.m文件时,你可能会看到这样的提示:

单击Yes !

如果你没有看到提示,或者不小心删除了桥接头,添加一个新的。h文件到你的项目,并命名为<#YourProjectName#>-Bridging-Header.h。

在某些情况下,特别是在使用Objective-C框架时,你没有显式地添加Objective-C类,Xcode就找不到链接器。在这种情况下,创建如上所述的.h文件,然后确保将其路径链接到目标项目设置中,如下所示:

注意:

使用$(SRCROOT)宏链接您的项目是最好的做法,这样如果您移动您的项目,或使用远程存储库与他人一起处理它,它仍然可以工作。$(SRCROOT)可以被认为是包含.xcodeproj文件的目录。它可能是这样的:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

步骤3:添加Objective-C Header——.h

添加另一个.h文件并将其命名为CustomObject.h。

步骤4:构建Objective-C类

在CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

在CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

步骤5:添加类到桥接头

在YourProject-Bridging-Header.h:

#import "CustomObject.h"

第六步:使用你的对象

在SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

不需要显式地导入;这就是桥接头的作用。

在Objective-C中使用Swift类

步骤1:创建新的Swift类

添加一个.swift文件到你的项目中,并将其命名为MySwiftObject.swift。

在MySwiftObject.swift:

import Foundation

@objc(MySwiftObject)
class MySwiftObject : NSObject {

    @objc
    var someProperty: AnyObject = "Some Initializer Val" as NSString

    init() {}

    @objc
    func someFunction(someArg: Any) -> NSString {
        return "You sent me \(someArg)"
    }
}

步骤2:将Swift文件导入ObjC类

在SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

文件:<#YourProjectName#>-Swift.h应该已经在你的项目中自动创建了,即使你看不到它。

第三步:利用你的课程

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];

NSLog(@"RetString: %@", retString);

注:

If Code Completion isn't behaving as you expect, try running a quick build with ⌘⇧R to help Xcode find some of the Objective-C code from a Swift context and vice versa. If you add a .swift file to an older project and get the error dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, try completely restarting Xcode. While it was originally possible to use pure Swift classes (Not descendents of NSObject) which are visible to Objective-C by using the @objc prefix, this is no longer possible. Now, to be visible in Objective-C, the Swift object must either be a class conforming to NSObjectProtocol (easiest way to do this is to inherit from NSObject), or to be an enum marked @objc with a raw value of some integer type like Int. You may view the edit history for an example of Swift 1.x code using @objc without these restrictions.

在Xcode 10.1中的Swift 4.2.1项目中,您可以轻松地添加Objective-C文件。按照以下步骤将Objective-C文件连接到Swift项目。

Step_01:使用Swift语言创建新的Xcode项目:

文件>新建>项目> objc。

在Swift项目中添加新的Objective-C文件:

File >新建>文件…> macOS > Objective-C文件。

Step_03:如果你第一次添加一个新的Objective-C文件到Swift项目中,Xcode会问你:

你想配置一个Objective-C桥接头吗?

Step_04:选择选项:

创建桥接头。

Step_05:将生成一个对应的文件,文件的名称如下:

Objc-Bridging-Header.h。

Step_06:现在,你需要在桥标头中设置桥文件路径。在项目导航器中单击名称为objc的项目,然后选择:

> Objective-C桥接头> objc桥接头。h

将Objc-Bridging-Header.h拖放到该框中生成文件路径。

打开你的Objc-Bridging-Header.h文件,并导入你想要在Swift文件中使用的Objective-C文件。

#import "SpecialObjcFile.m"

下面是SpecialObjcFile.m的内容:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

现在在你的Swift文件中,你可以使用一个Objective-C类:

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}

使用objective-c的双向方法

1

在Xcode Project中创建bridge-header.h文件 在bridge-Header文件中导入.h文件 在Build设置中设置bridge-Header的路径。 清理项目

2

在项目中创建objective-c文件(它会自动在Build Settings中为您设置路径) 在bridge-Header文件中导入.h文件

现在可以开始了 谢谢

我还想补充一点:

我非常感谢@Logan的回答。创建桥文件和设置有很大帮助。

但是在做了所有这些步骤之后,我仍然没有在Swift中获得Objective-C类。

我使用cocoapods库并将其集成到我的项目中。也就是豆荚"pop"。

因此,如果你在Swift中使用Objective-C pod,那么可能有一个机会,你不能获得或导入类到Swift中。

你要做的一件简单的事情是:

转到<YOUR-PROJECT>-Bridging-Header文件和 将语句#import <ObjC_Framework>替换为@import ObjC_Framework

例如:(Pop library)

取代

#import <pop/POP.h>

with

@import pop;

当#import无效时使用clang import。

引用自文档:

Any Objective-C framework (or C library) that’s accessible as a module can be imported directly into Swift. This includes all of the Objective-C system frameworks—such as Foundation, UIKit, and SpriteKit—as well as common C libraries supplied with the system. For example, to import Foundation, simply add this import statement to the top of the Swift file you’re working in: import Foundation This import makes all of the Foundation APIs—including NSDate, NSURL, NSMutableData, and all of their methods, properties, and categories—directly available in Swift.