Swift与OC混编

编程之家收集整理的这篇文章主要介绍了Swift与OC混编编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Swift与OC的混编可以总结出以下几种场景

  1. OC&Swift Mixed In The Same Target
  1. OC&Swift Mixed In The Different Target

这里把Pod替换为Framework也是一样的,有时也把Project Target说成APP Target。1是同一target内混编,2是target间混编。

主工程里OC&Swift相互调用
在OC工程里创建一个Swift类会跳出如下弹框

在这里插入图片描述

点击Create BrIDging header按钮生成桥接文件MainProject-BrIDging-header.h和MainProject-Swift,MainProject是工程名称。同时会在Build Settings里添加Swift ComplIEr配置:

在这里插入图片描述

如果没有点击Create BrIDging header按钮,而是点击了Don’t create,那么将不会创建桥接文件,但是Build Settings里添加Swift ComplIEr配置项,只是该配置项里没有BrIDging header,这时需要开发者自行创建桥接文件,并配置好路径

在这里插入图片描述

OC调用Swift接口
Swift类里的接口应该加上@objc修饰

class Dog: NSObject {
    
    @objc let legNumber = 4
    var temper = "temper-good"
    @objc var frIEnd = Cat()

    @objc func eat() {
        print("The dog is eating")
    }
}

在OC类中首先要引用MainProject-Swift.h

#import "MainProject-Swift.h"

最后就可以在OC类里引用Swift类

#import "MainProject-Swift.h"

@implementation VIEwController
- (voID)vIEwDIDLoad {
    [super vIEwDIDLoad];
    Dog *dog = [[Dog alloc] init];
    [dog eat];
}
@end

结论
我们再看看MainProject-Swift.h到底是什么。MainProject-Swift.h是一个自动生成的头文件,工程里没有对应的实体文件,可以Command+leftClick点击MainProject-Swift.h进去看到其中有一段

@class Cat;

SWIFT_CLASS("_TtC11MainProject3Dog")
@interface Dog : NSObject
@property (nonatomic, Readonly) NSInteger legNumber;      // @objc let legNumber = 4
@property (nonatomic, strong, getter=frIEnd, setter=setFrIEnd:) Cat * _Nonnull frIEnd_;  //@objc var frIEnd = Cat()
- (voID)eat;                  //@objc func eat()
- (nonnull instancetype)init OBJC_DESIGNATED_INITIAliZER;
@end

在Cat这个Swift类中加了@objc修饰的属性方法都在MainProject-Swift.h中自动生成了对应的OC属性方法,所以通过引用MainProject-Swift.h就可以去调用这些接口了。

Swift调用OC接口
Swift调用OC类略有不同

在MainProject-BrIDging-header.h桥接文件里引入需要被Swift调用的类

#import "Cat.h"

Swift可以直接使用MainProject-BrIDging-header.h里引入的类

class Dog: NSObject {
    @objc var frIEnd = Cat()
    func frIEndEatAction() {
        frIEnd.eat();
    }
}

这个桥接过程比较简单。

如果主工是Swift编写的
这种情况下OC&Swift的相互调用与上述并无二致。在创建OC类的时候需要同时生成一个桥接文件一个Swift转OC的接口文件,其他过程就不再赘述了。

OC主工程里调用Swift Pod
首先要确保OC主工程处于混编模式,否则再引入swfit pod,执行pod install时会报错这个问题问题2中有说明),此时最好是新建一个swift文件自动创建桥接文件

创建Swift类和接口。由于Swift接口是OC类调用的,所以Swift接口要有@objc修饰符; 另外接口调用是跨Target的,所以要有public或open关键字。如下代码,class前面和接口前面有@objc public修饰的就可以在主工程里使用

@objc public class Dog: NSObject {
    @objc let legNumber = 4
    var temper = "temper-good"
    @objc public func eat() {
        print("The dog is eating")
    }
}

OC调用Swift接口,Swift Pod工程的build setting里也有一个Interface header文件,首先要在主工程里引入这个文件,让后就可以在OC里面使用Swift相关接口了。(除此之外还有@import导入方式,这是module机制)

在这里插入图片描述

#import "VIEwController.h"
#import <SwiftPodFirst/SwiftPodFirst-Swift.h>
@implementation VIEwController
- (voID)vIEwDIDLoad {
    [super vIEwDIDLoad];
    Dog *dog = [[Dog alloc] init];
    [dog eat];
}

如果调用没有public的接口就会产生如下报错,OC可以访问的接口可以进入接口头文件SwiftPodFirst-Swift.h查看。

No visible @interface for 'Dog' declares the selector 'temper'

Swift主工程里调用OC Pod
首先要确保Swift主工程处于混编模式,具体方法不再赘述。
在Swift主工程桥接文件SwiftMainProject-BrIDging-header.h中添加#import引用

#import <OCPodSecond/Cat.h>    // 这里OCPodSecond是OC pod,Cat是OC类

Swift主工程中使用OC类

import UIKit

class VIEwController: UIVIEwController {
    let cat = Cat()   // Cat是OC类
    overrIDe func vIEwDIDLoad() {
        super.vIEwDIDLoad()
        cat.eat()       // 是OC对象的方法
    }
}

一个由OC语言创建的Pod里有Swift代码,再由一个OC主工程使用这个Pod(这是项目里最常用到的场景,也是最复杂的一个场景)
在之前的OCPodSecond里添加一个Swift类,使OC Pod变成混编模式。
在第1步之后会自动创建OCPodSecond-Swift.h接口头文件,但并不会有创建OC-BrIDging-header.h的提示,那只好自己创建一个桥接文件并在build setting里关联路径
遵循之前的原则为Swift类添加@objc public接口

// 这个类是OCPodSecond里的Swift类
@objc public class Pig: NSObject {
    @objc public func eat() {
        print("The pig is eating!!")
    }
}

最后在主工程里调用

#import "VIEwController.h"
#import <SwiftPodFirst/SwiftPodFirst-Swift.h>
#import <OCPodSecond/Cat.h>
#import <OCPodSecond/OCPodSecond-Swift.h>

@implementation VIEwController

- (voID)vIEwDIDLoad {
    [super vIEwDIDLoad];
    Dog *dog = [[Dog alloc] init];  // <SwiftPodFirst/SwiftPodFirst-Swift.h>
    [dog eat];
    
    Cat *cat = [[Cat alloc] init];  // <OCPodSecond/Cat.h>
    [cat eat];
    
    Pig *pig = [[Pig alloc] init];  // <OCPodSecond/OCPodSecond-Swift.h>  在OC Pod里添加的Swift类 Pig
    [pig eat];
}

运行一下试试,结果出现报错提示,framework targets不支持brIDging header(引文7),

<unkNown>:0: error: using brIDging headers with framework targets is unsupported
Command CompileSwiftSources Failed with a nonzero exit code

在Support files里有个OCPodSecond-umbrella.h头文件这个文件替代了brIDging header的作用,文件中会自动导入OC类。因此在Pod里混编更加简单了,桥接文件和相关接口会自动生成

另外,每当新增一个接口时,都有可能出现接口不可用的情况,这或许是因为语言间的转换没有这么快,也可能是存在一些接口缓存文件没有及时更新。遇到这种情况,最好是重新build一下或者把pod重新装一遍再或者clean重启一下工程。

OC Pod引用Swift Pod
这种情形与主工程调用Swift Pod没有区别,只需引入相关的接口文件就可以xxx-Swift.h,此处不再多述。需要注意的是,在podspec文件里要添加dependency,否则会无法引用相关pod。

Swift Pod 引用 OC Pod
这种情况有点特殊,虽然umbrella header有BrIDging header的作用,但是umbrella header里的#import指令是自动生成的,并且只有Pod内部混编时才会自动引用Pod内的OC header。所以这样只能支持Pod内部混编。

假设一个Swift Pod需要引用一个OC Pod,此时在Swift Pod的umbrella header添加#import “<xxPod/xx.h>”,虽然最后可以成功使用<xxPod/xx.h>接口并且通过编译。但只要重新执行pod install命令umbrella header就会被更新,里面自定义import指令会被全部删除。这意味着其他项目无法成功引用该Swift Pod。

这时我们需要modular的编译方式,在podfile里把use_frameworks!改为use_modular_headers!,这样就可以使用import 方式引用pod,import 方式同时兼容OC和Swift。

总结
最后混编路径汇总成下图,如果完全使用modular方式,可以把该图做一些简化。

在这里插入图片描述

问题1


[!] Unable to determine Swift version for the following pods:

- `SwiftPodFirst` does not specify a Swift version and none of the targets (`MainProject`) integrating
it have the `SWIFT_VERSION` attribute set. Please contact the author or set the `SWIFT_VERSION` attribute 
in at least one of the targets that integrate this pod.

需要指定pod的swift版本,以便提供合适的编译器。修改方式是在集成的Target里指定SWIFT_VERSION。例如我们这里产生的原因是OC主工程不是混编模式,所以没有swift相关的编译项,这里修改的方式是在OC主工程里新建一个Swift类,让主工程变为混编模式,会自动在build setting生成相关的swift编译项。

问题2

Module 'SwiftPodFirst' not found

找不到某个Module,这是我们再开发中最常遇到的问题了,导致这个报错的原因很多。

更多详情查看引用链接
链接https://www.jianshu.com/p/7e8312f3d8f1

解锁查看全部内容

付费后查看完整内容
限时 微信扫码支付 ¥9.9 19.9

总结

以上是编程之家为你收集整理的Swift与OC混编全部内容,希望文章能够帮你解决Swift与OC混编所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

Swift相关文章

最正确的方法就是去编译后的包里查看。步骤:1、先运行一下项目。2、找到编译后的目录。有两种方法:直接访问/通过XCode进入(1)直接访问编译后的文件路径:/Users/用户名/Library/Developer/Xcode/DerivedData/工程名-sdsdfsfdsfdsdfsf/Build/Products,文件下面有XXX-iphoneos,XXXX-iphonesimulator样式的文件夹。选择符合我们运行设备和版本的文件夹,点击进入。(2)可以通过Xco.
前言在iOS原生开发的时候,凡是涉及到运行项目之后Xcode提示Build target Runner-Log,是不是每次看到这种报错提示就觉得眼前一黑,头皮发麻?其实也没我说的那么夸张,但是有时候遇到这种问题确实比较费头发。本篇文章就来分享一个常见的问题,但是该问题解决起来不复杂,分享出来,方便后期查阅使用。重现报错提示具体在Xcode中的报错提示如下所示:Showing Recent Messagesdiff: /Users/admin/Documents/WorkSpac
本文将会给出2022年软件行业的编程语言、薪水、就业以及技术的深度分析数据全文较长,建议收藏之后,慢慢看文章目录一、最受欢迎的语言 二、最值得学习的语言 三、薪水/工资分析 四、就业状况 五、协作工具数据 六、网络框架分析 七、数据库排名软件开发行业正在全球范围内快速发展。因此,重要的是要掌握最流行的编程语言,以便在这个竞争激烈的行业中建立前途似锦的职业生涯。您可能不必掌握我们今天讨论的所有语言,但您的简历中掌握的语言越多,在 2022 年和未来几年内,就越有客户和开.
~/Library/Developer/Xcode/iOS Device Logs清空 Products~/Library/Developer/Xcode/ProductsXcode 12 及之后版本 还有3个占用内存的文件分别是:第一名:iOS.simruntime 10.29 GB (iOS 日常开发需要使用,勿删)第二名:watchOS.simruntime 7.05 GB (不做 watch 开发可以删除)第三名:tvOS.simruntime 5.39 G
Swift与OC的混编可以总结出以下几种场景OC&amp;Swift Mixed In The Same TargetProject中OC 调用 SwiftPod中OC 调用 SwiftProject中Swift 调用 OCPod中Swift 调用 OCOC&amp;Swift Mixed In The Different TargetOC Project 调用 Swift PodSwift Project 调用 OC PodOC Pod 调用 Swift PodSwift
最近数据结构实践课经常需要进行二进制文件读写,总结出以下经验:1. 读写二进制文件最好加上ios::binary2. 二进制文件用fstream读写时既可以输入又可以输出,此模式下可以实现只修改文件部分内容例如,我创建了含有100个数的二进制文件data_unsorted.dat,生成结果如下:写入如下代码(ios::in不能少) file.open("data_unsorted.dat", ios::binary | ios::in | ios::out); in.
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注