Objective-C是一种独立于平台的语言,而Swift则依赖于平台。因此,在Swift中编写非平台相关代码(业务逻辑库)并不明智。但是,在其中编写与平台相关的代码(例如,与接口相关)将非常好。不是说它会是一个好主意,但它肯定是一种兴趣。
答案 0 :(得分:1307)
**
如果您有现有的课程,请执行步骤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 = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
无需明确导入;这就是桥接头的用途。
将.swift
文件添加到您的项目中,并将其命名为MySwiftObject.swift
。
在MySwiftObject.swift
:
import Foundation
class MySwiftObject : NSObject {
var someProperty: AnyObject = "Some Initializer Val"
init() {}
func someFunction(someArg:AnyObject) -> String {
var returnVal = "You sent me \(someArg)"
return returnVal
}
}
在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);
// original
NSString * retString = [myOb someFunction:@"Arg"];
// xcode10 expands the external arg here
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];|
NSLog(@"RetString: %@", retString);
1。 CodeCompletion的行为并不像我想的那样准确。在我的系统上,使用“cmd + r”运行快速构建似乎有助于Swift找到一些Objective-C代码,反之亦然。
2。如果您向旧项目添加.swift
文件并收到错误:dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
,请完全尝试restarting Xcode。
3。虽然最初可以使用@objc
前缀在Objective-C中使用纯Swift类,但在Swift 2.0之后,这已不再可能。有关原始说明,请参阅编辑历史如果在将来的Swift版本中重新启用此功能,答案将相应更新。
答案 1 :(得分:115)
请参阅Apple的Using Swift with Cocoa and Objective-C指南。本指南介绍了如何使用Swift中的Objective-C和C代码,反之亦然,并提供了如何在现有项目中转换项目或混合和匹配Objective-C / C和Swift部件的建议。
编译器自动生成Swift语法,用于调用C函数和Objective-C方法。如文档中所示,此Objective-C:
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
变成了这个Swift代码:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Xcode也可以动态执行此转换 - 您可以在编辑Swift文件时使用Open Quickly并键入Objective-C类名,然后它将带您进入类标题的Swift-ified版本。 (您也可以通过cmd单击Swift文件中的API符号来获取此信息。)在{-3}}和iOS 8开发人员库中的所有API参考文档都可在Objective-C和Swift中看到表格(例如OS X v10.10 (Yosemite))。
答案 2 :(得分:57)
以下是在Swift项目中使用Objective-C代码(在本例中为第三方提供的框架)的分步说明:
简单的步骤:
出现提示,然后单击确定...如果没有出现,则我们手动创建它,如下所示...从iOS源创建一个头文件并命名为ProjectName-Bridging -Header(例如:Test-Bridging-Header),然后转到Swift编译器代码中的构建设置 - &gt; Objective-C网桥添加Objective-C网桥名称..(Test / Test-Bridging-Header.h)。是的,那已经完成了。
或者,删除您添加的Objective-C文件(在上面的GIF图像中命名为&#34;任何&#34;)。你不再需要它了。
打开桥接头文件 - 文件名的格式为 [YourProject] -Bridging-Header.h 。它包括Xcode提供的评论。 为要包含的Objective-C文件添加一行代码,例如第三方框架。例如,要将Mixpanel添加到项目中,您需要将以下代码行添加到桥接头文件中:
#import "Mixpanel.h"
现在在任何Swift文件中,您都可以使用现有的Objective-C代码,使用Swift语法(在本例中,您可以调用Mixpanel SDK方法等) 。您需要熟悉Xcode如何将Objective-C转换为Swift。 Apple's guide快速阅读。或者查看此答案以获得不完整的摘要。
Mixpanel的例子:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Mixpanel.sharedInstanceWithToken("your-token")
return true
}
那就是它!
注意:如果从项目中删除桥接头文件,请务必进入构建设置并删除&#34; Objective-C桥接头&#34;在&#34; Swift编译器 - 代码生成&#34;。
答案 3 :(得分:36)
您可以阅读不错的帖子 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)
})
另请查看Apple的文档 Using Swift with Cocoa and Objective-C 。
答案 4 :(得分:23)
我写了一个简单的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头放在那里。
请下载该项目作为完整示例。
答案 5 :(得分:20)
任何可作为模块访问的Objective-C框架(或C库) 可以直接导入Swift。这包括所有的 Objective-C系统框架 - 例如Foundation,UIKit和 SpriteKit以及随系统提供的通用C库。对于 例如,要导入Foundation,只需将此import语句添加到 您正在使用的Swift文件的顶部:
import Foundation
此导入使所有Foundation API - 包括NSDate,NSURL, NSMutableData,以及它们的所有方法,属性和 类别 - 可直接在Swift中使用。
答案 6 :(得分:19)
我非常感谢@ 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
。
答案 7 :(得分:10)
对于想要向Swift添加Objective-C库的人员,请注意:您应该在构建设置中添加 -ObjC - &gt; 链接 - &gt; 其他链接标记。
答案 8 :(得分:8)
创建桥接标头后,转到Build Setting =&gt;搜索“Objective-C Bridging Header”。
在下面你会找到“”Objective-C Generated Interface Header Name“文件。
在视图控制器中导入该文件。
示例:在我的情况下:“Dauble-Swift.h”
答案 9 :(得分:3)
答案 10 :(得分:3)
答案 11 :(得分:1)
在Xcode 10.1的Swift 4.2.1项目中,您可以轻松添加Objective-C文件。按照以下步骤将Objective-C文件桥接到Swift项目。
Step_01:使用Swift语言创建新的Xcode项目:
if __name__=='__main__':
while(True):
try:
print "***********"
print "1. Continuous"
print "2. Single Step"
print "***********"
try:
choice = int(raw_input('Choose a number between 1 & 2: '))
number = choice
move_group_python_interface()
except ValueError:
print "ERROR! Choose a number between 1 and 2"
except rospy.ROSInterruptException:
break
&gt; File
&gt; New
&gt; Project
。
Step_02:在Swift项目中添加新的Objective-C文件:
objc
&gt; File
&gt; New
&gt; File...
&gt; macOS
。
Step_03:如果你第一次在Swift项目中添加一个新的Objective-C文件,Xcode会问你:
Objective-C File
?
Step_04:选择选项:
Would you like to configure an Objective-C bridging header
。
Step_05:将生成一个名称为
的相应文件 Create Bridging Header
。
Step_06:现在,您需要在桥接头中设置Bridge文件路径。在Project Navigator中,单击名为Objc-Bridging-Header.h
的项目,然后选择:
objc
&gt; Build Settings
&gt; Objective-C Bridging Header
。
Step_07:将Objc-Bridging-Header.h
拖放到该框中以生成文件路径。
Step_08:打开Objc-Bridging-Header.h
文件并导入要在Swift文件中使用的Objective-C文件。
Objc-Bridging-Header.h
这里的内容为#import "SpecialObjcFile.m"
:
SpecialObjcFile.m
Step_09:现在在你的Swift文件中,你可以使用Objective-C类:
#import <Foundation/Foundation.h>
@interface Person: NSObject {
@public
bool busy;
}
@property
bool busy;
@end
答案 12 :(得分:0)
使用objective-c objective-c的双向方法
<强> 1 强>
<强> 2 强>
现在好转 的由于强>
答案 13 :(得分:0)
Apple在此文档中提供了官方指南: how-to-call-objective-c-code-from-swift
这是相关部分:
要将一组Objective-C文件导入同一应用程序目标内的Swift代码中,您需要依赖 Objective-C桥接头文件将这些文件暴露给Swift 。当您将Swift文件添加到现有的Objective-C应用程序或将Objective-C文件添加到现有的Swift应用程序时,Xcode会创建此标头。
如果接受,则Xcode会与创建的文件一起创建桥接头文件,并使用产品模块名称后跟“ -Bridging-Header.h”对其进行命名。或者,您可以通过选择文件>新建>文件> [操作系统]>源>头文件
来自己创建桥接头。编辑桥接标头以将您的Objective-C代码公开给您的Swift代码:
桥接标头中列出的任何公共Objective-C标头对Swift都是可见的。
答案 14 :(得分:0)
Logans answer可以正常工作,但最新的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
}
}
答案 15 :(得分:0)
添加头文件.h
和实现文件.m
-可可类文件
例如MyFileName
配置桥接头
当您看到Would you like to configure an Objective-C bridging header
时,请点击-是
将类添加到Bridging-Header
在Project-Bridging-Header.h
中添加一行#import "<MyFileName>.h"
添加一个<MyFileName>.swift
并扩展NSObject
将Swift文件导入到ObjC类中
将#import "<#YourProjectName#>-Swift.h"
添加到您的Objective-C文件中
标记公共Swift代码[@objc and @objcMembers]
答案 16 :(得分:0)
制作NSObject的任何Swift类子类也很有意义,我更喜欢使用任何Swift类在Objective-C类中看到:
@objc(MySwiftClass)
@objcMembers class MySwiftClass {...}