在Swift中,如何调用Objective-C代码?
苹果公司提到它们可以共存于一个应用程序中,但这是否意味着在构建Swift新类的同时,可以技术上重用以前使用Objective-C创建的旧类?
在Swift中,如何调用Objective-C代码?
苹果公司提到它们可以共存于一个应用程序中,但这是否意味着在构建Swift新类的同时,可以技术上重用以前使用Objective-C创建的旧类?
如果您有一个现有的类想要使用,请执行第2步,然后跳转到第5步。(某些情况下,我需要向旧的Objective-C文件添加显式的
#import <Foundation/Foundation.h>
。)
将.m
文件添加到您的类中,并将其命名为CustomObject.m
。
当添加.m
文件时,可能会弹出如下提示:
点击是!
如果您没有看到提示,或意外删除了桥接头文件,请添加一个新的.h
文件到您的项目中,并将其命名为<#YourProjectName#>-Bridging-Header.h
。
在某些情况下,特别是在使用Objective-C框架时,您不会显式地添加Objective-C类,而且Xcode无法找到链接器。在这种情况下,请创建如上所述命名的.h
文件,然后确保您在目标项目设置中链接其路径,如下所示:
注意:
最佳实践是使用$(SRCROOT)
宏链接您的项目,这样如果您移动项目或与使用远程存储库的其他人一起工作,则仍将正常工作。 $(SRCROOT)
可以被认为是包含您的.xcodeproj文件的目录。可能会像这样:
$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
再添加一个.h
文件,将其命名为CustomObject.h
。
在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
在YourProject-Bridging-Header.h
中:
#import "CustomObject.h"
在SomeSwiftFile.swift
中:
var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
不需要显式导入; 这就是桥接头文件的作用。
向您的项目添加一个.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)"
}
}
在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);
如果代码补全没有按照你的期望行事,请尝试使用 ⌘⇧R 进行快速构建,帮助Xcode在Swift上下文和Objective-C之间找到一些Objective-C代码。反之亦然。
如果您将一个 .swift
文件添加到旧项目中,并出现错误 dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
,请尝试完全重新启动Xcode。
原来可以使用纯Swift类(非 NSObject
的子类)并使用 @objc
前缀使其在Objective-C中可见,但是现在不再支持此操作。现在,要在Objective-C中可见,Swift对象必须要么是遵循 NSObjectProtocol
协议的类(最简单的方法是继承自 NSObject
),要么是标记为 @objc
并具有某个整数类型(如 Int
)的原始值的 enum
。 您可以查看Swift 1.x代码的编辑历史记录,其中使用了没有这些限制的 @objc
示例。
#import "ProductModuleName-Swift.h"
,它默认为项目名称,大多数人不会更改它。 - LoganUITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
转换为这个 Swift 代码:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
UIView
)。出现提示,然后点击“确定”…如果没有出现,则可以手动创建如下…从iOS源代码中创建一个头文件,并将其命名为ProjectName-Bridging-Header(例如:Test-Bridging-Header),然后转到Swift编译器代码的构建设置->Objective-C桥接添加Objective-C桥接名称..(Test/Test-Bridging-Header.h)。是的,完成了。
可选地,删除您添加的Objective-C文件(在上面的GIF图像中命名为“anything”)。 您不再需要它。
打开桥接头文件--文件名的格式为[YourProject]-Bridging-Header.h。 它包括Xcode提供的注释。 添加一行代码以包含要包含的Objective-C文件,例如第三方框架。 例如,要将Mixpanel添加到项目中,您需要向桥接头文件添加以下代码行:
#import "Mixpanel.h"
现在,在任何Swift文件中,您都可以使用现有的Objective-C代码,使用Swift语法(在此示例中,您可以调用Mixpanel SDK方法等)。 您需要熟悉Xcode如何将Objective-C翻译成Swift。 苹果公司的指南是一个快速阅读。 或者查看此答案以获取不完整的摘要。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Mixpanel.sharedInstanceWithToken("your-token")
return true
}
这就是全部内容!
注意:如果从项目中删除桥接头文件,请确保进入“构建设置”并删除“Swift编译器 - 代码生成”下的“Objective-C桥接头文件”的值。
你可以阅读这篇不错的文章: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)
})
还要查看苹果公司的文档 使用Swift与Cocoa和Objective-C。
非常感谢@Logan的答案。它对创建桥接文件和设置有很大帮助。
但是,即使完成了所有这些步骤,我仍然无法在Swift中获得Objective-C类。
我使用了库,并将其集成到我的项目中。该库是"pop"。
因此,如果您正在Swift中使用Objective-C pods,则可能无法获得或导入这些类。
您所需要做的简单的事情是:
<YOUR-PROJECT>-Bridging-Header
文件并#import <ObjC_Framework>
替换为@import ObjC_Framework
例如:(Pop library)
将
#import <pop/POP.h>
与,以及
@import pop;
当 #import
无法工作时,请使用 clang import
。
引用自文档:
任何作为模块可访问的Objective-C框架(或C库)都可以直接导入Swift。这包括所有Objective-C系统框架,例如Foundation、UIKit和SpriteKit,以及系统附带的常见C库。例如,要导入Foundation,只需将以下导入语句添加到您正在工作的Swift文件的顶部:
import Foundation
这个导入使得所有Foundation API,包括NSDate、NSURL、NSMutableData以及它们的方法、属性和类别在Swift中直接可用。
混合使用Objective-C和Swift
高级别示意图:
同一目标
//Objective-C exposes API for Swift through <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 through <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
配置桥接头文件
当你看到Would you like to configure an Objective-C bridging header
时,点击 - Yes
<target_name>-Bridging-Header.h
会自动生成将类添加到桥接头文件中
在<target_name>-Bridging-Header.h
文件中添加一行#import "<MyFileName>.h"
之后您可以使用Swift
的Objective-C's
MyFileName.h
、MyFileName.m
P.S.如果您应该将一个已存在的Objective-C文件添加到Swift项目中,请先添加Bridging-Header.h
并导入它
Objective-C消费者,Swift生产者
添加一个<MyFileName>.swift
并扩展NSObject
将Swift文件导入到ObjC类中
将#import "<target_name>-Swift.h"
添加到您的Objective-C文件中
通过@objc
公开Swift代码 [About]
之后,您就可以使用来自Objective-C
的Swift's
<MyFileName>.swift
[<product_name>-Swift.h file not found]
不同的目标
[.modulemap]和[umbrella.h]用于公开Swift的Objective-C。而Swift.h
用于公开Objective-C的Swift代码
对于任何想要向Swift添加Objective-C库的人,请注意:您应该在构建设置->链接->其他链接器标志中添加-ObjC。