在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 & Cocoapods的帖子。基本上,我们需要创建一个桥接头文件,并将所有Objective-C头文件放在那里。然后我们需要从构建设置中引用它。之后,我们可以使用Objective-C代码。

let manager = AFHTTPRequestOperationManager()
manager.GET(
  "http://example.com/resources.json",
  parameters: nil,
  success: { (operation: AFHTTPRequestOperation!,
              responseObject: AnyObject!) in
      println("JSON: " + responseObject.description)
  },
  failure: { (operation: AFHTTPRequestOperation!,
              error: NSError!) in
      println("Error: " + error.localizedDescription)
  })

也可以看看苹果的文档Using Swift with Cocoa和Objective-C。

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

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

参见Apple的使用Cocoa和Objective-C的Swift指南。本指南涵盖了如何使用Swift中的Objective-C和C代码,反之亦然,并对如何转换项目或在现有项目中混合和匹配Objective-C/C和Swift部分提出了建议。

编译器自动生成调用C函数和Objective-C方法的Swift语法。如文档所示,这个Objective-C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

变成了这样的Swift代码:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

Xcode也可以在运行中进行这种转换——你可以在编辑Swift文件时使用Open quick,并输入Objective-C类名,它会带你到Swift化的类头。(你也可以通过cmd点击Swift文件中的API符号来获得。)iOS 8和OS X v10.10 (Yosemite)开发者库中的所有API参考文档在Objective-C和Swift表单(例如UIView)中都是可见的。

给那些试图将Objective-C库添加到Swift的人一个提示:你应该在构建设置中添加- objc ->链接->其他链接器标志。

引用自文档:

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.