Swift 3.0 项目升级实战

  • dispatch_once方法废弃,可以使用如下两种方式实现:

public extension DispatchQueue {
private static var _onceTracker = String
/**
Executes a block of code, associated with a unique token, only once. The code is thread safe and will
only execute the code once even in the presence of multithreaded calls.
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
- parameter block: Block to execute once
*/
public class func once(token: String, block:()->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
}

第二种方式是苹果推荐的方式(xCode自动将swift升级时,几乎所有的dispath_once方法都会自动转换成下面这种形式),代码如下:

var t: SomeObject?
private static var __once: () = {
//此处做一次性操作
t = SomeObject()
}()

如果仅仅是需要单例模式的话可以通过如下代码实现(static let 标记的常量,为线程安全的,并且是懒加载,只赋值一次):

class SingleInstanceTest {
static let sharesdInstance = SingleInstanceTest()
private override init() {
// 注册通知等关初始化操作
}
}

  • CGSize、CGPoint、CGRect 的make方法取消,需要使用CGSize(width: 1, height: 1)等方式创建
  • 很多原来的方法如systemFontOfSize都将最后的单词变为方法的外部参数名:UIFont.systemFont(ofSize: kGlobalFontSize_H)
  • UIColor等类型的类方法都变为静态属性:

UIColor.redColor() -> UIColor.redColor
UIColor.clearColor() -> UIColor.clearColor

  • 绘制直线等CoreGraphics操作由之前的CGPathMoveToPoint、CGPathAddLineToPoint变为path.move、path.addLine等,参数不变(大多数CoreGraphics的方法调用都显得更swift化,可以查看相关文档)。
  • 如果方法带有返回值,例如

func sum(a: Int , b: Int) -> Int {
return a + b
}

如果不需要返回值可以通过 _ = sum(a: 5 , b: 6)来避免警告。

  • String与NSString必须显示转换例如,如下代码会报错:

func say(a: NSString) {
print(a)
}
var d : String = "hello"
say(a: d)

此时需要将变量d显式转换为NSString

  • NSDateFormatter、NSNumberFormatter、NSBundle等被彻底废弃,需要使用DateFormatter和NumberFormatter、Bundle等代替,同时苹果推出Date、Data、Calendar等swift类型(去OC化正在紧张进行中,如果苹果推出新的swift类型可以替代OC,可能会将原OC类型禁用掉,那么为了以后swift升级降低代码的修改量,建议使用swift的类型)。
  • GCD更swift化,swift3.0中可以使用DispatchQueue获取主线程、global线程或者创建单独的线程,线程任务的提交可以通过DispatchQueue的asyn、syn等(注意:通过指定线程优先级获取的global线程方法已经将要废弃,可以通过使用global(qos:_)->DispatchQueue创建)。
  • swift 3.0中对数组的操作例如:插入、删除、判断是否包含的相关方法更简洁:insert(: , at:)、remove(at: )、contains(: )
  • swift 3.0中获取类的名称(类型)需要通过 type(of: _)方法获得,如下代码所示:

class Person {
class func className() -> String {
return String(describing: self)
}
func typeS () -> String {
return String(describing: type(of: self))
// type(of: _)相当于dynamicType
}
func typeO () -> Person.Type {
let c = type(of: self)
return c
}
}
var c = Person().typeS()
var d = Person.className()
var o = String(describing: Person().typeO())

  • swift3.0 中 UIControl的状态(Normal、Disable、Highlight等)被封装到一个结构体中,并且该结构体实现了OptionSet协议,该协议用于掩码运算(注意:xCode会自动将.normal状态变为UIControlState(),可以修改为.normal)。
  • swift3.0 的取余运算:在xcode转换swift版本时,会将取余运算符% 变为truncatingRemainder(dividingby:_),进入文档看了一下swift3.0的标准库中多了许多的算数方法。
  • swift3.0通知变更,通知中心由NSNotificationCenter 变为 NotificationCenter,并且post与addObject方法中的key参数由NSNotification.Name代替,变化如下所示:
// swift 2
NSNotificationCenter.defaultCenter().postNotificationName("kLogoutNotification", object: nil)
// swift 3
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "kLogoutNotification"), object: nil)
  • swift 3.0方法外参的变化,第一个参数也需要指定一个外参数(外参数为调用处显示的参数,内参数是在函数内使用的参数),如果不指定外参数,需要有通配符替代,代码如下所示:

// swift 2 的写法,方法第一个外参数,可以不需要显示给出
func Say(p: Int , two: Int , _ three: Int) {
print("(p)")
print("(two)")
print("(three)")
}
// swift 3 的写法,必须显示给出第一个参数的外参数,否则编译报错
func Say(_ p: Int , two: Int , _ three: Int) {
print("(p)")
print("(two)") // 第二个参数two可同时做内参数与外参数
print("(three)") // 通配符代替第三个参数,调用处可以不显示外参数
}
Say(p: 0, two: 1, 2) //

  • swift 3.0 枚举的变化,xCode升级swift时,会将所有的枚举类型的值得首字母变为小写(不强制,最好还是按照这个规则进行编码),代码如下:

enum SchoolRange: Int {
case default = 1
case province
case city
case nation
func title() -> String {
switch self {
case .province:
return "省级"
case .city :
return "市级"
case .nation:
return "国家级"
default:
return "县级"
}
}
}

  • swift3.0中的泛型可以获取OC中泛型的类型,如果在OC中使用了泛型,那么在swift与OC的混编中,swift可以推测泛型占位符的类型,如下代码所示。
// OC 泛型定义
// OC 代码
@interface Person<T>
{
    id _typeCode;
} 
- (T)typeCode;
@end
@interface Student 
- (Person<School>)typeCodeSchool;
@end
// swift 2.2
var s: Student = Student()
var c = s.typeCodeSchool() //c的类型为Person
// swift 3.0
var s: Student = Student()
var c = s.typeCodeSchool() //c的类型为   Person<School>
  • private 和 fileprivate:在swift3中private的作用域缩小了,仅能在当前的大括号内被访问,而fileprivate仅能在当前文件中被访问,如下代码所示
// swift 2中 同一文件可以访问private标记的变量
class Person {
    private var name: String!
}
class Student {
    func testPer(p: Person) {
        p.name = "Hello"   // swift 2中private标记的变量,可以被同一文件内的任何类、方法访问
    }
}
// swift 3中private标记的变量只能被{}中的方法等访问
class Person {
    private var name: String!
    fileprivate var age: Int!
}
class Student {
    func testPer(p: Person) {
        p.age = 32  // swift3中fileprivate标记的变量可以在本文件中的任何位置访问
        p.name = "Hello"   // 此处编译错误
    }
}
  • swift3.0中的Bool类型的变量名前都加上了is如isEnable、isHidden等
  • swift3.0中新增open关键字,被open标记的变量可以被不同的module的类继承、重写,public标记的变量或者类可以被当前module的类继承、重写,默认情况下internal不可以被继承或者重写。
  • swift3.0中的逃逸闭包,如果闭包被作为参数传递到函数时,该闭包不需要立即执行而是需要等某些线程完成任务之后再执行,那么需要在该闭包前加上@escaping,否则编译器报错。如下代码所示:

//以下函数是当动画页面动画结束之后执行一个闭包
func animationAfter(completion: @escaping () -> Void) {
UIView.animate(withDuration: 0.3, animations: {
// do some animation
}) { (isCom) in
completion()
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容