广州凡科互联网科技有限公司

营业时间
MON-SAT 9:00-18:00

全国服务热线
18720358503

公司门店地址
广州市海珠区工业大道北67号凤凰创意园

OC新项目转Swift手册,

日期:2021-02-18 浏览:

OC新项目转Swift手册,

运作自然环境:Xcode 11.1 Swift5.0

近期参加的一个新项目必须从Objective-C(下列通称OC)转到Swift,期内碰到了一些坑,因此拥有这篇小结性的文本文档。
假如你也是有将OC新项目Swift化的要求,能够做为参照。

OC转Swift有一个大前提条件便是你需要对Swift有一定的掌握,了解Swift英语的语法,最好详细看了一遍官方网的Language Guide。

变换的全过程分全自动化和手动式转译,由于全自动化工厂具的鉴别率不可以令人令人满意,大部分分状况全是必须手动式变换的。

全自动化工厂具

有一个较为好的全自动化工厂具Swiftify,能够将OC文档乃至OC工程项目全部转成Swift,称为准确率能做到90%。我使用了一些完全免费版中的作用,但觉得实际效果其实不理想化,由于沒有应用过付钱版,因此都不五星好评价它便是不太好。

Swiftify也有一个Xcode的软件Swiftify for Xcode,能够完成对选定编码和单文档的转换。这一软件还挺好,对纯系统软件编码转换算是精准,但一部分编码还存有一些鉴别难题,必须手动式再改动。

手动式Swift化

假如你是在新项目中初次应用Swift编码,在加上Swift文档时,Xcode会提醒你加上一个.h的桥接文档。假如很大心点了不加上还能够手动式导进,便是自身手动式转化成一个.h文档,随后在Build Settings Swift Compiler - General Objective-C Bridging Header中填写该.h文档的相对路径。

这一桥接文档的功效便是供Swift编码引入OC编码,或是OC的三方库。

#import Utility.h 
#import Masonry/Masonry.h 

在Bridging Header的下边也有一个配备项是Objective-C Generated Interface Header Name,相匹配的值是ProjectName-Swift.h。它是由Xcode全自动转化成的一个掩藏头文档,每一次Build的全过程会将Swift编码中申明为外接启用的一部分转成OC编码,OC一部分的文档会相近pch一样全局性引入这一头文档。由于是Build全过程中转化成的,因此仅有.m文档中能够立即引入,针对在.h文档中的引入下面有详细介绍。

Appdelegate(程序通道)

Swift中沒有main.m文档,.m。因此大家能够把main.m文档开展清除。

系统软件API

针对UIKit架构中的大部分分编码变换能够立即查询系统软件API文本文档开展变换,这儿也不过量详细介绍。

property(特性)

Swift沒有property,都没有copy,nonatomic等特性装饰词,仅有表明特性是不是可变性的let和var。

留意点一 OC中一个类分.h和.m2个文档,各自表明用以曝露给外接的方式,自变量和仅作內部应用的方式自变量。转移到Swift时,应当将.m中的property标为private,即外接没法立即浏览,针对.h中的property不做解决,取默认设置的internal,即同控制模块可浏览。

针对涵数的转移也是同样的。

留意点二 有一种独特状况是在OC新项目中,一些特性以内部(.m)可变性,外界(.h)写保护。这类状况能够那么解决:

private(set) var value: String

便是只对value的set方式就可以了private标识。

留意点三 Swift中对于空种类有一个专业的标记?,相匹配OC中的nil。OC中沒有这一标记,可是能够根据在nullable和nonnull表明该种特性,方式主要参数或是回到值是不是能够空。

假如OC中沒有申明一个特性是不是能够为空,那么就去默认设置值nonnull。

假如大家想让一个类的全部特性,涵数回到值全是nonnull,除开手动式一个个加上以外也有一个宏指令。

NS_ASSUME_NONNULL_BEGIN
/* code */
NS_ASSUME_NONNULL_END

它是我的iOS开发设计沟通交流群:无论你是新手還是大神热烈欢迎进驻,能够一起共享工作经验,探讨技术性,相互学习培训发展!
另另附一份各朋友搜集的大厂招聘面试题,必须iOS开发设计学习培训材料、招聘面试真题,进群就可以获得!

点一下这里,马上与iOS大神沟通交流学习培训
enum(枚举类型)

OC编码:

typedef NS_ENUM(NSInteger, PlayerState) {
 PlayerStateNone = 0,
 PlayerStatePlaying,
 PlayerStatePause,
 PlayerStateBuffer,
 PlayerStateFailed,
typedef NS_OPTIONS(NSUInteger, XXViewAnimationOptions) {
 XXViewAnimationOptionNone = 1 0,
 XXViewAnimationOptionSelcted1 = 1 1,
 XXViewAnimationOptionSelcted2 = 1 2,

Swift编码:

enum PlayerState: Int {
 case none = 0
 case playing
 case pause
 case buffer
 case failed
struct ViewAnimationOptions: OptionSet {
 let rawValue: UInt
 static let None = ViewAnimationOptions(rawValue: 1 0)
 static let Selected1 = ViewAnimationOptions(rawValue: 1 0)
 static let Selected2 = ViewAnimationOptions(rawValue: 1 2)
 //...

Swift沒有NS_OPTIONS的定义,取代它的的是以便考虑OptionSet协议书的struct种类。

OC编码:

- (MTObject *)object {
 if (!_object) {
 _object = [MTObject new];
 return _object;

Swift编码:

lazy var object: MTObject = {
 let object = MTObject()
 return imagobjecteView

OC编码:

typedef void (^DownloadStateBlock)(BOOL isComplete);

Swift编码:

typealias DownloadStateBlock = ((_ isComplete: Bool) - Void)

OC编码:

+ (XXManager *)shareInstance {
 static dispatch_once_t onceToken;
 dispatch_once( onceToken, ^{
 instance = [[self alloc] init];
 return instance;

Swift对单例的完成较为简易,有二种方法:

第一种

let shared = XXManager()// 申明在全局性取名区(global namespace)
Class XXManager { 

你可以能会疑虑,为何沒有dispatch_once,怎样确保多段程下建立的唯一性?实际上是那样的,Swift中全局性自变量是懒载入,在AppDelegate中被原始化,以后全部的启用都是应用该案例。并且全局性自变量的原始化是默认设置应用dispatch_once的,这确保了全局性自变量的结构器(initializer)总是被启用一次,确保了shard的分子性。

第二种

Class XXManager {
 static let shared = XXManager()
 private override init() {
 // do something 

Swift 2 刚开始提升了static重要字,用以限制自变量的功效域。假如不应用static,那麼每个shared都是相匹配一个案例。而应用static以后,shared变成全局性自变量,就变成紧跟面第一种方法基本原理一致。能够留意到,因为结构器应用了 private 重要字,因此也确保了单例的分子性。

原始化方式和析构涵数

针对原始化方式OC先启用父类的原始化方式,随后原始自身的组员自变量。Swift先原始化自身的组员自变量,随后在启用父类的原始化方式。

OC编码:

// 原始化方式
@interface MainView : UIView
@property (nonatomic, strong) NSString *title;
- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title NS_DESIGNATED_INITIALIZER;
@implementation MainView
- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title {
 if (self = [super initWithFrame:frame]) {
 self.title = title;
 return self;
// 析构涵数
- (void)dealloc {
 //dealloc

上边类在启用时

Swift编码:

class MainViewSwift: UIView {
 let title: String
 init(frame: CGRect, title: String) {
 self.title = title
 super.init(frame: frame)
 required init?(coder: NSCoder) {
 fatalError( init(coder:) has not been implemented )
 deinit {
 //deinit

OC编码:

// 案例涵数(现有方式)
- (void)configModelWith:(XXModel *)model {}
// 案例涵数(独享方式)
- (void)calculateProgress {}
// 类涵数
+ (void)configModelWith:(XXModel *)model {}
// 案例涵数(现有方式)
func configModel(with model: XXModel) {}
// 案例涵数(独享方式)
private func calculateProgress() {}
// 类涵数(不能以褥子类重新写过)
static func configModel(with model: XXModel) {}
// 类涵数(能够褥子类重新写过)
class func configModel(with model: XXModel) {}
// 类涵数(不能以褥子类重新写过)
class final func configModel(with model: XXModel) {}

OC能够根据是不是将方式申明在.h文档说明该方式是不是为独享方式。Swift中沒有了.h文档,针对方式的管理权限操纵是根据管理权限重要词开展的,各重要词管理权限尺寸为: private fileprivate internal public open

在其中internal为默认设置管理权限,能够在同一module下浏览。

NSNotification(通告)

OC编码:

// add observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(method) name:@ NotificationName object:nil];
// post
[NSNotificationCenter.defaultCenter postNotificationName:@ NotificationName object:nil];

Swift编码:

// add observer
NotificationCenter.default.addObserver(self, selector: #selector(method), name: NSNotification.Name(rawValue: NotificationName ), object: nil)
// post
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationName ), object: self)

能够留意到,Swift中通快递知管理中心NotificationCenter没有NS作为前缀,通告名由标识符串变为了NSNotification.Name的构造体。

改为构造体的目地便是以便有利于管理方法标识符串,本来的标识符串种类变为了特定的NSNotification.Name种类。上边的Swift编码能够改动为:

extension NSNotification.Name {
 static let NotificationName = NSNotification.Name( NotificationName )
// add observer
NotificationCenter.default.addObserver(self, selector: #selector(method), name: .NotificationName, object: nil)
// post
NotificationCenter.default.post(name: .NotificationName, object: self)
protocol(协议书/代理商)

OC编码:

@protocol XXManagerDelegate NSObject 
- (void)downloadFileFailed:(NSError *)error;
@optional
- (void)downloadFileComplete;
@interface XXManager: NSObject
@property (nonatomic, weak) id XXManagerDelegate delegate; 

Swift中对protocol的应用扩宽了很多,不仅是class目标,struct和enum也都可以以完成协议书。必须留意的是struct和enum为引导用种类,不可以应用weak装饰。仅有特定当今代理商只适用类目标,才可以应用weak。将上边的编码转成相匹配的Swift编码,便是:

@objc protocol XXManagerDelegate {
 func downloadFailFailed(error: Error)
 @objc optional func downloadFileComplete() // 可选择协议书的完成
class XXManager: NSObject {
 weak var delegate: XXManagerDelegate? 

@objc是说明当今编码是对于NSObject目标,也便是class目标,便可以一切正常应用weak了。

假如并不是对于NSObject目标的delegate,只是是一般的class目标能够那样设定代理商:

protocol XXManagerDelegate: class {
 func downloadFailFailed(error: Error)
class XXManager {
 weak var delegate: XXManagerDelegate?

非常值得留意的是,。

Swift和OC混编留意事宜 涵数名的转变

假如你一直在一个Swift类里界定了一个delegate方式:

@objc protocol MarkButtonDelegate {
 func clickBtn(title: String)

假如你需要在OC中完成这一协议书,这时候候方式名就变为了:

- (void)clickBtnWithTitle:(NSString *)title {
 // code

这关键是由于Swift有特定主要参数标识,OC却沒有,因此在由Swift方式名转化成OC方式名时编译程序器会全自动加一些装饰词,已使涵数做为一个语句能够 通畅 。

在OC的头文档里启用Swift类

假如要在OC的头文档里引入Swift类,由于Swift沒有头文档,而以便让在头文档可以鉴别该Swift类,。

@class SwiftClass;
@interface XXOCClass: NSObject
@property (nonatomic, strong) SwiftClass *object;
对OC类在Swift启用下重新命名

由于Swift对不一样的module都是有取名室内空间,因此Swift类也不必须加上作为前缀。假如有一个带作为前缀的OC公共性部件,在Swift自然环境下降用时不可不特定作为前缀是一件很不雅致的事儿,因此iPhone加上了一个宏指令NS_SWIFT_NAME,容许在OC类在Swift自然环境下的重新命名:

NS_SWIFT_NAME(LoginManager)
@interface XXLoginManager: NSObject

那样大家就将XXLoginManager在Swift自然环境下的类名改成了LoginManager。

引入种类和值种类 struct 和 enum 是值种类,类 class 是引入种类。 String,Array和 Dictionary全是构造体,因而取值立即是复制,而NSString, NSArray和NSDictionary则是类,因此是应用引入的方法。 struct 比 class 更“轻量”,struct 分派在栈中,class 分派在堆中。 id种类和AnyObject

OC中id种类被Swift启用时候全自动转成AnyObject,她们很类似,但却实际上定义其实不一致。Swift中也有一个定义是Any,她们三者的差别是:

id 是一种通用性的目标种类,它能够偏向归属于一切类的目标,在OC中就是能够意味着全部承继于NSObject的目标。 AnyObject能够意味着一切class种类的案例。 Any能够意味着一切种类,乃至包含func种类。

从范畴尺寸较为便是:id AnyObject Any。

别的英语的语法差别及留意事宜(待填补)

1、Swift句子中不用大大加分号;。

2、有关Bool种类更为严苛,Swift已不是OC中的非0便是真,真伪只相匹配true和false。

3、Swift类内一般不用写self,可是闭包内是必须写的。

4、Swift是强种类語言,务必要特定确立的种类。在Swift中Int和Float不是能立即做计算的,务必要将她们转成同一种类才能够计算。

5、Swift抛下了传统式的++,--计算,抛下了传统式的C語言式的for循环系统书写,而改成for-in。

6、Swift的switch实际操作,不用在每一个case句子完毕的情况下都加上break。

7、Swift对enum的应用干了非常大的拓展,能够适用随意种类,而OC枚举类型仅适用Int种类,假如要写适配编码,应选择Int型枚举类型。

8、Swift编码要想被OC启用,。

9、Swift特有的特点,如泛型,struct,非Int型的enum等被包括才涵数主要参数中,。

10、Swift适用轻载,OC不兼容。

11、带默认设置值的Swift涵数再被OC启用时候全自动进行。

针对OC转Swift以后的英语的语法转变也有许多关键点非常值得留意,非常是针对第一次应用Swift这门語言的同学们,非常容易忽略或是待在家里OC的观念去敲代码。这儿强烈推荐一个英语的语法查验的架构SwiftLint,能够全自动化的查验大家的编码是不是合乎Swift标准。

能够根据cocoapods开展引进,配备好以后,每一次Build的全过程,Lint脚本制作都是实行一遍Swift编码的英语的语法查验实际操作,Lint还会继续将编码标准开展等级分类,比较严重的编码不正确会立即出错,造成程序没法起动,不太比较严重的会显示信息编码警示(⚠️)。

假如你觉得SwiftLint有点儿过度严苛了,还能够根据改动.swiftlint.yml文档,自定归属于自身的英语的语法标准。

dengb.TechArticleOC新项目转Swift手册, 运作自然环境:Xcode 11.1 Swift5.0 近期参加的一个新项目必须从Objective-C(下列通称OC)转到Swift,期内碰到了一些坑,因此拥有这...



网站知识

联系方式丨CONTACT

  • 全国热线:18720358503
  • 传真热线:18720358503
  • Q Q咨询:2639601583
  • 企业邮箱:2639601583@qq.com

首页
电话
短信
联系