在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.

点击新建文件菜单,并选择文件选择语言目标。这时,它会自动生成一个“Objective-C Bridging Header”文件,用于定义一些类名。

“Swift编译器-代码生成”下的“Objective-C桥接头”。

登录的答案工作良好,除了在最新的Swift 5,它给出了一些编译器错误。以下是针对Swift 5开发人员的修复。

斯威夫特5

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val" as AnyObject

    override init() {}

    func someFunction(someArg:AnyObject) -> String {
        let returnVal = "You sent me \(someArg)"
        return returnVal
    }
}

Create a .h file from NewFile -> Source -> header file Then save the name of file Your_Target_Name-Bridging-Header.h People here gets common mistake by taking their project name but it should be the Project's Target's name if in case both are different, generally they are same. Then in build settings search for Objective-C Bridging Header flag and put the address of your newly created bridging file, you can do it right click on the file -> show in finder -> drag the file in the text area then the address will be populated. Using #import Your_Objective-C_file.h In the swift file you can access the ObjC file but in swift language only.

混合Objective-C和Swift

高层图:

相同的目标

//Objective-C exposes API for Swift thought <target_name>-Bridging-Header.h
.swift uses .h.m = Swift consumer, Objective-C producer = <target_name>-Bridging-Header.h

//Swift exposes API for Objective-C thought <target_name>-Swift.h
.h.m uses .swift = Objective-C consumer, Swift producer = <target_name>-Swift.h

Swift消费者,Objective-C生产者

添加一个新的头文件。h和实现文件。m - Cocoa类文件(Objective-C) 例如<MyFileName>.h和<MyFileName>.m 配置桥接报头 当您看到“是否想配置Objective-C桥接头”时,单击“是” <target_name>-Bridging-Header.h将自动生成 构建设置-> Objective-C桥接头(SWIFT_OBJC_BRIDGING_HEADER) 将类添加到桥接头 在<target_name>-Bridging-Header.h中添加一行#import "<MyFileName>.h"

之后你可以使用Swift Objective-C的MyFileName.h,MyFileName.m

附注:如果你要添加一个现有的Objective-C文件到Swift项目中,请预先添加Bridging-Header.h并导入它

Objective-C消费者,Swift生产者

添加一个<MyFileName>.swift和extends NSObject 将Swift文件导入ObjC类 在Objective-C文件中添加#import "<target_name>-Swift.h" 通过@objc公开Swift代码[关于]

在此之后,您可以使用Objective-C Swift的<MyFileName>.swift

[<product_name>-Swift.h文件未找到]

不同的目标 (。modulemap]和[伞盖.h]用于暴露Objective-C for Swift。Swift.h用于为Objective-C公开Swift代码

(词汇)