提问



在Apple的新Swift语言中,如何调用Objective-C代码?



Apple提到它们可以在一个应用程序中共存,但这是否意味着可以在技术上重用Objective-C中的旧类,同时在Swift中构建新类?


推理



Objective-C是一种独立于平台的语言,而Swift则依赖于平台。因此,在Swift中编写非平台相关代码(业务逻辑库)并不明智。但是,在其中编写与平台相关的代码(例如与接口相关)将非常好。不是说它会是一个好主意,但它绝对是一种兴趣。

最佳参考


在Swift中使用Objective-C类



**
如果您有一个您想要使用的现有课程,请执行步骤2 ,然后跳到步骤5 。(在某些情况下,我必须添加一个明确的[[#import <Foundation/Foundation.h到较旧的Objective-C文件。)
**


第1步:添加Objective-C实现 - .m



.m文件添加到您的班级,并将其命名为CustomObject.m


第2步:添加桥接标题



添加.m文件时,您可能会遇到如下提示:





点击!


如果您没有看到提示或意外删除了桥接标题,请在项目中添加一个新的.h文件并将其命名为<#YourProjectName#>-Bridging-Header.h


在某些情况下,特别是在使用Objective-C框架时,您不会显式添加Objective-C类,Xcode也无法找到链接器。在这种情况下,创建如上所述命名的.h文件,然后确保在目标的项目设置中链接其路径,如下所示:





注意


最好使用$(SRCROOT)宏链接您的项目,这样如果您移动项目,或者使用远程存储库与其他人一起工作,它仍然可以工作。$(SRCROOT)可以被认为是作为包含.xcodeproj文件的目录。它可能如下所示:


$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h


第3步:添加Objective-C标头 - .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:向Bridging-Header添加类



YourProject-Bridging-Header.h中:


#import "CustomObject.h"


第6步:使用您的对象



SomeSwiftFile.swift中:


var instanceOfCustomObject: CustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()


无需明确导入;这就是桥接头的用途。


在Objective-C中使用Swift类



第1步:创建新的Swift类



.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
    }   
}


第2步:将Swift文件导入ObjC类



SomeRandomClass.m中:


#import "<#YourProjectName#>-Swift.h"


文件:<#YourProjectName#>-Swift.h应该已经在项目中自动创建,即使您看不到它。


第3步:使用你的班级



MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
NSString * retString = [myOb someFunction:@"Arg"];
NSLog(@"RetString: %@", retString);


注意:



1。 CodeCompletion并没有像我想的那样准确。在我的系统上,使用cmd + r运行快速构建似乎有助于Swift找到一些Objective-C代码,反之亦然。


2。如果您将.swift文件添加到较旧的项目并收到错误:dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib,请尝试完全重新启动Xcode。


3。虽然最初可以通过使用@objc前缀在Objective-C中使用纯Swift类,但在Swift 2.0之后,这已不再可能。有关原始说明,请参阅编辑历史如果在将来的Swift版本中重新启用此功能,则答案将相应更新。

其它参考1


请参阅Apple的使用Swift与Cocoa和Objective-C的指南。本指南介绍了如何使用Swift中的Objective-C和C代码,反之亦然,并提供了如何转换项目或混合和匹配Objective-C/C的建议。和现有项目中的Swift部分。[75]


编译器自动生成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)。[76] [77] [78]

其它参考2


以下是在Swift项目中使用Objective-C代码(在本例中为第三方提供的框架)的分步说明:



  1. 通过选择文件 - >新建 - >新建文件 - >目标-C文件,将任何Objective-C文件添加到Swift项目。保存后, Xcode会询问您是否要添加桥接标头。选择。 Gif:将空文件添加到项目并生成桥接头http://www.derrrick.com/stackoverflow/1-empty-file.gif



简单的步骤:[79]



  1. 出现提示,然后单击确定...如果没有出现,则我们手动创建它,如下所示...从iOS源创建一个头文件并命名为ProjectName-Bridging-Header(例如:Test-Bridging-Header),然后转到Swift编译器代码中的构建设置 - > Objective-C bridge添加Objective-C桥接名称..(Test/Test-Bridging-Header.h)。是的,那是完整的。

  2. (可选)删除您添加的Objective-C文件(在上面的GIF图像中命名为any)。你不再需要了。

  3. 打开桥接头文件 - 文件名的格式为 [[YourProject]] -Bridging-Header.h 。它包括Xcode提供的评论。 为要包含的Objective-C文件添加一行代码,例如第三方框架。例如,要将Mixpanel添加到项目中,您需要将以下代码行添加到桥接头文件中:


    #import "Mixpanel.h"

  4. 现在,在任何Swift文件中,您都可以使用现有的Objective-C代码,使用Swift语法(在本例中,您可以调用Mixpanel SDK方法等)。您需要熟悉Xcode如何将Objective-C转换为Swift。 Apple的指南是一个快速阅读。或者看到这个答案的不完整摘要。[80]



Mixpanel的示例:


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}


而已!


注意:如果从项目中删除桥接头文件,请务必进入构建设置并删除Swift编译器下 Objective-C桥接头的值 - 代码生成。

其它参考3


你可以阅读好文章 Swift&的CocoaPods 。基本上,我们需要创建一个桥接头文件并将所有Objective-C头放在那里。然后我们需要从构建设置中引用它。之后,我们可以使用Objective-C代码。[81]


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的文档使用Swift与Cocoa和Objective-C 。[82]

其它参考4


我写了一个简单的Xcode 6项目,展示了如何混合使用C ++,Objective-C和Swift代码:


https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console[83]


特别是,示例 从Swift调用Objective-C和C ++函数


关键是创建一个共享头,Project-Bridging-Header.h,并将Objective-C头放在那里。


请下载该项目作为完整示例。

其它参考5


从文件中引用:[84]



  任何可作为模块访问的Objective-C框架(或C库)
  可以直接导入Swift。这包括所有的
  Objective-C系统框架 - 例如Foundation,UIKit和
  SpriteKit以及随系统提供的通用C库。对于
  例如,要导入Foundation,只需将此import语句添加到
  您正在使用的Swift文件的顶部:

  
  import Foundation

  
  这个导入使所有的Foundation API - 包括NSDate,NSURL,
  NSMutableData,以及它们的所有方法,属性和
  类别 - 可直接在Swift中使用。


其它参考6


我想在此处补充一点:



我非常感谢@Logan的回答。创建桥文件和设置有很大帮助。


但是在完成所有这些步骤后,我仍然没有在Swift中获得Objective-C类。


我使用cocoapods库并将其集成到我的项目中。这是pod "pop"


因此,如果在Swift中使用Objective-C pod,则可能无法将类或import类转换为Swift。


你要做的很简单:



  1. 转到<YOUR-PROJECT>-Bridging-Header文件和

  2. 将声明#import <ObjC_Framework>替换为@import ObjC_Framework



例如:(流行图书馆)


更换


#import <pop/POP.h>





@import pop;


#import不起作用时使用clang import

其它参考7


对于想要向Swift添加Objective-C库的人,请注意:您应该在构建设置 - > 链接中添加 -ObjC - > 其他链接器标志。

其它参考8


创建桥接标头后,转到Build Setting => Search forObjective-C Bridging Header。


在下面你会发现Objective-C Generated Interface Header Name文件。


在视图控制器中导入该文件。


示例:在我的情况下:Dauble-Swift.h


[85]

其它参考9


单击 New 文件菜单,然后选择文件选择语言Objective。那时它会自动生成一个Objective-C Bridging Header文件,用于定义一些类名。


Swift编译器 - 代码生成下的Objective-C Bridging Header。

其它参考10



  1. 从NewFile - > Source - > header file
  2. 创建一个.h文件
  3. 然后保存文件的名称​​ Your_Target_Name-Bridging-Header.h 这里的人们通过获取他们的项目名称会遇到常见的错误,但如果两者都是,那么它应该是Project的目标名称不同,一般都是一样的。

  4. 然后在构建设置中搜索 Objective-C Bridging Header 标志并输入新创建的桥接文件的地址,你可以右键单击文件 - >在finder中显示 - >拖动文本区域中的文件将填充地址。

  5. 使用#import Your_Objective-C_file.h

  6. 在swift文件中,您可以访问ObjC文件,但只能使用swift语言。


其它参考11


任何可作为模块访问的Objective-C框架(或C库)都可以直接导入Swift。这包括所有Objective-C系统框架 - 例如Foundation,UIKit和SpriteKit - 以及随系统提供的通用C库。例如,要导入Foundation,只需将此import语句添加到您正在使用的Swift文件的顶部:


import Foundation


此导入使所有Foundation API(包括NSDate,NSURL,NSMutableData及其所有方法,属性和类别)直接在Swift中可用。


我从Apple的文档中得到了这个。

其它参考12


使用objective-c objective-c 的双向方法


1


1. Create bridge-header.h file in Xcode Project
2. import .h file in bridge-Header file
3. Set path of bridge-Header in Build settings. 
3. Clean the Project 


2


  1. Create objective-c files in project(it automatically set path in Build Settings for you )
  2. import .h file in bridge-Header file


现在好好去
由于

其它参考13


我在github上添加了包含小样本的项目,以便从swift调用目标c代码。[[[86]


从swift调用ObjectiveC类[87]

其它参考14


在Xcode 9.4的Swift 4.2项目中,您可以轻松添加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?


[88]


Step_04:选择选项:


Create Bridging Header


Step_05:将生成一个名称相应的文件:


Objc-Bridging-Header.h


[89]


Step_06:现在,您需要在桥接头中设置Bridge文件路径。在Project Navigator中,单击名称为objc的项目,然后选择:


Build Settings> Objective-C Bridging Header> Objc-Bridging-Header.h


Step_07:将Objc-Bridging-Header.h拖放到该框中以生成文件路径。


[90]


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)
}



[91] [92]