Swift 3做了非常大的更换,来领悟OC与swift不一致以及swift版本变动细节

提议读叁回swift
blog
来领会OC与swift分歧以及swift版本变动细节

转自:
https://github.com/KQAppleDev/SwiftLearn
http://blog.csdn.net/qq\_16437739/article/details/52819452
http://www.jianshu.com/p/460b5424942a
http://www.qingpingshan.com/rjbc/swift/155193.html

相较于Swift 2.2 , Swift 3做了相当的大的更换,渐渐脱离OC的黑影。
语法上过多对象去掉了NS初叶,去掉了累赘的命名。如 UIColor.redColor() 改为
UIColor.red , 形成了品质,还会有方法的第一个参数假如不钦命
_调用的时候也要写参数名等等…

OC id -> Swift Any

优点,没有要求手动装箱
使得OC API更灵活

OC Swift2 Swift3
id AnyObject Any
NSArray * [AnyObject] [Any]
NSDictionary * [NSObject:AnyObject] [AnyHashable:Any]
NSSet * Set<NSObject> Set<AnyHashable>

必要小心的而是swift2不再提供隐式调换,因而NS桥接的内需您来得转变

斯威夫特 3 出来也可能有说话了,Swift3做了相当的大的转移,慢慢脱离OC的黑影。语法上过多对象去掉了NS初步,去掉了繁琐的命名。

正文主要商讨斯维夫特 3中的一些坑和选取进度中的一些小技术,排行无理由~~

Overriding methods and conforming to protocols

取名符合OC的典型,id->Any

// Swift 2
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: AnyObject?) -> Bool { ... }
    func copyWithZone(_ zone: NSZone?) -> AnyObject { ... }
}

// Swift 3
class Foo: NSObject, NSCopying {
    override func isEqual(_ x: Any?) -> Bool { ... }
    func copy(with zone: NSZone?) -> Any { ... }
}

本文首要商量斯威夫特 3中的一些坑和平运动用进程中的一些小本领,排名无理由~~

AnyObject 、Any

在此之前全部项目基本只用 AnyObject
代表好些个实例,基本也不和Any有怎么着交集。因为Swift 2 针对Int、String
等结构体进行了更动,编写翻译器会自动桥接为NSNumber和NSString这种对象类型
,在swift3中AnyObject无法表示结构体了 。而 Any 能够象征 struct 、 class
、 func 等差不离全体类型。

Untyped Collections

隐式桥接荒诞不经了,需求接纳as,swift3导入的cocoa接受了Any/AnyHashable,由此对此集结也得以动用[AnyHashable:Any]

// Swift 2
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    var asPropertyList: [NSObject: AnyObject] {
        var result: [NSObject: AnyObject] = [:]//也可以使用NSDictionary
        // Implicit conversions turn String into NSString here…
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        // …and Int into NSNumber here.
        result["population"] = self.population
        return result
    }
}

let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
NSNotification(name: "foo", object: nil,
               userInfo: california.asPropertyList)

// Swift 3
struct State {
    var name: String
    var abbreviation: String
    var population: Int

    // Change the dictionary type to [AnyHashable: Any] here...
    var asPropertyList: [AnyHashable: Any] {
        var result: [AnyHashable: Any] = [:]
        // No implicit conversions necessary, since String and Int are subtypes
        // of Any and AnyHashable
        result["name"] = self.name
        result["abbreviation"] = self.abbreviation
        result["population"] = self.population
        return result
    }
}
let california = State(name: "California",
                       abbreviation: "CA",
                       population: 39_000_000)
// ...and you can still use it with Cocoa API here
Notification(name: "foo", object: nil,
             userInfo: california.asPropertyList)
转换为结构体的类

在以前的斯维夫特版本中,苹果引进了String、Array和Dictionary那八个协会体来代替OC中的NSString、NSArray和NSDictionary那四个类,当然这八个OC类依旧得以接纳。可是在平常的开辟应用中,Swift的那多个结构体使用起来更有益于,抢先二分之一状态下作用越来越高。
在Swift3.0中,苹果又推出了以下新的结构体,原有OC类依然能够应用。而且能够互相转化。

新扩大结构体类型及相应的OC类型

fileprivate

在原本的swift中的private其实并非真的的个人,要是二个变量定义为private,在同叁个文本中的别的类依然是足以访谈到的。这一个场景在使用extension的时候很生硬。

class User {
    private var name = "private"
}

extension User{
    var accessPrivate: String {
        return name
    }
}

那般带动了八个难题:

  • 当大家标识为private时,意为真的私有依然文件内可分享呢?
  • 当大家假若计划为确实的私人民居房时,必须保险那几个类照旧结构体在三个独立的文书里。不然大概同文件里其余的代码访谈到。

经过,在swift 3中,新添了二个
fileprivate来显式的表明,这么些因素的探访权限为文件内私有千古的private对应未来的fileprivate。今后的private则是真正的私人商品房,离开了这几个类依然结构体的效能域外面就不可能访谈

The AnyHashable Type

Any类型能够具备别的类型,不过Dictionary、Set须求Hasble,AnyHashble是swift3提议的hashable的超类,任何三个可hash的品类都实现了Anyhashble协议,举例String、Int

常用系统提供单例类的得到格局Swift风格化

斯维夫特 3.0 和 Swift 2.3 写法相比

不再有CGRectMake,CGSizeMake等常用函数了

UIView(frame: CGRectMake(0, 0, 48, 48))
被改为
UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 48))

// 'CGRectMake' is unavailable in Swift
// let frame = CGRect(0, 20, view.bounds.width, 130)        
// Swift 3.0 不再有CGRectMake,CGSizeMake等常用函数了        
 let frame = CGRect(x: 0, y: 20, width: view.bounds.width, height: 130)

Explicit Conversion for Unbridged Contexts

在局地限制的地方swift不可能直接桥接C和OC的盘算,比方id*,今年api将会呈现UnsafePointer<AnyObject>,此时必要as转变,再&

// ObjC
@interface Foo

- (void)updateString:(NSString **)string;
- (void)updateObject:(id *)obj;

@end

// Swift
func interactWith(foo: Foo) -> (String, Any) {
    var string = "string" as NSString // explicit conversion
    foo.updateString(&string) // parameter imports as UnsafeMutablePointer<NSString>
    let finishedString = string as String

    var object = "string" as AnyObject
    foo.updateObject(&object) // parameter imports as UnsafeMutablePointer<AnyObject>
    let finishedObject = object as Any

    return (finishedString, finishedObject)
}

别的,OC的会谈是类协议,无法用结构体、枚举或任何轻量级的通用项目遵从OC的说道

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

包括:UserDefaults、URL、NotificationCenter、Bundle、Timer、Thread、RunLoop

Swift 3.0 和 斯维夫特 2.3 写法相比

参谋文献

AnyObject Member Lookup

Any未有AnyObject的追寻行为艺术,由此不能够动态的向Any发送信息,然而AnyObject能够,此时内需转移

// Swift 2
func foo(x: NSArray) {
    // Invokes -description by magic AnyObject lookup
    print(x[0].description)
}

// Swift 3
func foo(x: NSArray) {
    // Result of subscript is now Any, needs to be coerced to get method lookup
    print((x[0] as AnyObject).description)//也可以转换到你期望的指定类型as!NSOjbect
}
BOOL属性的命名准则

在OC中,官方提议大家将BOOL属性的getter方法命名字为isXXX,斯维夫特中出于只是将原来OCUIKit框架实行Swift调换,所以那几个法规在前边是斯维夫特中并不曾反映。
Swift3.0中,这么些准绳被另行使用,全数的BOOL类型都重新命名字为isXXX,所以事后大家的自定义类中BOOL属性的命名也应展现那个法则。

Swift Value Types in Objective-C

Any能够具有其他的结构体、枚举、元组或许别的的种类,OC的id在swift3等价于any,在swift第22中学必要手动封箱只怕转入类,swift3则无需

// Swift 2
struct CreditCard { number: UInt64, expiration: NSDate }

let PaymentMade = "PaymentMade"

// We can't attach CreditCard directly to the notification, since it
// isn't a class, and doesn't bridge.
// Wrap it in a Box class.
class Box<T> {
    let value: T
    init(value: T) { self.value = value }
}

let paymentNotification =
    NSNotification(name: PaymentMade,
                   object: Box(value: CreditCard(number: 1234_0000_0000_0000,
                                                 expiration: NSDate())))


// Swift 3
let PaymentMade = Notification.Name("PaymentMade")

// We can associate the CreditCard value directly with the Notification
let paymentNotification =
    Notification(name: PaymentMade,
                 object: CreditCard(number: 1234_0000_0000_0000,
                                    expiration: Date()))

急需当心的是swift3中对此广大的布局体类型将会桥接作为透明对象并非cocoa对象,Int、UInt、Double、Bool会桥接为NSNumber,Int8,UInt16则单独桥接为透明对象。假使遭受了unrecognized selector sent to _SwiftValue主题素材,它代表OC尝试唤醒一个情势在swift
值类型上,此时大家须要手动管理

swift Any持有任一类型富含Optional,固然OC api要求是nonull
id,Optional在未解包的事态下也能够当作参数字传送递,会招致runtime
error并不是编写翻译错误。swift3.0.1+Xoce8.1消除了上述难题,为了幸免包容难点,不要借助于透明对象因为前景的swift恐怕会桥接到固定类型

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方法被调用了")
    }
}

Working with JSON in Swift

JSONSerialization Foundation framework

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。

Extracting Values from JSON

JSONSerialization类方法jsonObject重返Any类型而且扔出极其借使data不可能解析

import Foundation

let data: Data // received from a network request, for example
let json = try? JSONSerialization.jsonObject(with: data, options: [])

json顶层对象一般为字典也许数组,大家能够使用as?+if举办决断调换

// Example JSON with object root:
/*
    {
        "someKey": 42.0,
        "anotherKey": {
            "someNestedKey": true
        }
    }
*/
if let dictionary = jsonWithObjectRoot as? [String: Any] {
    if let number = dictionary["someKey"] as? Double {
        // access individual value in dictionary
    }

    for (key, value) in dictionary {
        // access all key / value pairs in dictionary
    }

    if let nestedDictionary = dictionary["anotherKey"] as? [String: Any] {
        // access nested dictionary values by key
    }
}

// Example JSON with array root:
/*
    [
        "hello", 3, true
    ]
*/
if let array = jsonWithArrayRoot as? [Any] {
    if let firstObject = array.first {
        // access individual object in array
    }

    for object in array {
        // access all objects in array
    }

    for case let string as String in array {
        // access only string values in array
    }
}
用stride 代替 C-style 循环

斯维夫特 3 移除了 C 语言风格的 for 循环:

for var a = -6.28; a <= 6.28; a += 0.1 {
    print(a, separator: " ", terminator: " ")
}

采用stride

for a in stride(from: -6.28, to: 6.28, by: 0.1) { // from ..< to
    print(a, separator: " ", terminator: " ")
}

for x in stride(from: -6.28, through: 6.28, by: 0.1) {  // from ... to
    print(x, separator: " ", terminator: " ")
}

Creating Model Objects from Values Extracted from JSON

假使有个饭馆的model

import Foundation

struct Restaurant {
    enum Meal: String {
        case breakfast, lunch, dinner
    }

    let name: String
    let location: (latitude: Double, longitude: Double)
    let meals: Set<Meal>
}

来自sever的JSON数据

{
    "name": "Caffè Macs",
    "coordinates": {
        "lat": 37.330576,
        "lng": -122.029739
    },
    "meals": ["breakfast", "lunch", "dinner"]
}
@discardableResult 消除再次回到值警告

在Swift 3中,若是措施的重临值未有拍卖xCode会报叁个警戒,借使在艺术前增进@discardableResult
不管理的时候就不会有警示了。也得以用
_ = xxx()
来撤销警告。

Writing an Optional JSON Initializer

extension Restaurant {
    init?(json: [String: Any]) {
        guard let name = json["name"] as? String,
            let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"],
            let mealsJSON = json["meals"] as? [String]
        else {
            return nil
        }

        var meals: Set<Meal> = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                return nil
            }

            meals.insert(meal)
        }

        self.name = name
        self.coordinates = (latitude, longitude)
        self.meals = meals
    }
}
浮点数取余数和除法

在斯威夫特 3中 ,假诺你声澳优(Ausnutria Hyproca)个 let m = 12.0
私下认可m是 Double, Double是不能够和Float做运算的。 CGFloat在32人设备上是
Float32 在陆拾人设备上是 Float64, 所以假若三个 Double 和多少个 Float
做运算时先要转换类型的

let m = 12.0
let n:CGFloat = 19.0
let x = CGFloat(m)/n
let k = m.multiplied(by: Double(n)) // 乘法
let y = m.divided(by: Double(n)) // 除法

唯独取余算法是无法功用于浮点型的,倘若那样就能够报错 CGFloat(m)%n
不错的做法是:

let z = CGFloat(m).truncatingRemainder(dividingBy: n) //取余 12.0

Writing a JSON Initializer with Error Handling

enum SerializationError: Error {
    case missing(String)
    case invalid(String, Any)
}

extension Restaurant {
    init(json: [String: Any]) throws {
        // Extract name
        guard let name = json["name"] as? String else {
            throw SerializationError.missing("name")
        }

        // Extract and validate coordinates
        guard let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"]
        else {
            throw SerializationError.missing("coordinates")
        }

        let coordinates = (latitude, longitude)
        guard case (-90...90, -180...180) = coordinates else {
            throw SerializationError.invalid("coordinates", coordinates)
        }

        // Extract and validate meals
        guard let mealsJSON = json["meals"] as? [String] else {
            throw SerializationError.missing("meals")
        }

        var meals: Set<Meal> = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                throw SerializationError.invalid("meals", string)
            }

            meals.insert(meal)
        }

        // Initialize properties
        self.name = name
        self.coordinates = coordinates
        self.meals = meals
    }
}
AnyObject、 Any

那四个品种都以Swift中很已经出现的项目,可是大家经常应用AnyObject,非常少使用Any。
AnyObject类似于OC中的id类型,表示大肆的class的实例对象,可是在Swift中,比方我们广大的String和Array都改为结构体了,
与此同一时候在Swift3.0中,更加的多的类别大概枚举被写为结构体了,AnyObject的适用范围变相被弱化了,
为此在斯维夫特3.0的API中早就多数AnyOjbect的种类被替换为Any了。

斯威夫特 3.0 和 斯威夫特 2.3 写法相比

事先全部项目为主只用 AnyObject 代表许多实例,基本也不和 Any
有如何交集。因为斯威夫特 2 针对 Int、 String
等结构体实行了改变,编写翻译器会自行桥接为 NSNumber 和 NSString
这种对象类型,在swift3中 AnyObject 无法表示结构体了 。而 Any 能够表示
struct、 class、 func 等差不离全体品种。

那几个改动导致品种相当多地点都要随着改,而且大许多库也做了改造,如Alamofire的参数从
[String:AnyObject]? 变成 [String:Any]?

值得一说的是 Any 能够表示任何可空类型,不用钦赐 Any?

栗子:

let str:String? = "xwwa"
var param:[String:Any] = ["x":1,"code":str]
// ["code": Optional("xwwa"), "x": 1]

str 是二个 Optional 类型的,输出出来也是
Optional。因为大家原先的央求是索要在header中带参数的json机密,换到 Any
怎么都卡住,后来意识有 Optional 值。
此处写了个格局转化了下

func absArray(param:[String:Any])->[String:Any]{ 
    let res = param.map { (key,value) -> (String,Any?) in 
        let newValue = Mirror(reflecting: value) 
        if newValue.displayStyle == Mirror.DisplayStyle.optional{ 
            if let v = newValue.children.first?.value{
                return (key,v) 
            }else{ 
                return (key,nil) 
            }
        } return (key,value) 
    } 
    var newParam:[String:Any] = [:] 
    res.forEach { (key,v) in 
        newParam[key] = v 
    } 
    return newParam
}
print(absArray(param:param))  // ["code": "xwwa", "x": 1]

用了反光决断假诺值是optional就取出他骨子里的值.

Interactive Playgrounds

至于这里能够去看自个儿的简文playground正确行使姿势

Swift 3中 Notification 使用办法

斯维夫特 3.0
中NSNotification和Notification成立时,文告的name参数类型都成为“Notification.Name”类型

Paste_Image.png

extension Notification.Name { 
    static let kNoticeDemo = Notification.Name("xx.xx.ww.ss")
}

class DE{
    func test(){ 
        NotificationCenter.default.post(name:Notification.Name.kNoticeDemo , object: nil) 
        NotificationCenter.default.addObserver(self, selector: #selector(demo), name: Notification.Name.kNoticeDemo, object: nil)
        NotificationCenter.default.removeObserver(self, name: Notification.Name.kNoticeDemo, object: nil) 
    } 

    @objc func demo(){

    }
}

Literals in Playgrounds

Xcode7.1开头帮助字面量,重要用来颜色、图片、文件

自定义操作符

在swift 第22中学自定义操作符

infix operator =~ {
    associativity none 
    precedence 130
}

到现在在斯威夫特 3中如此的话会报告警察方告
Operator should no longer be declared with body;use a precedence group instead

自定义操作符 小名类型

// >>>操作符, 优先级别名
infix operator >>> : ATPrecedence
precedencegroup ATPrecedence { //定义运算符优先级ATPrecedence
    associativity: left 
    higherThan: AdditionPrecedence 
    lowerThan: MultiplicationPrecedence
}

直白钦命操作符的类型,对那一个类型实行定义,

  • associativity: left 代表左结合
  • higherThan 优先级高于 AdditionPrecedence 那个是加法的门类
  • lowerThan 优先级低于 MultiplicationPrecedence 乘除

那边给出常用项目对应的group

infix operator || : LogicalDisjunctionPrecedence
infix operator && : LogicalConjunctionPrecedence
infix operator < : ComparisonPrecedence
infix operator <= : ComparisonPrecedence
infix operator > : ComparisonPrecedence
infix operator >= : ComparisonPrecedence
infix operator == : ComparisonPrecedence
infix operator != : ComparisonPrecedence
infix operator === : ComparisonPrecedence
infix operator !== : ComparisonPrecedence
infix operator ~= : ComparisonPrecedence
infix operator ?? : NilCoalescingPrecedence
infix operator + : AdditionPrecedence
infix operator - : AdditionPrecedence
infix operator &+ : AdditionPrecedence
infix operator &- : AdditionPrecedence
infix operator | : AdditionPrecedence
infix operator ^ : AdditionPrecedence
infix operator * : MultiplicationPrecedence
infix operator / : MultiplicationPrecedence
infix operator % : MultiplicationPrecedence
infix operator &* : MultiplicationPrecedence
infix operator & : MultiplicationPrecedence
infix operator << : BitwiseShiftPrecedence
infix operator >> : BitwiseShiftPrecedence
infix operator ..< : RangeFormationPrecedence
infix operator ... : RangeFormationPrecedence
infix operator *= : AssignmentPrecedence
infix operator /= : AssignmentPrecedence
infix operator %= : AssignmentPrecedence
infix operator += : AssignmentPrecedence
infix operator -= : AssignmentPrecedence
infix operator <<= : AssignmentPrecedence
infix operator >>= : AssignmentPrecedence
infix operator &= : AssignmentPrecedence
infix operator ^= : AssignmentPrecedence
infix operator |= : AssignmentPrecedence

Strings in Swift 2

关于这里能够去看本人的简文您实在懂swift
string吗?

理当如此的施用非常管理,进步代码品质

在平时支出中,大概际遇比比较多非同一般情形,使得程序不可能继续推行下去。有的来自系统语法方面,有的是来自业务方面包车型客车。那时候可以动用自定义非常,在尾部代码中不断throw
在最后一层中去管理。

struct ZError : Error { 
    let domain: String 
    let code: Int
}

func canThrow() throws{ 
    let age = 10 
    if a < 18{ 
        let error = ZError(domain: "xxx", code: 990) 
        throw error 
    }
}

do { 
    try canThrow()
} catch let error as ZError {
    print("Error: \(error.code) - \(error.domain)") // Error: 990 - xxx
}

是时候屏弃前缀的庞大了
先前大家要给 UIView 扩充是这么的

extension UIView { 
    var zz_height:CGFloat{ 
        set(v){ 
            self.frame.size.height = v 
        } 

        get{ 
            return self.frame.size.height 
        } 
    }
}

如此在融洽写的属性后面加一个前缀。然而Swift3出来后更加多的抉择应该是如此的view.zz.height 。 在此以前 kingfisher是
imageView.kf_setImage 将来改成 imageView.kf.setImage 。 SnapKit也改成成了 make.snp.left 之类的语法那么怎么写这么的恢宏呢?

此地看了 KingFisher
的代码,给出他的消除方案。比方大家想写一个UIView的强大。

// 写一个协议 定义一个只读的类型
public protocol UIViewCompatible { 
    associatedtype CompatableType 
    var zz: CompatableType { get }
}

public extension UIViewCompatible { 
    // 指定泛型类型为自身 , 自身是协议 谁实现了此协议就是谁了 
    public var zz: Auto<Self> {
        get { return Auto(self) } // 初始化 传入自己
        set { } 
    }
}

// Auto是一个接受一个泛型类型的结构体
public struct Auto<Base> {
    // 定义该泛型类型属性  
    public let base: Base 
    public init(_ base: Base) {
        self.base = base 
    }
}

// 写一个Auto的扩展 指定泛型类型是UIView 或者其子类
public extension Auto where Base:UIView { 
    var height:CGFloat{ 
        set(v){ 
            self.base.frame.size.height = v 
        } get{ 
            return self.base.frame.size.height 
        } 
    }
}

// 扩展 UIView 实现 UIViewCompatible 协议,就拥有了zz属性 zz又是Auto类型 Auto是用泛型实例化的 这个泛型就是UIView了
extension UIView : UIViewCompatible{
}
// 使用
view.zz.height

地点的笺注已经竭尽详细的表达了这段代码,hope you can understand !

Increasing Performance by Reducing Dynamic Dispatch

swift允许重写超类的不二等秘书技和属性,那就须要在运维时刻接的拜望何况实行直接调用。那么些技艺叫做动态派发,那项技能增添了语言表明的复杂和大量的runtime消耗在直接的利用上。上面介绍两种方法化解动态派发:final、private、WholeModule
Optimization

请看上边包车型地铁代码

class ParticleModel {
    var point = ( 0.0, 0.0 )
    var velocity = 100.0

    func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
    p.update((i * sin(i), i), newV:i*1000)
}

就好像上面写的,编写翻译器发出动态派发调用

  1. 调用p 的 update
  2. 调用p 的 updatePoint
  3. 获得p 的 point元祖属性
  4. 获取p 的 速率

此地使用动态派发的由来在于ParticleModel的子类大概由此可总结属性重写point、velocity,也重写update、updatePonit

动态派发调用的落实是通过寻觅method
table然后推行直接调用。着相对于直接调用的速度必然是慢的。

GCD 的改变

swift 3彻底更改了GCD的运用办法,这里给出平时最基本的多少个

您无需在去用 dispatch_get_main_queue ( ) 来赢得主线程,而是
DispatchQueue . main
,那么要放权主线程的代码怎么实践呢?只要求在线程前面使用 . async { }
即可,也正是说,大约是这么:

DispatchQueue.main.async {
    print("这里在主线程执行")
}

优先级

  • DISPATCH_QUEUE_PRIORITY_HIGH: .userInitiated
  • DISPATCH_QUEUE_PRIORITY_DEFAULT: .default
  • DISPATCH_QUEUE_PRIORITY_LOW: .utility
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND: .background

//global 中设置优先级 不设置默认是 default
DispatchQueue.global(qos: .userInitiated).async {
    print("设置优先级")
}

始建一个行列

let queue = DispatchQueue(label: "im.demo.test")

也能够钦定优先级和队列

let highQueue = DispatchQueue(
    label: "high.demo.test.queue",
    qos: DispatchQoS.background, 
    attributes: DispatchQueue.Attributes.concurrent,
    autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit,
    target: nil
)

highQueue.async { 
    print("ceshi")
}

3秒后试行

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) { 
    print("after")
}

Use final when you know that a declaration does not need to be overridden

final关键字能够范围class、method、property不被重写。能够平安的驱动编写翻译器裁撤动态派发。point、velocity、updatePoint不实行动态派发,直接访问,update举办动态派发

class ParticleModel {
    final var point = ( x: 0.0, y: 0.0 )
    final var velocity = 100.0

    final func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

final修饰类的时候,证明不能够被子类化,由此指明函数、属性都以final

final class ParticleModel {
    var point = ( x: 0.0, y: 0.0 )
    var velocity = 100.0
    // ...
}
根据View查找VC

假设你在三个 UITableViewCell 可能cell上自定义的一个view上想使用这些view所在的vc怎么做? 代理 ? 百多年不遇援引? NO ! 二个增添化解。
一个UIView的扩展

// 查找vc
func responderViewController() -> UIViewController { 
    var responder: UIResponder! = nil 
    var next = self.superview 
    while next != nil { 
        responder = next?.next 
        if (responder!.isKind(of: UIViewController.self)){ 
            return (responder as! UIViewController) 
        } 
        next = next?.superview 
    } 
    return (responder as! UIViewController)
}

记得写在扩展中哦,加上后面包车型客车本领。不论你在哪个view中。只供给如此let vc = view.zz.responderViewController()
就能够得到所处的vc了。
View中的第一响应者
又是二个View的扩大也很好用,上代码

func findFirstResponder()->UIView?{ 
    if self.isFirstResponder{ 
        return self 
    } 
    for subView in self.subviews{ 
        let view = subView.findFirstResponder() 
        if view != nil { 
            return view 
        } 
    } 
    return nil
}

用法同上,这么些东西能干啥啊?
利用那个能够在 NSNotification.Name.UIKeyboardWillShow
文告公告中得到第一响应者,纵然第一响应者是UIText田野(field),能够算出局底下的偏离,给挡墙view做转变。制止被遮盖。何况以那一件事物能够写在研究的暗中同意完结中恐怕
写在二个基类中公用。本文为杂谈不细说了,点到截止咯!

Infer final on declarations referenced in one file by applying the private keyword.

利用private关键字,限制在当下文件内,即便当前文件内并未有对该class的重写,那么编写翻译器就能估量它不适用动态派发

class ParticleModel {
    private var point = ( x: 0.0, y: 0.0 )
    private var velocity = 100.0

    private func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

与final同样,private也足以修饰class

UIViewController 重回是不是出示状态栏的秘籍变化

调节器方法改为属性

Use Whole Module Optimization to infer final on internal declarations.

internal私下认可的访问调节权限评释仅能够在模块可见。swift编写翻译文件是模块独立的,不可能分明internal申明在不一致的公文是还是不是被重写了。可是要是全部模块的优化是翻开的,全体的模块同一时候编写翻译、能够允许编写翻译器将internal估算它的可知性

public class ParticleModel {
    var point = ( x: 0.0, y: 0.0 )
    var velocity = 100.0

    func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
        point = newPoint
        velocity = newVelocity
    }

    public func update(newP: (Double, Double), newV: Double) {
        updatePoint(newP, newVelocity: newV)
    }
}

var p = ParticleModel()
for i in stride(from: 0.0, through: times, by: 1.0) {
    p.update((i * sin(i), i), newV:i*1000)
}
调整器方法改为属性

获取string的字符串长度方法的转移

获得字符串长度参数退换

Nullability and Objective-C

实际上对应的正是可选值

  • !表示非空
  • ?可空
获得沙盒钦点文件夹路线的情势变化

取得文件路线统一交由FileManager来治本

收获沙盒路线参数改动

Swift3.0中selecter的Swift风格化

在斯威夫特2.第22中学,当我们为八个开关增多点击事件时常常那样写:

Swift 2.3 中 Selector写法

Swift 2.3 中 Selector写法

在Swift2.2立异到Swift2.3后能够看来警告告诉大家那是贰个OC风格的写法,提出改为Swift风格的写法。在斯威夫特3.0中两种写法依旧都得以运用,可是提出统一写为Swift风格的,因为您不驾驭什么样时候OC风格的就不被允许了。

Swift 3.0 中 Selector写法

Swift3中字符串管理的改变
//字符串的索引
str = "Hello, Swift"
//str.characters[0] //这是错误的
let startIndex = str.startIndex //str字符串的起始Index, 注意它是Index类型的, 并不是Int类型.
str[startIndex] //"H"
//str[startIndex.advancedBy(5)] //"," //swift2
str[str.index(startIndex, offsetBy: 5)] //"," //swift3

//let spaceIndex = startIndex.advancedBy(6) //6 //swift2
let spaceIndex = str.index(startIndex, offsetBy: 6) //6 //swift3
spaceIndex //6
//str[spaceIndex.predecessor()]  //"," //spaceIndex前一个字符. //swift2
str[str.index(before: spaceIndex)]  //"," //spaceIndex前一个字符. //swift3
//str[spaceIndex.successor()] //"S" spaceIndex后一个字符.
str[str.index(after: spaceIndex)]//"S" spaceIndex后一个字符.

let endIndex = str.endIndex //12 最后一个字符的下标.
//str[endIndex] //下标越界了
//str[endIndex.predecessor()] //用endIndex.predecessor()来表示最后一个字符. //swift2
str[str.index(before: endIndex)] //swift3

str[startIndex..<spaceIndex] //"Hello,"
//let range = startIndex..<spaceIndex.predecessor() //圈定str字符串中的某个区间. //swift2
let range = startIndex..<str.index(before: spaceIndex) // swift3

//str.replaceRange(range, with: "Hi") //用 "Hi" 替换range中的字符串. //swift2
str.replaceSubrange(range, with: "Hi") //swift3

//str.appendContentsOf("123") // "Hi, Swift123" /swift2
str.append("123") //swift3

//str.insert("?", atIndex: str.endIndex) //"Hi, Swift123" //swift2
str.insert("?", at: str.endIndex) //swfit3

//str.removeAtIndex(str.endIndex.predecessor()) //"?" //swift2
str.remove(at: str.index(before: str.endIndex)) //swift3

str //"Hi, Swift123"
//str.removeRange(str.endIndex.advancedBy(-2)..<str.endIndex) //"Hi, Swift1" 删除后两个字符. //swift2
str.removeSubrange(str.index(str.endIndex, offsetBy: -2)..<str.endIndex) //swift3

//str.uppercaseString  //"HI, SWIFT1" //swift2
str.uppercased() //swift3

//str.lowercaseString  //"hi, swift1" //swift2
str.lowercased() //swift3

//str.capitalizedString //"Hi, Swift1" 单词首字母大写 方法 //swift2
str.capitalized //swift3

//str.containsString("Hello") //false //swift2
str.contains("Hello") //swift3

str.hasPrefix("Hi")  //true 是否以"Hi"开头
str.hasSuffix("ft1") //true 是否以"ft1"结束

let p1 = "one third is \(1.0/3.0)" //"one third is 0.333333333333333"
// 使用OC中的NSString 格式化保留两位小数, 并使用as强制转换为Swift的String类型.
let p2:String = NSString(format: "one third is %.2f", 1.0/3.0) as String

var p3:NSString = "one third is 0.33" //声明并赋值一个NSString字符串变量.
//p3.substringFromIndex(4) //NSString截取字符从第4个字符开始. //swift2
p3.substring(from: 4) //swift3

//p3.substringToIndex(3)  //NSString截取字符到第3个字符. //swift2
p3.substring(to: 3) //swift3

//p3.substringWithRange(NSMakeRange(4, 5)) //"third" 4~9 //swift2
p3.substring(with: NSRange(location: 4, length: 5)) //swift3

相关文章