• 本文介绍几点Swift 3.0相对于Swift 2.0的一些改变和使用方法 关于Swift 3.0的具体使用指南大家可以去阅读Swift 3.0中文文档(Swift 3.0 中文文档)和Swift 3.0官网文档(Swift 3.0 官网文档)

    关于Swift 3.0的具体使用指南大家可以去阅读Swift 3.0中文文档(Swift 3.0 中文文档)和Swift 3.0官网文档(Swift 3.0 官网文档

    1.首当其冲的就是闭包的修改。

    升级完Xcode8之后根据提示会默认帮你进行一些修改。但是修改完成还有500+多个错误很大一部分是闭包的修改,我的内心是这样的。

    在Swift2.3中我们写闭包是这样写:

        //Swift 2.2
        typealias detailCollectBlock = (state:Bool)->Void
    
        var detailCollect:detailCollectBlock?
    
        func detailCollect(detailCollect:detailCollectBlock)
        {
            self.detailCollect = detailCollect
        }
    
        //在需要的时候调用
        self.detailCollect?(state:true)
    
        //
        controller.detailPraise({ (state) in
            model.isPraise = (state ? "1" : "0")
                })
        //Swift3中的 使用方法1 
        typealias detailCollectBlock = (Bool)->Void
    
        var detailCollect:detailCollectBlock?
    
        func detailCollect(detailCollect:@escaping detailCollectBlock)
        {
            self.detailCollect = detailCollect
        }
        //在需要的时候调用
        self.detailCollect?(true)
    
        //在上页面回调接收的时候的用法
        controller.detailPraise(detailPraise: { (<#Bool#>) in
             model.isPraise = (state ? "1" : "0")
                })
    
        //使用方法2
        typealias detailCollectBlock = (_ state:Bool)->Void
    
        var detailCollect:detailCollectBlock?
    
        func detailCollect(_ detailCollect:@escaping detailCollectBlock)
        {
            self.detailCollect = detailCollect
        }
    
        //在需要的时候调用
        self.detailCollect?(state:true)
    
        //
        controller.detailPraise({ (state) in
            model.isPraise = (state ? "1" : "0")
                })

    这个时候大家应该就可以从代码中发现,swift3中需要定义闭包的时候不需要命名参数名,只需要告诉参数类型即可.

    现在迁移我们也可以使用方法2,这时我们的参数在使用时还是省略的(就和2.2时使用相同),外部调用闭包的时候就不需要在修改了。这样可以减少很多工作量,因为项目中的闭包实在是太多了..

    如果闭包不是在当前作用域内执行而是还要继续传递到别的函数里的话, 那就必须加上@escaping,本身的意思是逃逸的

    别接收回调的地方也和swift2.2不同,回调方法中会有block的名字,但是没有参数名了(方法2中就没有名字啦),只有参数的类型,我们需要自己来定义参数的名称.

    详情见SE-0103SE-0118

    2.在Swift2.3中我们函数在被调用时的第一个参数名会被省略,除非在前面在此定义eq:

    //这样才会在调用的时候显示参数名 swift2.2时
    func addCollect(detailId detailId)

    在Swift3中我们不需要在这样做了。会一直带有第一个参数名

    3.UIControlState等的表示状态的常量 都变成了首字母小写

    //Swift2.2
    self.toolsView?.praiseButton.setImage(UIImage.init(named: "tool_icon_like_normal"), forState: .Normal)
    
    self.phone?.componentsSeparatedByString() //swift2.2
    
    //swift3
    self.toolsView?.praiseButton.setImage(UIImage.init(named: "tool_icon_like_normal"), for: .normal)
    
    self.phone?.components(separatedBy: "-") //swift3

    这样做也是为了脱离OC冗长的方法命名,精简了语意,但是可读性还需要长时间的检验吧

    3.使用NSDictionary的修改

    dict.setObject(true, forKey: "state")
    dict.setObject(num, forKey: "key")

    在之前我们一直使用NSDictionary(<font color=gray>因为从OC转过来感觉还是NSarray和NSDictionary用起来顺手的</font> ),用来设置key的时候。现在需要添加NSCopying ,所以我都改成Dictionary啦哈哈。现在我们也应该在之后写代码的时候避免使用NSString,NSArray, NSDictionary等因为现在更加不方便了~~

    4.泛型

    //swift2.2
     var selectResult:PHFetchResult?
    
    //swift3
     var selectResult:PHFetchResult<PHAsset>?

    这个是项目中图片管理器所用到的,现在就是需要在PHFetchResult后面告诉它是什么类型,也可以是AnyObject
    这个后面还需要详细的介绍。给自己挖个坑

    5.没有了CGRectMake 改用CGRect.init来初始化或者我们写一个他的扩展.来模拟之前的CGRectmake

    //用来代替,修改的CGRectMake
    func CGRectMake(_ x:CGFloat,_ y:CGFloat,_ width:CGFloat,_ height:CGFloat)->CGRect
    {
        return CGRect.init(x: x, y: y, width: width, height: height)
    }

    6.关于颜色的初始化方法UIColor.color都去掉了括号,并且color的后缀页去掉了,新添加了Url类,也是为了脱离OC的NSUrl吧.

    7.GCD的改变 更加Swift化.

    DispatchQueue.main.async {
        let controller = LoginViewController()
        self.present(controller, animated: true, completion: nil)
                    }

    其实GCD的用法没有太多的改变,只是写法变的更加Swift,去掉了之前C语言的形式,多写读多熟悉应该就好了。

    9.NSString操作的变化

    //swift2.2
       let ch = (pinYinString as NSString).character(at: 0)
    //swift3
        let ch=pinYinString?.unicodeScalars[(pinYinString?.unicodeScalars.startIndex)!]

    因为我需要取到拼音的首字母来进行排序,所以需要获取到首字母的ASCII码。所以使用NSString更方便。但是现在不能这样用了,所以我们只能使用Swift中的这个unicodeScalars来获取啦。

    8.枚举变成了小写,自己定义的时候是大写当他变成.语法的时候Xcode页把它变成了小写

    展开全文
  • 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax… 让Xcode帮我们把Swift2.3的代码转换为Swift3.0。 手动调出Xcode自动转换Swift2.3 到 Swift3.0弹出语言版本选择界面,选择Covert ...

    Swift3.0语法变化

    写在前面

    首先和大家分享一下学习新语法的技巧:
    用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax… 让Xcode帮我们把Swift2.3的代码转换为Swift3.0。

    这里写图片描述
    手动调出Xcode自动转换Swift2.3 到 Swift3.0

    弹出语言版本选择界面,选择Covert to Swift3,Next:
    这里写图片描述

    进入选择模块界面:
    这里写图片描述
    选择模块界面

    建议只选择自己创建的模块,第三方框架的模块最好不要使用Xcode来转换,等待第三方作者更新。

    进入转换界面:
    这里写图片描述
    转换界面
    不要着急Save,在这个界面中详细的列出了各个语法具体变化,我们可以利用这个界面来快速学习自己项目中遇到语法变化。

    好了,下面给大家分享一下我的遇到的语法变化。

    常用类及方法的Swfit风格化

    UIColor

    将常用的标准颜色写成了只读属性,不再是方法,调用方法改变。
    这里写图片描述

    Swift 2.3 UIColor

    这里写图片描述

    Swift 3.0 UIColor

    这里写图片描述

    Swift 3.0 和 Swift 2.0 写法对比

    Any和AnyObject

    这两个类型都是Swift中很早就出现的类型,但是我们经常使用AnyObject,很少使用Any。
    AnyObject类似于OC中的id类型,表示任意的class的实例对象,但是在Swift中,例如我们常见的String和Array都变为结构体了,而且在Swift3.0中,更多的类型或者枚举被写为结构体了,AnyObject的适用范围变相被削弱了,所以在Swift3.0的API中曾经许多AnyOjbect的类型被替换为Any了。
    当然,这对于我们使用这些API没有影响,但是在我们自己定义方法时,如果需要用到AnyObject,就需要认真考虑一下该用AnyObject还是Any了。
    这里写图片描述

    Swift 3.0 和 Swift 2.0 写法对比

    BOOL属性的命名规则

    在OC中,官方建议我们将BOOL属性的getter方法命名为isXXX,Swift中由于只是将原有OCUIKit框架进行Swift转换,所以这个规则在之前是Swift中并没有体现。在Swift3.0中,这个规则被再次应用,所有的BOOL类型都重新命名为isXXX,所以以后我们的自定义类中BOOL属性的命名也应体现这个规则。
    这里写图片描述

    布尔类型的属性get方法改变

    Foundation框架部分类名去掉NS前缀

    包括:UserDefaults、URL、NotificationCenter、Bundle、Timer、Thread、RunLoop
    这里写图片描述

    Swift 3.0 和 Swift 2.3 写法对比

    常用系统提供单例类的获取方法Swift风格化

    这里写图片描述
    Swift 3.0 和 Swift 2.3 写法对比

    常用结构体的构造方法改变

    常用的结构体有:CGSize、CGPoint和CGRect。
    这里写图片描述

    Swift 3.0 和 Swift 2.3 写法对比

    Swift2.3中,使用构造方法和make函数都可以创建;

    // Make函数创建
    let _ = CGSizeMake(10, 20)
    // 构造方法创建
    let _ = CGSize(width: 10, height: 20)
    Swift3.0中,废弃make函数,只能使用构造方法创建。

    // 只能使用构造方法创建
    let _ = CGSize(width: 10, height: 20)

    转变为结构体的类

    在之前的Swift版本中,苹果引入了String、Array和Dictionary这三个结构体来代替OC中的NSString、NSArray和NSDictionary这三个类,当然这三个OC类依然可以使用。但是在平时的开发使用中,Swift的这三个结构体使用起来更方便,大部分情况下效率更高。
    在Swift3.0中,苹果又推出了以下新的结构体,原有OC类依然可以使用。并且可以相互转化。
    这里写图片描述
    新增结构体类型及对应的OC类型

    通知的变化

    这里写图片描述

    Swift 3.0 和 Swift 2.3 写法对比

    Swift 3.0 中NSNotification和Notification创建时,通知的name参数类型都变为“Notification.Name”类型,该类型创建比较复杂。

    // Swift3.0中的通知
    let _ = NSNotification(name: NSNotification.Name(rawValue: “name”), object: nil)
    let _ = Notification(name: NSNotification.Name(rawValue: “name”))

    UIViewController 返回是否显示状态栏的方法变化

    这里写图片描述
    控制器方法改为属性

    获取string的字符串长度方法的改变

    这里写图片描述
    获取字符串长度参数改变

    获取沙盒指定文件夹路径的方法变化

    获取文件路径统一交给FileManager来管理
    这里写图片描述

    获取沙盒路径参数改变

    Swift3.0中GCD语法的改变

    Swift3.0中GCD写起来更简洁了。
    这里写图片描述
    GCD语法改变

    延迟执行的代码转换的不够好。应该这样写:

    // 延迟执行代码
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
    print(“2324”)
    }

    Swfit的关键字的变化

    private和fileprivate

    private: 私有属性和方法,仅在当前类中可以访问,不包括分类;
    fileprivate: 文件内私有属性和方法,仅在当前文件中可以访问,包括同一个文件中不同的类。

    /// 以下所有的类都在同一个文件中
    class Test: NSObject {
    // 只能在当前大括号内访问
    private var value: Int = 0
    // 只能在当前文件内访问
    fileprivate var value1: Int = 0

    // 只能在当前大括号内访问
    private func privatePractise() {
    value = 1
    value1 = 1
    fileprivatePractise()
    fileprivatePractise1()
    print(“privatePractise方法被调用了”)
    }
    // 只能在当前文件内访问
    fileprivate func fileprivatePractise() {
    privatePractise()
    fileprivatePractise()
    fileprivatePractise1()
    print(“fileprivatePractise方法被调用了”)
    }
    }
    extension Test {
    // 只能在当前大括号内访问
    private func privatePractise1() {
    value1 = 1
    fileprivatePractise()
    fileprivatePractise1()
    print(“privatePractise方法被调用了”)
    }

    // 只能在当前文件内访问
    fileprivate func fileprivatePractise1() {
    privatePractise1()
    fileprivatePractise()
    print(“fileprivatePractise方法被调用了”)
    }
    }
    class Test2: NSObject {
    func test() {
    let t = Test()
    t.value1 = 0
    t.fileprivatePractise()
    t.fileprivatePractise1()
    }
    }

    public和open

    在Swift2.3中,pubic有两层含义:

    1. 这个元素可以在其他作用域被访问
    2. 这个元素可以在其他作用域被继承或者override

    继承是一件危险的事情。尤其对于一个framework或者module的设计者而言。在自身的module内,类或者属性对于作者而言是清晰的,能否被继承或者override都是可控的。但是对于使用它的人,作者有时会希望传达出这个类或者属性不应该被继承或者修改。这个对应的就是 final。

    final的问题在于在标记之后,在任何地方都不能override。而对于lib的设计者而言,希望得到的是在module内可以被override,在被import到其他地方后其他用户使用的时候不能被override。

    这就是 open产生的初衷。通过open和public标记区别一个元素在其他module中是只能被访问还是可以被override。

    在Swift3.0中

    • public表示当前类、属性或者方法只能在当前module内被继承或者override,在当前module意外只能被访问;
    • open表示当前类、属性或者方法可以在任何地方被继承或者override;
    • final是一个辅助修饰词,表示当前类、属性或者方法在任何地方都只能被访问,不能被继承或者override;
    • internal表示默认级别。

    /// ModuleA:
    import UIKit
    /// 这个类在ModuleA的范围外是不能被继承的,只能被访问
    public class NonSubclassableParentClass: NSObject {
    // 这个方法在ModuleA的范围外只能被访问,不能被override
    public func test() {
    print(“test”)
    }
    //这是错误的写法,因为class已经不能被集成,所以她的方法的访问权限不能大于类的访问权限
    open func bar() {
    print(“bar”)
    }
    // 这个方法在任何地方都只能被访问,不能被override
    public final func baz() {
    print(“baz”)
    }
    }
    /// 在ModuleA的范围外可以被继承
    open class SubclassableParentClass: NSObject {
    // 这个属性在ModuleA的范围外只能被访问,不能被override
    public var size: Int = 0
    // 这个方法在ModuleA的范围外只能被访问,不能被override
    public func foo() {
    print(“foo”)
    }
    // 这个方法在任何地方都可以被override
    open func baz() {
    print(“baz”)
    }
    // 这个方法在任何地方都只能被访问,不能被override
    public final func bar() {
    print(“bar”)
    }
    }
    /// 这个类在任何地方都不能被继承
    public final class FinalClass {
    }

    总结

    Swfit3.0中,访问控制权限由高到低依次为:open、public、internal(默认)、fileprivate,private。

    Swift3.0中if…where和guard…where的变化

    Swift3.0中对where关键字的使用场景进行了一些调整,在Swift2.3中,我们常这样写:

    // Swift2.3
    var value: Int?
    var num: Int?

    if let v = value, n = num where v > n {
    print(“value > num”)
    }

    value = 1
    num = 2

    guard let v = value, n = num where v > n else {
    print(“value < num”)
    return
    }
    在Swift3.0中,应该这样实现:

    // Swift3.0
    var value: Int?
    var num: Int?

    if let v = value, let n = num, v > n {
    print(“value > num”)
    }

    value = 1
    num = 2

    guard let v = value, let n = num, v > n else {
    print(“value < num”)
    return
    }

    Swift3.0中枚举的变化

    在Swift2.3中,官方使用的枚举值首字母使用大写,在Swift3.0中,统一将官方使用的枚举值首字母改为了小写。虽然自定义的枚举中枚举值首字母依然可以使用大写,但是为了和官方风格保持一致,建议枚举值首字母使用小写。

    /// 这种写法是正确的(与官方风格一致,推荐使用)
    enum Direction: String {
    case east = “east”
    case south = “south”
    case west = “west”
    case north = “north”
    }

    /// 这种写法也是正确的(与官方风格不一致,不推荐使用)
    enum Sex: Int {
    case Man = 0
    case Woman = 1
    case Other = 2
    }

    Swift3.0中方法名的Swift风格化

    在Swift的方法命名规则中,参数有两个名称,一个内部名,一个外部名。当参数有外部名时,方法调用时只显示外部名,若无外部名,则默认外部名和内部名相同。
    这里写图片描述
    外部名和内部名

    在Swift2.3中,第一个参数若没有外部名,则调用时候常省略。对于常用的UIKit和Foundation框架来说,Swift2.3中的方法名称依然是OC语言的风格。
    这里写图片描述

    Swift2.3 方法名称风格

    在Swift3.0中,第一个参数若没有外部名,则调用时显示内部名,不省略。同时将常用的UIKit和Foundation框架的方法名进行了Swift风格化,使方法调用时更简洁清晰。
    这里写图片描述

    Swift3.0 方法名称风格

    两种风格方法调用对比:
    这里写图片描述
    dismiss方法swift风格化

    建议以后自定义方法时,风格尽量和Swift3.0保持一致。
    在Swift3.0 编译器环境下两种风格对比:
    这里写图片描述

    自定义方法两种风格对比

    Swift3.0中selecter的Swift风格化

    在Swift2.2中,当我们为一个按钮添加点击事件时常常这样写:
    这里写图片描述

    Swift 2.3 中 Selector写法

    在Swift2.2更新到Swift2.3后可以看到警告告诉我们这是一个OC风格的写法,建议改为Swift风格的写法。
    在Swift3.0中两种写法依然都可以使用,但是建议统一写为Swift风格的,因为你不知道什么时候OC风格的就不被允许了。
    这里写图片描述
    Swift 3.0 中 Selector写法
    运算符的变化

    1. Swift3.0中运算符的左右两边必须不能为optional。
    2. ++和–是继承自C语言中的运算符,在Swift3.0中被移除,建议使用 x += 1来代替。
      这里写图片描述

    文/光无影(简书作者)
    原文链接:http://www.jianshu.com/p/460b5424942a
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

    展开全文
  • 很久没看swift。 println已经变成了print了。 定义属性不用现在也会有警告了。 字符串的长度从以前的count(str) 变成现在的str7.characters.count了。 字符串从大写变为小写的方法从lastPathComponent变成了现在的...

    很久没看swift。以前写的代码出现了很多问题。抛弃之。

    println已经变成了print了。

    字符串的长度从以前的count(str) 变成现在的str7.characters.count了。

    字符串从大写变为小写的方法从lastPathComponent变成了现在的lowercaseString

    字符串转化为int类型,从以前的.toInt()变成了现在的.hashValue或者Int(str)

    for (index,str) in enumerate(listZ)  ==>  for (index,str) in listZ.enumerate()           

    数组的 unshare,copy 去掉,数组和字典的行为一致了,都是值类型

     


    展开全文
  • Swift_3.0 相对于 Swift_2.2 版本发生了哪些的变化。本文件将以最直观的代码对比以及文字分析阐述。

    一、编译器和语法变化



    函数或方法参数


    • 调用函数或方法时从第一个参数开始就必须指定参数名

    在Swift的历史版本中出现过在调用函数时不需要指定任何函数参数(或者从第二个参数开始指定参数名),在调用方法时则必须从第二个参数开始必须指定参数名等多种情况,而在Swift3.0中不管是函数还是方法都必须从第一个参数开始必须指定参数名(当然可以使用“_”明确指出调用时省略参数)。

    // 从第一个参数就必须指定参数名,除非使用"_"明确指出省略参数
    func sum(num1:Int,num2:Int)->Int{
        return num1 + num2
    }
    
    sum(num1: 1, num2: 2) // old: sum(1,2)或者sum(1, num2: 2)
    • 取消var参数

    //func increase(var a:Int){
    //    a += 1
    //}
    // 上面的代码会报错,可改写成
    func increase(a:Int){
        var a = a
        a += 1
    }
    • inout参数修饰改放到类型前

    //func increase(inout a:Int) {
    //    a += 1
    //}
    // 上面的代码会报错,可改为
    func increase( a:inout Int) {
        a += 1
    }


    方法返回值


    Swift 3.0 中方法的返回值必须有接收否则会报警告,当然其实主要目的是为了避免开发人员忘记接收返回值的情况,但是有些情况下确实不需要使用返回值可以使用"_"接收来忽略返回值。当然你也可以增加@discardableResult声明,告诉编译器此方法可以不用接收返回值。

    struct Caculator {
        func sum(a:Int,b:Int) -> Int {
            return a + b
        }
        
        @discardableResult
        func func1(a:Int,b:Int) ->Int {
            return a - b + 1
        }
    }
    let ca = Caculator()
    ca.sum(a: 1, b: 2) // 此处会警告,因为方法有返回值但是没有接收
    let _ = ca.sum(a: 1, b: 2) // 使用"_"接收无用返回值
    ca.func1(a: 1, b: 2) // 由于func1添加了@discardableResult声明,即使不接收返回值也不会警告


    可选类型


    Swift3.0对于可选类型控制更加严谨,隐式可选类型和其他类型的运算之后获得的是可选类型而不是隐式可选类型。

    let a:Int! = 1
    let b = a + 1 // 此时强制解包,b是Int型
    let c = a // 注意此时c是Int? 在之前的Swift版本中c是Int!


    Selector的变化


    Selector的改变其实从1.0到3.0经历了多次变化,从最早的@Selector("method:")到现在的#selector(method(param1:))可以说经历了多次修改,好在它变得越来越好,毕竟字符串操作对于语法检查来说是很无助的。

    class MyClass {
        @objc func sum(a:Int,b:Int) -> Int {
            return a + b
        }
        
        func func1(){
            let _ = #selector(sum(a:b:))
        }
    }
    
    // old: Swift 2.2
    //class MyClass {
    //    @objc func sum(a:Int,b:Int) -> Int {
    //        return a + b
    //    }
    //    
    //    func func1(){
    //        let _ = #selector(sum(_:b:))
    //    }
    //}


    协议中的可选方法


    在Swift3.0之前如果要定义协议中可选方法,只需要给协议加上@objc之后方法使用optional修饰就可以了,但是Swift3.0中除了协议需要@objc修饰,可选方法也必须使用@objc来修饰。

    @objc protocol MyProtocol {
        @objc optional func func1() //old: optional func func1()
        func func2()
    }


    取消++、--操作符


    var d = 1
    d++ //报错,可以改写成 d += 1 或者 d = d + 1


    取消C风格for循环


    //for var i = 0 ;i < 10 ; i += 1 {
    //    debugPrint(i)
    //}
    // 上面的代码会报错,可改写成如下代码
    for i in 0  ..< 10  {
        debugPrint(i)
    }



    二、SDK类库变化


    大家都知道Swift诞生在Objective-C已经发展的相当成熟的情况下,为了保证ObjC开发人员顺利过渡到Swift,也因为Swift处于初级阶段,很多类库和方法命名都尽量和ObjC保持一致,在使用Swift开发iOS应用中处处可以看到ObjC的影子。但是作为一门Modern语言Swift还是做出了改变,从中可以看出日后Swift将彻底摆脱ObjC的影子。这其中包括重新导入Foundation消除类型前缀、方法名去重、函数和方法去C风格等等。


    命名


    // 1.去掉前缀
    let url1 = URL(string: "www.cmjstudio.com")
    let isFileURL = url1?.isFileURL //old:url1.fileURL ,现在更加注重语意
    let data1 = Data() //NSData
    
    // 2.方法名使用动词,其他名词、介词等作为参数或移除
    var array1 = [1,2,3]
    array1.append(contentsOf: [4,5,6]) // old:array1.appendContentsOf([4,5,6])
    array1.remove(at: 0) // old:array1.removeAtIndex(0)
    
    // 3.不引起歧义的情况下尽量消除重复
    let color1 = UIColor.red() // old:var color1 = UIColor.redColor()
    
    // 4.枚举成员首字母变成小写
    let label1 = UILabel()
    label1.textAlignment = .center // old:label1.textAlignment = .Center
    
    // 5.按钮的Normal状态去掉
    let btn1 = UIButton()
    btn1.setTitle("hello", for: UIControlState()) // 相当于Normal状态


    去C风格


    Swift发展初期很多类库的引入依然保持的ObjC风格,但是ObjC由于根出C语言,因此很多操作其实并不是对象和方法操作而是C语言的函数形式。到了Swift3.0之后这一现状将发生变化,全局函数将会变成某些类型的方法;某些常量定义将以某个枚举类型的成员来表示。

    let rect1 = CGRect(x: 0, y: 0, width: 100, height: 100)
    // 下面的代码将要报错,3.0完全废除这种类C的风格
    //let rect1 = CGRectMake(0, 0, 100, 100)
    
    if let context1 = UIGraphicsGetCurrentContext() {
        CGContext.fillPath(context1) // old:CGContextFillPath(context1!)
    }
    
    // GCD的改变
    let queue = DispatchQueue(label: "myqueue")
    queue.async {
        debugPrint("hello world!")
    }
    // old:
    //let queue = dispatch_queue_create("myqueue", nil)
    //dispatch_async(queue) {
    //    debugPrint("hello world!")
    //}
    
    // 相关常量定义被移到枚举内部
    NotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: UserDefaults.didChangeNotification, object: nil)
    //old:NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: NSUserDefaultsDidChangeNotification, object: nil)


    集合API的变化


    let array1 = [1,2,3]
    let next = array1.index(after: 0)  // old:let start = array1.startIndex let next = start.successor()
    let first = array1.first { (element) -> Bool in // 增加新的方法
        element > 1
    }
    
    let r = Range(0..<3) //old: let _ = NSRange(location: 0, length: 3)
    
    // 下面的代码必须在控制器中执行,用于遍历当前view及其父视图
    for subview in sequence(first: self.view, next: { $0?.superview }){
        debugPrint(subview)
    }


    新的浮点协议


    Float、Double、CGFloat使用了新的协议,提供了提供 IEEE-754标准的属性和方法。

    let a = 2 * Float.pi // old: let a = 2 * M_PI
    let b = 2.0 * .pi // 注意前面是浮点型,后面可以省略Float



    三、从Swift_2.2迁移到Swift_3.0


    可以看出如果要更新到Swift3.0现有项目需要作出大量修改,经过使用之前的项目进行测试,区区十个类文件就出现了一百多个错误,不过好在Xcode 8已经提供了很好用的迁移工具(Xcode:Editor - Convert - To Current Swift Syntax),经过迁移工具转化后仅仅发现两处错误需要手动修正。在使用这个工具的时候大家会看到如下界面:



    Swift 2.3?没错Swift2.2和Swift 3.0中间还有个Swift 2.3,Apple也解释了什么是Swift 2.3,其实就是Swift 2.2 + New SDKs。之所以如此是因为Xcode 8目前还是beta版,使用Swift 3.0进行开发的应用还不能提交App Store,因此在Swift 2.2基础上使用新的SDK开发还是有存在必要的。

    展开全文
  • 每当看到新的编程语言我总是会有相当大的兴趣,是的,Swift 3是一门『新语言』,因为它看起来,怎么都不像过往的 Swift。打开一个老的项目时,发现满目疮痍,基本上能标红的代码全被标红了。先来个截图提提神: 图...

    每当看到新的编程语言我总是会有相当大的兴趣,是的,Swift 3是一门『新语言』,因为它看起来,怎么都不像过往的 Swift。打开一个老的项目时,发现满目疮痍,基本上能标红的代码全被标红了。先来个截图提提神:


    图一 代码标红

    怎么样,清醒点了没?可能你会觉得奇怪,怎么连 whiteColor() 这种通用的东西都不能用了?其实这是本次 Swift(和 SDK)大改的一个重要目标,就是『去重』。新的 SDK 去除了大量可有可无的东西,并且把库做深度的修整,现在的 SDK 看起来更好用了(当然你也可以吐槽又要记大量新的东西了,不过 Swift 哪次新版发布时你不改程序了,对吧)。下面我一一来讲述。

    一、去重

    Swift 3 对于重复输入的表达式深恶痛绝,如上图所示的 whiteColor(),现在一律被改为了 white()。我们可以推断出其他类似的改动(或者让 IDE 帮助我们),如:

    UIColor.whiteColor() 
    被改为
    UIColor.white()
    list.objectAtIndex(i)
    被改为
    list.object(at: i)

    同样的,方法也被如此修改了,如:

    presentViewController(controller, animated: true)
    被改为
    present(toViewController: controller, animated: true)
    dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath)
    被改为
    dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    func numberOfSectionsInTableView(tableView: UITableView) -> Int
    被改为
    func numberOfSections(in tableView: UITableView) -> Int

    一个很不幸而且几乎会让人崩溃的消息是,这样的改动几乎发生在每一处函数调用,这使用开发人员不得不重新审视几乎所有的代码,因为老的代码可能都在新的 SDK 下变得毫无建树。

    二、参数

    Swift 3 对参数的传入做了大幅改动,主要是添加了参数名称的限定,在 Swift 3 下,一个方法所接受的参数必须拥有『名称』,而让全部参数都拥有名称这件事,改动实在太大了,因此 Swift 又想出了一招可以让你不写名称,使用单个下划线作为允许匿名符号。参考以下实例:

    override func viewWillAppear(animated: Bool)
    被改为
    override func viewWillAppear(_ animated: Bool)

    下面再看一个实例的调用例子,加深印象:

    func myFunc(x: Int, y: Int)
    这个函数在调用时必须使用以下代码
    myFunc(x: 1, y: 2)

    若是允许匿名参数,则修改之:

    func myFunc(_ x: Int, _ y: Int)
    这个函数在调用时允许不带参数名称
    myFunc(1, 2)

    这样的改动较大程度的影响了原有继承下来的方法,如viewWillAppear,UITableView 的回调函数等。对于自己写的方法,稍加注意即可,这两种方法都有着各自适用的场景。

    三、命名

    在早期的 Objective-C 或 Swift 中,系统内的常量、函数等的命名一直是一件让人头疼的事,例如UIControlContentHorizontalAlignmentCenter这种,简直又臭又长,超级难记,虽说有 Xcode 这种强大的 IDE,也难免会弄错。在 Swift 3 内,所有的相关常量都被划到指定的枚举类中,而常量和函数均遵守相当良好的代码规范。来看几个实例:

    lbl.textAlignment = NSTextAlignment.Center
    被改为
    lbl.textAlignment = NSTextAlignment.center
    tableFooterView = UIView(frame: CGRectZero)
    被改为
    tableFooterView = UIView(frame: CGRect.zero)

    另外,现在的新的命名方式也更注重突出实际作用,再给个例子体会下:

    lbl.hidden = false
    被改为
    lbl.isHidden = false

    与此同时,所有NS类的类名也变得简洁了,不再需要NS前缀,再配合其他的改动(如去重),对代码的精简形成了相当大的影响:

    let bundle = NSBundle.mainBundle()
    被改为
    let bundle = Bundle.main()
    let mgr = NSFileManager.defaultManager()
    被改为
    let mgr = FileManager.default()

    再次告知一个不幸的消息,这样的改动几乎也牵动了全部的代码!!讲到这里可能有一部分人已经哭了,居然要改那么多代码,还能不能好好玩耍了? 别担心,下面还有一半。

    四、方法的返回值处理

    我们在开发中可能会经常调用一些带有返回值的方法,但是却不处理返回值,例如以下这种:

    navigationController!.popViewControllerAnimated(true)

    这个方法实际上返回一个 UIViewController,但是很少有人会用,更多的场景是把它当成无返回的方法来使用。但是在 Swift 3 中,这样做是不行的,你必须处理掉这个返回值,如下:

    let _ = navigationController!.popViewController(animated: true)

    使用单个下划线来指代一个不会被使用的变量。

    另外,Swift 3 不再允许传入传出的对象,之前带有 var 的方法声明将全部作废:

    func myFunc(var a: Int) -> Int

    如以上这种声明,已不可再使用,对于有多个值要返回的方法,必须改为:

    fun myFunc(a: Int) -> (Int, Int)

    五、可选类型

    Swift 3 对可选类型的处理更严格了,必须显式的在任何地方使用感叹号,例如我们有以下代码:

    var str: String! = "a"
    var s = str
    print(s)

    在 Swift 以往的版本中,print 语句会打印出 str 的值,也就是『a』。而在 Swift 2.3 下,则是会打印出『Optional("a")』。因此很多对字符串处理(特别是路径处理)的代码都会出错,因为会莫名其妙的带上了各种各样的『Optional』字样。正确的处理方式是:

    var str: String! = "a"
    var s = str!
    print(s)

    或者

    var str: String! = "a"
    var s = str
    print(s!)

    同样的,在实际开发中,如果用到字符串模板,也需要非常注意这样的变化:

    var str  = "Loaded: \(data)"
    需要被修改为
    var str  = "Loaded: \(data!)"

    六、Selector

    Swift 对于 Selector 的修改可能是最让人无奈的了,我们来细数一下经历过的版本:

    self.performSelector(onMainThread: #selector(handle(ret:)), with: ret, waitUntilDone: true)
    就以 Swift 3 下的这个函数为基准吧,老版本的Selector获取方法是这样的:
    #selector(ViewController.handle(_:))    // 2.2
    #selector(ViewController.handle(:))     // 2.1
    #selector(handle)                       // 2.0
    @selector("handle:")                    // 1.x  x等于几已经不记得了
    "handle:"                               // 没记错的话是 1.0 时代,直接传个字符串就是 Selector
    N/A                                     // Swift 的历史上,还真有过没有 Selector 的版本

    回到 Swift 3 上来,目前的 Selector 写法如最上面那种,需要注意的是,Selector 的方法名和参数名必须与实际被调用的方法完全一致,否则编译时就会报错。

    另外,Selector 传参时,只能传递对象,不能传基础数据类型,传基础数据类型的情况下,一律变成0(希望这只是当前版本的 bug,不然太蛋疼了)。虽说苹果已经把大部分的 NS 类都去掉了前缀,但是 NSNumber 这东西还是得经常用一下呢,至少目前是这样的。

    七、类库

    随着 Swift 3 一起发布的 iOS SDK 10,其改动也不小,特别是对一些类库的改动,删除了大量的方法,有些方法可能是对我们过去的开发带来大量帮助的。但是没有办法,我们必须接受这样的改变。

    类库的改动没有办法一一说明,我用到的 SDK 成员也非常有限,所以就只讲几个例子。

    • 针对有 option 选项的 protocol,目前强制要求为每一条都写上 @objc,如:

      @objc protocol MyProtocol: NSObjectProtocol {
            optional func foo(myClass: MyClass?)
            optional func bar(myClass: MyClass?)
      }
      需要改为
      @objc protocol MyProtocol: NSObjectProtocol {
            @objc optional func foo(myClass: MyClass?)
            @objc optional func bar(myClass: MyClass?)
      }
    • 不再有CGRectMakeCGSizeMake等常用函数了,如:

      UIView(frame: CGRectMake(0, 0, 48, 48))
      被改为
      UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 48))
    • Normal选项用方括号对来代替,如:

      btn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
      被改为
      btn.setTitleColor(UIColor.white(), for: [])

      至于为什么会如此改,我是没想明白,不管怎么说,UIControlState内已经没有normal这个选项了,目前也只能这么做。方括号非常容易引起对于数组或是集合等的联想,但是此处却又完全不是数组或集合,方括号的语义并不清晰。

    • 图形图象库有较大改动,给个具体例子参考下:

      let imgData = UIImageJPEGRepresentation(img, 1)
      let imgPath = "\(FileUtils.getDocumentPath())/\(name)"
      imgData!.writeToFile(imgPath, atomically: true)
      必须改为
      let imgData = UIImageJPEGRepresentation(img, 1)
      let imgPath = "\(FileUtils.getDocumentPath()!)/\(name!)"
      NSData(data: imgData!).write(toFile: imgPath, atomically: true)

    结束语

    就先讲这么些吧,已经够各位改一阵子了。虽然 Swift 这么虐,但是随着一次次迭代,还是可以看到它在稳固的进步着,希望以后不要再那么大变化了吧。至少语法给个兼容,类库给个 Mapping,不要直接全屏飘红(可以飘黄呀...),或许这样才能走得更快更稳吧。

    最后多讲一句,临时改标题是不对的,但是我还是改了,跟大家说声抱歉。昨天犯了个错误,XCode8 里面的确是 Swift3,只是我们都被它内置的 2.3 给误导了,真正的 Swift3 编译器被放在一个奇怪的地方:

    Swift 2.2: Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
    Swift 2.3: Developer/Toolchains/Swift_2.3.xctoolchain/usr/bin/swift
    Swift 3:   Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator/swift



    原文链接:http://www.jianshu.com/p/198405c1c467
    展开全文
  • 警告:Expression of type ‘UIViewController?’ is unused// 赋值给_,否则会报Expression of type 'UIViewController?' is unused _ = self.navigationController?.popViewController(animated: true)...
  • 这是一篇学习笔记。在粗略的看了 Protobuf 的文档中关于 proto2 和 proto3 的说明后,记录下了几点 proto3 区别于 proto2 的地方。 总的来说,proto3 比 proto2 支持更多语言但 更简洁。去掉了一些复杂的语
  • 为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。如果你的项目以前使用过这些API,建议您立即升级到基于 NSURLSession 的API的AFNetworking的版本。本指南将引导您完成...
  • 2.0时代 func change(a : Int){ a += 1 } 2.3时代 func change(inout a : Int){ a += 1 } 3.0时代 func change(a : inout Int){ a += 1 } 调用方法的时候: var testInt = 0 change(a: &te...
  • 如何快速将Swift2.0的项目过渡到Swift3.0 今年WWDC之后,相信大家都已经更新到iOS10和Xcode8.0beta版本尝鲜了,其中包括SiriKit、新的语音识别框架SFSpeechRecognizer、通知框架(UserNotifications.framework、...
  • 最近开发完OC的项目,开始搞Swift ,2016年从开发OSX应用 到OC应用 再回归到Swift,回头看已经到Swift3.0了。之前在开发Swift的时候还在1.2 到2.0的切换中。 下面给自己总结一下变化: 1. 监听方法: swift ...
  • 公司需要在原先Swift 3.0项目中引入EasyAR 的Unity SDK。这篇文章记录了集成过程和遇到的问题。 开发环境:macOS 10.12.5, iOS 8,Xcode 8.3.3,Unity 5.6.1f1 #准备工作 1.导出Unity工程 导出Unity工程时的设置 ...
  • Swift 3.0 以后, GCD 的使用发生了很大的变化, 相比 Swift 2.0+ ,变得更加简洁了!首先学习几个比较重要的概念:队列 1 - 并发队列可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务) 并发功能只有在...
  • swift2.0 类型转换 Any AnyObject
  • 环信IM3.0和之前用的2.0版本有些区别,遇到了一些坑,现在总结下: 1.环信3.0 SDK集成 可以通过gradle远程链接导入 首先在你的项目根目录build.gradle文件的allprojects→repositories属性下加入远程库地址 ...
  • 这个方法只能转换有色部分,alpha=0的部分会被转为黑色,所有转换的图片都是不带透明部分的
  • Swift 3到5.1新特性整理

    2019-06-28 20:25:43
    本文转载自:...Hipo 2.0 重写从Swift1的版本写到2的版本,后续Hipo功能稳定,更新慢了很多……,Swift本身却在长足的发展,5.0都已经发布了,本文对Swift 3.0Swift 5.1 的更新点做个总结。...
  • 点击上方“蓝色字”可关注我们!2018上海区块链国际周早鸟票仅剩最后20天,点击阅读原文,立即报名,即可以最优惠的票价参与高质量的区块链盛会。其中,技术开放日+峰会联票优...
1 2 3 4 5 ... 20
收藏数 3,299
精华内容 1,319