OC Swift混编

2,501 阅读3分钟

前言

因最近准备切换公司Objective-C(下面简称OC)项目为Swift项目,切换过程中不可避免地涉及到混编这一块,特此记录下来, 主要分为在swift项目中调用OC文件 和在OC项目中调用swift文件

在Swift工程或者文件使用Objective - C文件

  • 在OC项目中添加swift文件或者在swift项目中添加OC文件(创建的文件必须是继承与NSobject或者间接继承与NSobject)

  • 这时会提示你是否添加桥接文件,点击创建后体统会自动创建一个桥接文件,但是如果点击取消后,就需要自己建桥接文件;

  • 不过名字必须是“ProjectName-Bridging-Header.h”头文件(名称组成:工程名-Bridging-Header.h),如果名字记不清也可以自己新建Header file后,在Targets→Build Settings→Swift Compiler - General→Objective-C Bridging Header配置文件路径,这个文件主要是Swift使用OC类时使用

  • 在桥接文件即projectName-Bridging-Header.h文件中引入需要的OC头文件,具体使用,按照对应的Swift语法结构来即可

在Objective - C工程或者文件使用Swift的文件

  • 在OC中调用swift需要先import桥接文件(项目名-Swift.h,自动生成)
  • 这个文件是混编时,系统生成的Swift文件对应的Objective-C的头文件,具体可以在Targets→Build Settings→Swift Compiler - General→Objective-C Generated Interface Header Name进行配置,默认文件名是工程名-Swift.h,一般不做改动。
  • 这个文件虽然在工程中看不到,但是她真实存在,编译后,你可以按住Command+单击该文件名,就会看到具体生成的代码
  • 引入后,具体类的使用,直接按照OC的方式使用即可。

注意事项

  • 对于需要混编的Swift类添加@objc声明或继承NSObject或NSObject的子类如果要在Objective-C类中使用TestClass类,应当使用@objc加以声明,或者将TestClass继承自NSObject或NSObject的子类,否则,引入ProductName-Swift.h之后,程序找不到对应类。
class TestClass {

// 属性

// 实现

}
  • 在swift类中调用OC文件中的单例时,OC单例方法命名强制为share开头,否则在swift文件中找不到该方法

  • 使用第三方Framework 设置: target-->build setting -->Packaging -->Defines Module为 “Yes”;然后,配置文件Target -> Build Phases -> Link Binary,添加要导入的Framework;最后,还是要配置桥接文件,比如要使用 abc-lib.framework库中的 abc.h 就要这样配置:#import"abc-lib/abc.h";

  • Subclass子类问题:对于自定义的类而言,Objective-C的类,不能继承自Swift的类,即要混编的OC类不能是Swift类的子类。反过来,需要混编的Swift类可以继承自OC的类。 注解

  • OC宏文件: 如Swift文件要使用OC中定义的宏,只能使用常量简单宏文件

  • Swift独有特性: Swift中有许多OC没有的特性,比如,Swift有元组、为一等公民的函数、还有特有的枚举类型。所以,要使用的混编文件要注意Swift独有属性问题。

案例之swift中使用OC的block

Swift中使用Closure不能使用Block作为属性进行传值,必须是初始化方法或函数。 Objective-C文件中:

#import <UIKit/UIKit.h>
typedef void (^Myblock)(NSString *arg); 

@interface FirViewController : UIViewController 
//@property (copy, nonatomic) Myblock myBlock; 
//这种作为公共参数的形式,如果在Swift类中去回调的话,是有问题的。提示没有初始化方法,所以使用下面的以Block为参数的方法 

- (void)transValue:(Myblock) block;

@end

下面是.m文件

#import "FirViewController.h" 
@implementation FirViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.view.backgroundColor = [UIColor whiteColor]; 
} 

- (void)transValue:(Myblock)block
{ 
    if (block) 
    { 
        block(@"firBack"); 
    } 
} 
@end

在Swift文件回调:

在Swift使用OC的类时,首先在桥接文件中声明oc的头文件 工程名-Bridging-Header.h这是创建Swift工程的情况下

import UIKit 
class ViewController: UIViewController 
{ 
   override func viewDidLoad() 
    { 
        super.viewDidLoad() 
        self.view.backgroundColor = UIColor.whiteColor() 
    } 
    @IBOutlet weak var goFirst: UIButton! 
    @IBAction func goFirstAction(sender: AnyObject) 
    { 
        let firVC:FirViewController = FirViewController() 
        firVC. transValue { ( arg:String !) -> Void in 
            self.aBtn?.setTitle(arg, forState: UIControlState.Normal)
        } 
        self.navigationController?.pushViewController(firVC, animated: true) 
}