美文网首页
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