Apple提到它们可以在一个应用程序中共存,但这是否意味着可以在技术上重用Objective-C中的旧类,同时在Swift中构建新类?
Objective-C是一种独立于平台的语言,而Swift则依赖于平台。因此,在Swift中编写非平台相关代码(业务逻辑库)并不明智。但是,在其中编写与平台相关的代码(例如,与接口相关)将非常好。不是说这是一个好主意,但它肯定是一种兴趣。
**如果您有一个您想要使用的现有类,请执行步骤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 = 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版本中重新启用此功能,则答案将相应更新。
单击New file菜单,然后选择文件选择语言Objective。那时它会自动生成一个“Objective-C Bridging Header”文件,用于定义一些类名。
“Swift编译器 - 代码生成”下的“Objective-C Bridging Header”。
在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
?
Step_04:选择选项:
Create Bridging Header
。
Step_05:将生成一个名称相应的文件:
Objc-Bridging-Header.h
。
Step_06:现在,您需要在桥接头中设置Bridge文件路径。在Project Navigator中,单击名为objc
的项目,然后选择:
Build Settings
> Objective-C Bridging Header
> Objc-Bridging-Header.h
。
Step_07:将你的Objc-Bridging-Header.h
拖放到该框中以生成文件路径。
Step_08:打开Objc-Bridging-Header.h
文件并导入要在Swift文件中使用的Objective-C文件。
#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)
}
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代码:
Swift可以看到桥接头中列出的任何公共Objective-C头。
双向使用objective-c objective-c的方法
1
2
现在很高兴去谢谢
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
}
}
请参阅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符号来获取此信息。)iOS 8和OS X v10.10 (Yosemite)开发人员库中的所有API参考文档都可以在Objective-C和Swift格式中看到(例如UIView
)。
以下是在Swift项目中使用Objective-C代码(在本例中为第三方提供的框架)的分步说明:
简单的步骤:
Mixpanel的示例:
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)
})
另请参阅Apple的文档Using Swift with Cocoa and 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头放在那里。
请下载该项目作为完整示例。
任何可作为模块访问的Objective-C框架(或C库)都可以直接导入Swift。这包括所有Objective-C系统框架 - 例如Foundation,UIKit和SpriteKit - 以及随系统提供的通用C库。例如,要导入Foundation,只需将此import语句添加到您正在使用的Swift文件的顶部:
import Foundation
此导入使所有Foundation API(包括NSDate,NSURL,NSMutableData及其所有方法,属性和类别)直接在Swift中可用。
我非常感谢@ 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
。
对于试图向Swift添加Objective-C库的人来说只是一个注释:你应该在Build Settings - > Linking - > Other Linker Flags中添加-ObjC。