在Swift中,如何调用Objective-C代码?
苹果公司提到它们可以在一个应用程序中共存,但这是否意味着在技术上可以重复使用由Objective-C创建的旧类,同时在Swift中构建新类呢?
在Swift中,如何调用Objective-C代码?
苹果公司提到它们可以在一个应用程序中共存,但这是否意味着在技术上可以重复使用由Objective-C创建的旧类,同时在Swift中构建新类呢?
Answers:
如果您要使用现有的类,请执行步骤2,然后跳至步骤5。(在某些情况下,我必须在
#import <Foundation/Foundation.h
旧的Objective-C文件中添加一个显式文件。)
将.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代码,反之亦然。
如果将.swift
文件添加到较旧的项目中并出现错误dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
,请尝试完全重新启动Xcode。
尽管最初可以NSObject
通过使用@objc
前缀使用对Objective-C可见的纯Swift类(不是的后代),但这不再是可能的。现在,要在Objective-C中可见,Swift对象必须是符合的类NSObjectProtocol
(最简单的方法是从继承NSObject
),或用诸如的整数类型的原始值enum
标记。在没有这些限制的情况下,您可以查看Swift 1.x代码示例的编辑历史记录。@objc
Int
@objc
请参阅Apple关于将Swift与Cocoa和Objective-C结合使用的指南。本指南涵盖了如何使用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文件时使用“快速打开”并键入Objective-C类名称,然后将您带到类头的Swift版本。(您也可以通过cmd单击Swift文件中的API符号来获取此信息。)iOS 8和OS X v10.10(Yosemite)开发人员库中的所有API参考文档在Objective-C和Swift中都可见形式(例如UIView
)。
以下是在Swift项目中使用Objective-C代码(在本例中为第三方提供的框架)的分步说明:
简单的步骤:
出现提示,然后单击“确定...”。如果未出现,则如下所示手动创建...从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文件中,您都可以使用Swift语法使用现有的Objective-C代码(在本示例中,您可以调用Mixpanel SDK方法,等等)。您需要熟悉Xcode如何将Objective-C转换为Swift。苹果的指南是快速阅读。或者查看此答案以获取不完整的摘要。
Mixpanel示例:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Mixpanel.sharedInstanceWithToken("your-token")
return true
}
而已!
注意:如果从项目中删除桥接头文件,请确保进入“构建设置”,并删除“快速编译器-代码生成”下“ 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结合使用》。
我写了一个简单的Xcode 6项目,展示了如何混合C ++,Objective-C和Swift代码:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
特别是,该示例从Swift调用了Objective-C和C ++函数。
关键是创建一个共享头Project-Bridging-Header.h,然后在其中放置Objective-C头。
请下载该项目作为完整示例。
我非常感谢@Logan的回答。创建桥接文件和设置会很有帮助。
但是在完成所有这些步骤之后,我仍然没有在Swift中获得Objective-C类。
我使用了cocoapods
库并将其集成到我的项目中。哪个是pod "pop"
。
因此,如果您在Swift中使用Objective-C Pod,则可能会导致无法获取import
类或将其放入Swift。
您要做的简单的事情是:
<YOUR-PROJECT>-Bridging-Header
文件并#import <ObjC_Framework>
为@import ObjC_Framework
例如:(流行音乐库)
更换
#import <pop/POP.h>
与
@import pop;
clang import
在#import
无法使用时使用。
创建桥接头之后,转到Build Setting =>搜索“ Objective-C桥接头”。
在下面,您将找到““ Objective-C生成的接口头名称””文件。
将该文件导入您的视图控制器。
示例:以我为例:“ Dauble-Swift.h”
单击“ 新建文件”菜单,然后选择文件选择语言“目标”。那时,它会自动生成一个“ Objective-C桥接头”文件,该文件用于定义某些类名。
“快速编译器-代码生成”下的“目标C桥接标头”。
在Xcode 10.1的Swift 4.2.1项目中,您可以轻松地添加Objective-C文件。请按照以下步骤将Objective-C文件桥接到Swift项目。
Step_01:使用Swift语言创建新的Xcode项目:
File
> New
> Project
> objc
。
Step_02:在Swift项目中添加新的Objective-C文件:
File
> New
> File...
> macOS
> Objective-C File
。
Step_03:如果您是第一次在Swift项目中添加新的Objective-C文件,Xcode会询问您:
Would you like to configure an Objective-C bridging header
?
步骤_04:选择选项:
Create Bridging Header
。
步骤_05:将生成一个名称对应的文件:
Objc-Bridging-Header.h
。
步骤_06:现在,您需要在网桥头中设置网桥文件路径。在项目浏览器中,单击名称为的项目objc
然后选择:
Build Settings
> Objective-C Bridging Header
>Objc-Bridging-Header.h
。
Step_07:将您的鼠标拖放Objc-Bridging-Header.h
到该框中以生成文件路径。
Step_08:打开Objc-Bridging-Header.h
文件,然后将要使用的Objective-C文件导入Swift文件中。
#import "SpecialObjcFile.m"
以下是内容SpecialObjcFile.m
:
#import <Foundation/Foundation.h>
@interface Person: NSObject {
@public
bool busy;
}
@property
bool busy;
@end
Step_09:现在,在您的Swift文件中,您可以使用Objective-C类:
override func viewDidLoad() {
super.viewDidLoad()
let myObjcContent = Person()
print(myObjcContent.busy)
}
洛根答案很好用,除非最近Swift 5
它给出了一些编译器错误。这是针对使用Swift 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
}
}
添加标头.h
和实现.m
文件-可可类文件(Objective-C)
例如MyFileName
配置桥接标头
看到时Would you like to configure an Objective-C bridging header
单击- 是
<target_name>-Bridging-Header.h
将自动生成添加类桥接报头
中<target_name>-Bridging-Header.h
添加一行#import "<MyFileName>.h"
PS如果您应该将现有的Objective-C文件添加到Swift项目中,请Bridging-Header.h
事先添加
添加<MyFileName>.swift
和扩展NSObject
将Swift文件导入到ObjC类中
添加#import "<#YourProjectName#>-Swift.h"
到您的Objective-C文件中
标记公共Swift代码[@objc和@objcMembers]
Apple已在此文档中提供了官方指南: 如何从Swift调用目标C代码
这是相关的部分:
要将一组Objective-C文件导入同一应用程序目标内的Swift代码中,您需要依靠Objective-C桥接头文件将这些文件公开给Swift。当您将Swift文件添加到现有的Objective-C应用程序或将Objective-C文件添加到现有的Swift应用程序时,Xcode会提供创建此标头的功能。
如果接受,则Xcode会与创建的文件一起创建桥接头文件,并使用产品模块名称后跟“ -Bridging-Header.h”对其进行命名。另外,您可以通过选择文件>新建>文件> [操作系统]>源>头文件来自己创建桥接头。
编辑桥接标头,将您的Objective-C代码公开给您的Swift代码:
Swift可以看到桥接头中列出的所有公共Objective-C头。
使用Objective-C的两种方法Objective-C
1个
2
现在好去 谢谢