美文网首页
Swift与OC混编问题记录

Swift与OC混编问题记录

作者: Trigger_o | 来源:发表于2021-03-05 18:16 被阅读0次
  • 1.文件引用
    (1)OC项目创建swift文件时,xcode询问是否创建XXX-Bridging-Header文件,确定创建.
    (2)在targets - build setting - packaging中设置Defines Module为YES,同一栏里面的product name需要是项目名称.
    setting
    (3)在Bridging-Header文件中import OC头文件,swift文件里就可以访问该OC文件了.
    Bridging-Header
    tset.swift
    (4)完成12步之后OC文件内#import <GOLAXY-Swift.h>,OC文件就可以访问该swift文件了,#import <GOLAXY-Swift.h>可以写在pch文件中
  • 2.文件和方法名
    有这样一个OC类
@interface MyObject : NSObject

+ (instancetype _Nonnull )object;

@end

@implementation MyObject

+ (instancetype)object
{
    MyObject *logic = [[self alloc] init];
    return logic;
}

在swift类中调用+objec方法时会报错


image.png

如果一个OC的类方法的方法名是类的最后一个单词,那么在swift中就无法使用.这个问题在纯swift中不会发生

  • 3.获取class
    OC代码从storyboard中初始化VC
NSString *className = NSStringFromClass(newClass);
[[UIStoryboard storyboardWithName:storyboardName bundle:nil]instantiateViewControllerWithIdentifier:className]

这个方法,当OC调用时,传入类名.class,于是className就是"类名"
在swift中,由于存在命名空间,当调用时,不管传入self(类方法中),或者类名.self,或者类名.classForCoder() 得到的className都是"包名.类名" ,需要切割字符串来适应原有的代码逻辑

  • 4.在swift中使用+load和+initialize方法
    原文
    (1)定义一个协议
@protocol NSSwiftyLoadProtocol <NSObject>
@optional
+ (void)swiftyLoad;
+ (void)swiftyInitialize;
@end

(2)写一个宏用来为类生成分类,并且实现NSSwiftyLoadProtocol协议的方法

#define SWIFTY_LOAD_INITIALIZE(className) \
@interface className(swizzle_swifty_hook)\
@end\
\
@implementation className(swizzle_swifty_hook)\
+ (void)load {if ([[self class] respondsToSelector:@selector(swiftyLoad)]) {[[self class] swiftyLoad];}}\
+ (void)initialize {if ([[self class] respondsToSelector:@selector(swiftyInitialize)]) {[[self class] swiftyInitialize];}}\
@end

(3)把需要调用+load和+ (void)initialize方法的类,用宏来生成分类

#import <Foundation/Foundation.h>
#import <GOLAXY-Swift.h>

//添加需要重写+load或者+initialize的swift类
SWIFTY_LOAD_INITIALIZE(GLCourseListVC)
//...更多的类

(4)在swift类中调用

extension GLCourseListVC : NSSwiftyLoadProtocol{
    public static func swiftyLoad() {
       ///code
    }
}
  • 5.swift和OC的互相访问
    (1)只要宏定义中涉及OC的方法,swift文件里肯定是编译不了的,只能在swift中再定义一次,swift中的宏其实就是全局变量;
    纯字符串的宏在swift文件也可以使用,不过这种我一般定义为静态字符串,不用define
/* theme */
//.h
extern NSString *const __nonnull GLTextBlack;
extern NSString *const __nonnull GLTextWhite;
//.m
NSString * const GLTextBlack = @"222222";
NSString * const GLTextWhite = @"dddddd";

这种定义在OC和swift中都可以使用;

(2)OC文件中的东西在swift中基本都可以用,只是需要按照swift的语法来写,但是swift中的全局变量在OC中是用不了的,只有@objc修饰的才可以在在OC文件中使用

@objc class TestClass:NSObject{
}

@objc修饰的类需要继承NSObject,并且@objc可以省略

@objc protocol TestProtocol{
    @objc optional func testFunc()
}

@objc修饰的协议只能由OC类来遵循,swift类,结构体,枚举都不能遵循这种协议
并且方法也需要用@objc修饰,两边都得要,协议没加@objc的时候方法也不能加

@objc enum TestEnum:Int{
    case TestEnumaa = 0
    case TestEnumbb = 1
}

@objc 修饰的枚举,rawValue必须是Int类型

@objc class TestClass:NSObject{
   @objc func test(){
        
    }
}
extension TestClass{
   @objc func extest(){
        
    }
}

对于方法,不管是类的还是扩展的都必须用@objc修饰

@objc var pur : (() -> ())?

swift的属性也需要加@objc才能在OC文件中访问,并且添加@objc后不影响swift文件的访问

class ExampleClass: NSObject {
    @objc var enabled: Bool {
        @objc(isEnabled) get {
            
        }
    }
}

这段代码是给OC提供一个enabled属性的getter叫isEnabled

6.swift使用#if DEBUG
首先OC中能够使用#if DEBUG需要设置

image.png
需要有debug=1,一般默认就有
另外下面的release栏不要加,不然失去了意义

然后在swift中也能使用#if DEBUG需要设置,同样只设置debug


image.png
image.png

相关文章

网友评论

      本文标题:Swift与OC混编问题记录

      本文链接:https://www.haomeiwen.com/subject/rhukqltx.html