Swift blog《Swifter 100个swift必备的tips》(第二版本)阅读笔记。

by admin on 2018年10月5日

提议读一全勤swift
blog来了解OC与swift不同以及swift版本变动细节

问题

1)柯里化,通过柯里化,改造target-action,因为selector只能以字符串,在编译时无法发现错误,并且不利重构。
2)framework和命名空间中的涉及,写个demo验证一下。
3)对象初始化的过程,如何解决OC中神秘的初始化bug。
http://stackoverflow.com/questions/8056188/should-i-refer-to-self-property-in-the-init-method-with-arc
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html

4)swift能像OC一样动态的摊派方法也? 参见:动态类型及多方式

  1. lazy方法的实现。
    func lazy<S : SequenceType>(s: S) ->
    LazySequence<S>
    func lazy<S : CollectionType where S.Index :
    RandomAccessIndexType>(s: S)
    -> LazyRandomAccessCollection<S>
    func lazy<S : CollectionType where S.Index :
    BidirectionalIndexType>(s: S)
    -> LazyBidirectionalCollection<S>
    func lazy<S : CollectionType where S.Index :
    ForwardIndexType>(s: S)
    -> LazyForwardCollection<S>”

6) 多重Optional具体在仓房中使的景是呀?
7)swift中链表的时间,enum,indirect
8)实例方法的动态调用测试结果跟开及之免均等
9)一个App的开行流程是何许的?
10)GCD 和延时调用, 这同样省之封装没看懂。

11)Comparison of Objective-C Enumeration Techniques
https://www.mikeash.com/pyblog/friday-qa-2010-04-09-comparison-of-objective-c-enumeration-techniques.html
12)R.swift 和 SwiftGen管理资源
13)swift的死去活来机制

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桥接的要而展示转换

1. Swift 新元素

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 { ... }
}

柯里化(currying)

回到一个函数,

柯里化是量产类似措施的好法子,通过柯里化一个计模板,可以免写起多双重道。

Instance Methods are Curried Functions in Swift
https://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/?utm\_campaign=iOS\_Dev\_Weekly\_Issue\_157&utm\_medium=email&utm\_source=iOS%252BDev%252BWeekly

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)

拿 protocol 的措施声明也 mutating

描绘为别人使用的结构体中得考虑添加mutating说明,

当使用 class 来实现带有 mutating
的点子的接口时,具体实现的前头是无欲加 mutating 修饰的,因为 class
可以轻易改变自己的成员变量。所以说于接口里之所以 mutating 修饰方法,对于
class 的贯彻是全透明,可以当做不存在的。

The AnyHashable Type

Any类型可以享有另外类型,但是Dictionary、Set需要Hasble,AnyHashble是swift3提出的hashable的超类,任何一个可hash的档次且落实了Anyhashble协议,比如String、Int

Sequence

现实查看转Array的sequence实现。

GeneratorType 实现 next()-> Element?
的法门。每次调用都回去下一个因素,不可知重置。

SequenceType包含一个Generator的目标。

map, filter, reduce方法是以sequence
基础及,用智扩展实现之。它们一旦会挨个编排容器类就可了。

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的商谈

多元组 (Tuple)

交换值的新写法

返多只价值

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
}

@autoclosure和??

1)阅读更清楚

2)节省开销,如果无是闭包,在defaultValue传值的时段会被求值一赖,这个是未曾必要地。

Optional Chaining
optional chaining 返回的定是一个optional值

Swift Value Types in Objective-C

Any可以有所另外的结构体、枚举、元组或者其他的色,OC的id在swift3等价于any,在swift2中得手动封箱或者转入类,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可能会见桥接到固定类型

操作符

Working with JSON in Swift

JSONSerialization Foundation framework

fun的参数修饰

参数是let属性,不可知看做var来运
若果运用inout,传参时需要为此&的艺术。

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
    }
}

字面量转换

一定的门类实现这些协议,将这些字面量转化为项目的值

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"]
}

下标

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
    }
}

道嵌套

措施现在是均等顶百姓,可以看作参数,返回值,也足以于措施吃定义方法。这些子方只有以眼前方式外立竿见影。

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
    }
}

命名空间

了解framework

Interactive Playgrounds

有关此可以错过押本身之简文playground正确运用姿势

Any和Any Object

id和Any object的区别

Literals in Playgrounds

Xcode7.1开始支持字面量,主要用来颜色、图片、文件

typeelias和泛型接口

Strings in Swift 2

关于此可以去看自己之简文君真的懂swift
string吗?

可是转换参数函数

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然后实施间接调用。着相对于直接调用的快自然是慢的。

初始化方法的次第

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
    // ...
}

担保安全的初始化。

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

Designated,Convenience 和 Required

当 Objective-C 中,init 方法是挺勿安全的:没有人会管 init
只为调用一不好,也没有人担保在初始化方法调用以后实例的各个变量都完成初始化,甚至只要当初始化里应用性能进行安装的话,还可能会见招致各种问题,虽然
Apple 也肯定说明了无该当 init
中采用属性来访问,但是及时并无是编译器强制的,因此要会产生诸多开发者犯这样的谬误。

故而 Swift 有了顶尖严格的初始化方法。一方面,Swift 强化了 designated
初始化方法的位置。Swift 中无加修饰的 init 方法还需在章程中管所有非
Optional 的实例变量被赋值初始化,而在子类中呢强制 (显式或者隐式地) 调用
super 版本的 designated
初始化,所以无论如何走何种路线,被初始化的目标总是可以好

因此开展一下总,可以望初始化方法永远以以下简单个规格:

  • 初始化路径必须管对象了初始化,这可以通过调用本类型的 designated
    初始化方法来收获保证;
  • 子类的 designated 初始化方法必须调用父类的 designated
    方法,以保父类也做到初始化。

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)
}

初始化返回 nil

怀有的结果尚且将凡 Int? 类型,通过 Optional
Binding,我们不怕能够清楚初始化是否中标,并安全地应用其了。我们当马上类初始化方法被尚得对
self 进行赋值,也总算 init 方法里之特权之一。

Nullability and Objective-C

实则对应的即使是不过选值

  • !表示非空
  • ?可空

protocol 组合

Any的定义 protocol<>
AnyObject的定义?

除外可以便宜地发表空接口这同样概念外,protocol
的构成相比之下叫新创一个接口的极端可怜分别就是在于那匿名性。

static 和 class

当档次的概念属性时,只能采用static,
每当概念类型的法门时,enum,struct 只能用static,
类里面可以使static,也得使class

多类型和容器

以容器类使用protocol,这样虽可知存储不同的

default 参数

默认参数没有不得不是终极一个参数的限制,因为swift的艺术调用可以指定调用时不传染哪些参数

func NSLocalizedString(key: String, tableName: String? = default, bundle: NSBundle = default, value: String = default, comment: String) -> String

func assert(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = default, file: StaticString = default, line: UWord = default)

正则表达式

正则表达式30分钟入门教程

模式匹配

… 和 ..<

“不难窥见,其实这几个章程还是支持泛型的。除了我们常常因此之输入 Int 或者
Double,返回一个 Range 以外,这个操作符还有一个奉 Comparable
的输入,并返回 ClosedInterval 或 HalfOpenInterval 的重载。在 Swift
中,除了数字外另一个兑现了 Comparable 的基本类型就是
String。也就是说,我们好透过 … 或者 ..<
来连接两单字符串。一个广泛的运用状况就是是反省有字符是否是官的字符。比如想确认一个单词里之上上下下字符都是聊写英文字母的言语,可以这么做:”

AnyClass,元型以及 .self

typealias AnyClass = AnyObject.Type

骨子里在 Swift 中,.self
可以就此当项目后面取得类型我,也足以用在某个实例后面取得这个实例本身。前一模一样种艺术好为此来抱一个意味着该型的价值,这在少数时候会坏有因此;而后人为将到的实例本身,所以暂时似乎并未最好多得这么使用的案例。

self.tableView.registerClass( UITableViewCell.self, forCellReuseIdentifier: "myCell”)

元编程,

通过安排文件初始化

接口和类方法中之 Self

“但是当这种气象下,Self
不仅替的是兑现该接口的门类我,也包括了是类型的子类。从概念上来说,Self
十分简短,但是事实上落实一个这样的法子可稍微要反个转移”

动态类型和多措施

Swift 中我们则可经 dynamicType 来赢得一个靶的动态类型
(也尽管是运行时之实在类型,而不代码指定要编译器看到的门类)。但是以运用着,Swift
现在也是免支持多计的,也就是说,不可知因目标在动态时的种进行适当的重载方法调用。”
(编译时规定调用哪个方法?)

性能观察

初始化方法对性能的设定,以及当 willSet 和 didSet
中针对性能的重设定都无会见更触发属性观察的调用,一般的话就会是你所急需之所作所为,可以放心使用能够。

特性观察 (Property Observers) 是 Swift
中一个分外特别之特色,利用性观察我们得以当此时此刻型内监视对于性之设定,并作出有响应。Swift
中呢咱提供了少数独特性观察的法门,它们各自是 willSet 和 didSet。”

final

final 关键字可以据此当 class,func 或者 var
前面进行修饰,表示未允对拖欠内容开展继续或重写操作”

“一般的话,不盼吃接续和重写会发生就几乎栽情景:

类似或措施的功力实在已全了”
“子类继承和改是均等宗危险的工作”
“为了父类中某些代码一定会给执行”

lazy 修饰符和 lazy 方法

lazy属性的实现, 代码块(闭包)的调用 {}(), lazy方法的贯彻。
func lazy<S : SequenceType>(s: S) -> LazySequence<S> func lazy<S : CollectionType where S.Index : RandomAccessIndexType>(s: S) -> LazyRandomAccessCollection<S> func lazy<S : CollectionType where S.Index : BidirectionalIndexType>(s: S) -> LazyBidirectionalCollection<S> func lazy<S : CollectionType where S.Index : ForwardIndexType>(s: S) -> LazyForwardCollection<S>

Reflection 和 Mirror

swift这个力量还是很死了,只能读取值,不克设置值,不可知和OC的周转时相比

隐式解包 Optional

除去以IB中,其它地方慎用。

多重 Optional

具体于库房使用的场景也?

Optional Map

Protocol Extension

商量扩展里心想事成了某个方法,类实现里为落实了有方法。

重整一下息息相关的规则的语:

一经类型推断得到的凡实际上的色
那类型受到的实现用于调用;如果类型中绝非实现的话,那么接口扩展中之默认实现用受应用
倘若类型推断得到的是接口,而未是实际类型
而方法以接口中进行了定义,那么类型中之兑现用给调用;如果类型受到从来不落实,那么接口扩展中之默认实现叫采取
再不 (也尽管是办法无当接口中定义),扩展中之默认实现用于调用”

where 和模式匹配

1)应用被switch case, if, for,可以使if代替
2)应用叫泛型限制

本着self做更限制,如果非信守Comparable协议,就非克调用sort方法,在编译时限制
extension SequenceType where Self.Generator.Element : Comparable {
public func sort() -> [Self.Generator.Element]
}

indirect 和嵌套 enum

2. 从 Objective-C/C 到 Swift

Selector

Swift 里对应原本 SEL 的品种是一个名叫 Selector 的结构体。

let someMethod = #selector(callMe) let anotherMethod = #selector(callMeWithParam(_:))

末尾用留意的是,selector 其实是 Objective-C runtime 的定义,如果你的
selector 对应之方式只有以 Swift 中可见的话 (也就是说它是一个 Swift 中之
private 方法),在调用这个 selector 时若会碰到一个 unrecognized selector
错误,正确的做法是在 private 前面加上 @objc
关键字,这样运行时虽会找到呼应的章程了。”

实例方法的动态调用

Swift 中可一直用 Type.instanceMethod
的语法来特别成一个方可柯里化的措施。

单例

“在 Swift 1.2
以及下,如果无专门的要求,我们引进使用下这样的方法来写一个单例:

class MyManager { static let sharedInstance = MyManager() private init() {} }
这种写法不仅简单,而且保证了单例的绝世。在初始化类变量的时候,Apple
将会见将这个初始化包装在同样不好 swift_once_block_invoke
中,以保它们的唯一性。另外,我们以此类别受到入了一个民用的初始化方法,来罩默认的公开初始化方法,这被项目被之其它地方不克透过
init 来转自己的 MyManager
实例,也保了品种单例的唯一性。如果你待的凡近似 defaultManager
的样式之单例 (也就是说这个近乎的使用者可以创造好之实例)
的言辞,可以去丢这私有的 init 方法。”

极编译

swift不支持宏,编译标记需要以 swift compiler -> Custom Flags 加上 -D
标记

编译标记
//MARK: //TODO: //FIXME:
小还非支持
//WARNING:

@UIApplicationMain

“这个标签做的作业虽是拿让标的类似作为委托,去创造一个 UIApplication
并启动全套程序。在编译的早晚,编译器将寻找这个符号的近乎,并自行插入像
main 函数这样的模版代码。我们得以尝试看将 @UIApplicationMain
去丢会什么:

Undefined symbols _main

证找不交 main 函数了。

于形似景象下,我们并不需要对斯标签做其他改动,但是当我们而想如果动用
UIApplication 的子类而不是其自己的语句,我们虽用对当下有的情 “做点动作”
了。

刚刚说交,其实 Swift 的 app 也是得 main 函数的,只不过默认情况下是
@UIApplicationMain 帮助我们自动生成了而已。和 C 系语言的 main.c 或者
main.m 文件一律,Swift 项目为得以起一个“名也 main.swift
特殊的文件。在这个文件中,我们无需定义作用域,而可直接写代码。这个文件中之代码用用作
main 函数来实施。比如我们在剔除 @UIApplicationMain 后,在项目被上加一个
main.swift 文件,然后加上如此的代码:

UIApplicationMain(Process.argc, Process.unsafeArgv, nil,
NSStringFromClass(AppDelegate))
现今编译运行,就非会见重复冒出谬误了。”
(监事应用的轩然大波)

@objc 和 dynamic

swift和OC之间的互操作

swift调用OC
透过添加 {product-module-name}-Bridging-Header.h
文件,并当里边填写想只要采取的条文件名称,我们尽管足以老容易地于 Swift
中以 Objective-C 代码了

“Objective-C 和 Swift 在底部以的凡鲜仿了不同之建制,Cocoa 中之
Objective-C 对象是依据运行时之,它自从龙骨里仍了 KVC (Key-Value
Coding,通过类似字典的主意囤对象信息) 以及动态派发 (Dynamic
Dispatch,在运作调用时更决定实际上调用的具体贯彻)。而 Swift
为了追求性,如果没新鲜需要的话,是无见面当运行时再也来决定这些的。也就是说,Swift
类型的积极分子要措施以编译时就既控制,而运行时便不再用经同不行找,而足直接运用。”

“显而易见,这带来的问题是若我们设动 Objective-C
的代码或者特性来调用纯 Swift
的门类上,我们会盖找不至所需要之这些运行时信息,而造成失败。解决起来也坏简单,在
Swift 类型文件被,我们得以以索要暴露被 Objective-C 使用的另地方
(包括类,属性和方等) 的扬言前加上 @objc
修饰符。注意是手续只需要针对那些无是连续自 NSObject 的类别进行,如果你用
Swift 写的 class 是继承自 NSObject 的说话,Swift 会默认自动吗具有的非
private 的近乎与分子加上 @objc。这就是说,对一个 NSObject
的子类,你一味待导入相应的条文件就好在 Objective-C 里下这个仿佛了。”

“@objc 修饰符的其余一个作用是为 Objective-C
侧重新声明方法或者变量的名。虽然多方时自动转换的法门名曾经足够好用
(比如会将 Swift 中接近 init(name: String) 的方易成为
-initWithName:(NSString *)name 这样),但是有时我们还是要
Objective-C 里采取与 Swift 中无同等的艺术名或者类的名字,”

可选接口及接口扩展

原生的 Swift protocol
里没有但选,所有定义的点子还是必兑现之。如果我们怀念使如 Objective-C
里那样定义可选取的接口方法,就需以接口本身定义为 Objective-C 的,也就于
protocol 定义之前增长 @objc。另外和 Objective-C 中的 @optional
不同,我们运用无 @ 符号的要字 optional 来定义可选取方式:

@objc protocol OptionalProtocol {
optional func optionalMethod()
}

一个不可避免的界定是,使用 @objc 修饰的 protocol 就只好吃 class
实现了,也就是说,对于 struct 和 enum
类型,我们是无法让她所实现之接口中蕴含可选方法或者性质的。另外,实现其的
class 中的法还必须为深受标为 @objc,或者全体类即是延续自
NSObject。这对准咱形容代码来说是平栽十分让人口烦躁的范围。

每当swift中落实接口可卜的方法是通过protocol extension的法子。

内存管理,weak 和 unowned

weak和unowned的区别

如果我们得规定于全路经过遭到 self 不会被释放吧,我们可以方面的 weak
改呢 unowned,这样即便不再要 strongSelf 的论断。但是若以过程遭到 self
被放出了而 printName 这个闭包没有吃放走的话 (比如 生成 Person
后,某个外部变量持有了 printName,随后此 Persone 对象被释放了,但是
printName 已然是并可能为调用),使用 unowned
将致倒。在此间我们要根据实际的需来决定是使用 weak 还是 unowned。

@autoreleasepool

值类型和援类型

String 还是 NSString

UnsafePointer

C 指针内存管理

COpaquePointer 和 C convention

GCD 与延时调用

得到对象类型

透过dynamicType方法,进一步运用与否?

自省

而是继续自NSObject类,可以据此isKindOfClass, isMemberOfClass判断,
当swift里可以就此is判断,is可以用来枚举,结构体和好像

KVO

唯其如此用于后续自NSObject的类似,
设想用reactiveCocoa swift版本?(好好研究一下)

局部 scope

C语言用少单{}来包裹代码段,swift因为同闭包的冲,不可知直接这样用。

用 do
do {
let textLabel = UILabel(frame: CGRectMake(150, 80, 20, 40))
//…
}

匿名闭包

titleLabel = {
let label = UILabel(frame: CGRectMake(150, 30, 20, 40))

return label

}()

判等

swift中 == Equatable接口里之道。注意的凡, func
放在全局,因为要是对准全局生效。事实上,swfit的操作符都是全局的

protocol Equatable { func ==(lhs: Self, rhs: Self) -> Bool }

class TodoItem { let uuid: String var title: String

init(uuid: String, title: String) { self.uuid = uuid self.title = title } }

extension TodoItem: Equatable { }

func ==(lhs: TodoItem, rhs: TodoItem) -> Bool { return lhs.uuid == rhs.uuid }

于原 Objective-C 中采取 == 进行的靶子指针的判断,在 Swift
中提供的是外一个操作符 ===。在 Swift 中 === 只来平等种植重载:

func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
它们用来判断两单 AnyObject 是否是和一个援。

哈希

protocol Hashable : Equatable { var hashValue: Int { get } }

于哈希值,另一个特地要提出的凡,除非我们正在开发一个哈希散列的数据结构,否则我们无应直接依赖系统所实现的哈希值来举行其他操作。首先哈希的定义是只为的,对于当的靶子要值,我们好期待它持有一致的哈希,但是转头并不一定成立。其次,某些对象的哈希值有或随着系统环境或时间之变而改。因此而也未应借助让哈希值来构建有急需规定目标唯一性的力量,在多方面情形下,你拿会获得错误的结果。

类簇

OC中的实现,
于 Objective-C 中,init
开头的初始化方法虽然从在初始化的称号,但是实际做的作业与其它艺术并从未最好多不同之处。类簇以
Objective-C 中实现起来呢够呛当然,在所谓的“初始化方法”中将 self
进行调换,根据调用的道要输入的档次,返回合适的村办子类对象就是可以了。

然 Swift 中之动静有所不同。因为 Swift
拥有真正的初始化方法,在初始化的上咱们只好获取时接近的实例,并且使就所有的配置。也就是说对于一个公共类来说,是勿可能以初始化方法被归其子类的信的。对于
Swift 中
的类簇构建,一栽中的道是应用工厂方法来进行。例如下面的代码通过
Drinking 的厂方法以可乐和啤酒两只私有类进行了仿佛簇化

运用工程,积累提供一个像样方式作为工厂方法。

Swizzle

swift借助OC运行时落实。
SWRoute (了解一下原理)
https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift

调用 C 动态库

输出格式化

一经用制订类似小数点后几乎位,借助NSString的format方法来实现。

Options

oc里的NSOptions被转正为OptionSetType的档次,

public struct UIViewAnimationOptions : OptionSetType {
public init(rawValue: UInt)
static var LayoutSubviews: UIViewAnimationOptions { get }
static var AllowUserInteraction: UIViewAnimationOptions { get }

//...

static var TransitionFlipFromBottom: UIViewAnimationOptions { get }

}

OptionSetType 是实现了 SetAlgebraType
的,因此我们得以本着少数单集聚进行各种集合运算,包括并集 (union)、交集
(intersect) 等等。另外,对于无欲选择项输入的状况,也就算是针对性诺原的
kNilOptions,现在咱们一直采用一个缺损的集合 [] 来表示:

数组 enumerate

以 Objective-C 中极其方便之主意是应用 NSArray 的
enumerateObjectsUsingBlock: 方法

当 Swift
中,我们以遇见这么的急需的当儿,有一个频率,安全性与可读性都十分好之替代,那就算是快速枚举某个数组的
EnumerateGenerator,它的素是还要含有了元素下标索引以及元素本身的多元组:

var result = 0 for (idx, num) in [1,2,3,4,5].enumerate() { result += num if idx == 2 { break } } print(result)

花色编码 @encode

C 代码调用和 @asmname

于导入Darwin的时刻,swfit会自动开类型转换。通过桥接头文件之点子在swift中引用C函数。

也堪由此asmname来指定名称。
“//File.swift
//将 C 的 test 方法映射为 Swift 的 c_test 方法
@asmname(“test”) func c_test(a: Int32) -> Int32

sizeof 和 sizeofValue

//sifeof 3.0 sizeof不能使用了 MemoryLayout<String>.size MemoryLayout.size(ofValue: "abcd")

delegate weak delegate

protocol MyClassDelegate { func method() }

class MyClass { weak var delegate: MyClassDelegate? }

// weak var delegate: MyClassDelegate? 编译错误 // 'weak' cannot be applied to non-class type 'MyClassDelegate”

为ARC的weak属性只能用来Class类型,不能够用来枚举和Struct,可以通过动用@objc,或者
protocol MyClassDelegate: class 来实现。推荐应用后者。

Associated Object

swift中为会使OC运行时之功效,接口有接触不等同。

func objc_getAssociatedObject(object: AnyObject!, key: UnsafePointer<Void> ) -> AnyObject!

func objc_setAssociatedObject(object: AnyObject!, key: UnsafePointer<Void>, value: AnyObject!, policy: objc_AssociationPolicy)

Lock

@synchronized 虽然此主意很简短好用,但是生丧气之凡在 Swift 中它已经
(或者是临时) 不设有了。其实 @synchronized 在骨子里做的工作是调用了
objc_sync 中的 objc_sync_enter 和 objc_sync_exit
方法,并且在了片死判断。因此,在 Swift
中,如果我们忽略掉那些可怜的语,我们怀念如果 lock 一个变量的话,可以这样形容:

func myMethod(anObj: AnyObject!) { objc_sync_enter(anObj) // 在 enter 和 exit 之间 anObj 不会被其他线程改变 objc_sync_exit(anObj) }

再也进一步,如果我们喜欢以前的那种样式,甚至足以写一个大局的法子,并受一个闭包,来拿
objc_sync_enter 和 objc_sync_exit 封装起:

func synchronized(lock: AnyObject, closure: () -> ()) { objc_sync_enter(lock) closure() objc_sync_exit(lock) }

Toll-Free Bridging 和 Unmanaged

3. Swift 与出环境以及部分实施

Swift 命令行工具

可以像脚本语言一样实行swift

自由数变化

眼看是错误代码

let diceFaceCount = 6 let randomRoll = Int(arc4random()) % diceFaceCount + 1 print(randomRoll)

Swift 的 Int 是与 CPU 架构有关的:在 32 位的 CPU 上 (也尽管是 iPhone 5
跟先行者们),实际上它们是 Int32,而以 64 位 CPU (iPhone 5s 及其后的机型)
上是 Int64。arc4random 所返的值不论在什么平台达成还是一个 UInt32,于是当
32 位的平台上虽来一半几乎带领在进行 Int
转换时越界,时不时的倒台也即欠缺为惊讶了。

这种情形下,一栽相对安全之做法是应用一个 arc4random 的改进版:

func arc4random_uniform(_: UInt32) -> UInt32
夫改良版接受一个 UInt32 的数字 n 作为输入,将结果归一化到 0 到 n – 1
期间。只要我们的输入不跳 Int 的限量,就可以避危险的换:

let diceFaceCount: UInt32 = 6 let randomRoll = Int(arc4random_uniform(diceFaceCount)) + 1 print(randomRoll)

超级实践当然是吧创建一个 Range
的随机数之法,这样我们即便能够于随后好易地复用,甚至设计类与
Randomable 这样的接口了:

func randomInRange(range: Range<Int>) -> Int { let count = UInt32(range.endIndex - range.startIndex) return Int(arc4random_uniform(count)) + range.startIndex }

for _ in 0...100 { print(randomInRange(1...6)) }

print 和 debugPrint

每当extension中实现CustomStringConvertible这个协议

张冠李戴与特别处理

死和不当的别
“Swift
现在底不可开交机制吗并无是十备十怡然自得的。最酷的题材是种安全,不指文档的话,我们现在是无法从代码中直接得知所摒弃来底充分的品种的。”

于是,在 Swift 2 一代中的错误处理,现在一般的超级实践是于同 API
使用非常机制,对于异步 API 使用泛型枚举。

有关 try 和 throws,想再度多谈点儿单小点。首先,try 可以接 !
表示强制执行,这表示你规定知道这次调整用无见面丢掉来怪。如果在调用中冒出了十分的口舌,你的程序用会见倒,这同我们当针对
Optional 值用 ! 进行强制解包时之行为是相同的。另外,我们吧足以当 try
后面长 ? 来开展尝试性的运转。try? 会返回一个 Optional
值:如果运行成功,没有弃来荒谬的讲话,它见面蕴藏这长达告句子之回值,否则将为
nil。和另返回 Optional 的章程类似,一个一流的 try? 的使用场景是暨 if
let 这样的讲话搭配使用,不过假如您用了 try?
的口舌,就意味着你冷淡了错的求实品种:

“值得一提的凡,在一个可以 throw 的法里,我们祖祖辈辈不应有回到一个
Optional 的价。因为成 try? 使用以来,这个 Optional
的回值将受再卷入一样交汇 Optional,使用这种又 Optional
的价非常容易产生错误,也甚让丁迷惑 (详细而参见多又 Optional 的内容)。

断言

func assert(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = default, file: StaticString = default, line: UInt = default)

对诺 target 的 Build Settings 中,我们在 Swift Compiler – Custom Flags
中之 Other Swift Flags 中上加 -assert-config Debug 来强制启用断言,或者
-assert-config Release
来强制禁用断言。当然,除非有充足的说辞,否则连无建议做这么的改。如果我们需要以
Release 发布时当无法继续时将先后强行终止的语,应该选使用 fatalError。

fatalError

于调试时我们得以断言来排遣类似这样的题目,但是断言只会以 Debug
环境遭受有效,而于 Release
编译中持有的断言都将给剥夺。在撞真正因为输入的错无法要程序继续运行的早晚,我们一般考虑以有致命错误
(fatalError) 的法子来已程序。

@noreturn func fatalError(@autoclosure message: () -> String = default, file: StaticString = default, line: UInt = default)
至于语法,唯一要待说明的是
@noreturn,这表示调用这个点子的言语可以不再要回到值,因为程序整个都以停止。这足以助编译器进行局部检查,比如在某些需要返回值的
switch 语句被,我们仅仅盼被 switch
的情以某些范围外,那么我们在可于未属这些限制的 default 块里一直写
fatalError 而不再需要指定返回值:

代码组织及 Framework

但倘若特别指出,虽然同 Apple 的框架的晚缀名一样是
.framework,使用方法啊接近,但是这些第三正值框架都是不容置疑的静态库,每个
app 需要以编译的时进行单独地链接。

framework的打和援

有惊无险之资源集团办法

应用字符串指定资源名称的题材。
OC中可由此宏来制定文件名称。

“在 Swift 中凡是没宏定义的,取而代之,我们得以活地使 rawValue 为
String 的 enum 类型来字符串,然后经过为资源类型添加合适的 extension
来叫编译器帮助我们当资源名称修改时能够在代码中当对应之转。

enum ImageName: String { case MyImage = "my_image" }

enum SegueName: String { case MySegue = "my_segue" }

extension UIImage { convenience init!(imageName: ImageName) { self.init(named: imageName.rawValue) } }

extension UIViewController { func performSegueWithSegueName(segueName: SegueName, sender: AnyObject?) { performSegueWithIdentifier(segueName.rawValue, sender: sender) } }

但是以 Swift 中,根据项目内容来自动化生成像是 ImageName 和 SegueName
这样的档次并无是相同桩难事。Swift
社区中本吗来部分比成熟之自动化工具了,R.swift 和 SwiftGen
就是内的高明。

Playground 延时运行

以使 Playground 具有延时运行的本领,我们得引入 Playground 的
“扩展包” XCPlayground 框架。现在者框架中寓了几个和 Playground
的行相和控制 Playground 特性的 API,其中便包括要 Playground
能延时执行之地下魔法,XCPlaygroundPage 和 needsIndefiniteExecution。

咱们一味需要在方底代码上面长:

import XCPlayground XCPlaygroundPage.currentPage.needsIndefiniteExecution = true //swift 3.0中,这个属性已经不推荐使用了

默认时间是30秒, 但是使你想更改这时刻的话,可以经 Alt + Cmd + 回车
来打开辅助编辑器。在此处您会相控制高出口和时间轴,将右侧下角的 30
改成为你想只要之数字,就可以对延时运行的卓绝丰富日子进行设定了。

Playground 与品种合作

可以于列面临动用

数学及数字

NAN: Not a Number

JSON

最好老的题目在于我们为了保项目的正确,做了极致多之变换和判断。我们并不曾应用一个使得的
JSON
容器总该是字典或者数组这个有效的表征,而致使每次用下标取得的值都是需要更换的
AnyObject。如果我们会重载下标的话,就得经下标的取值配合 Array 和
Dictionay 的 Optional Binding 来大概地当 JSON
中取值。鉴于篇幅,我们在此处不给有切实的贯彻。感兴趣之读者可倒看看
json-swift 或者 SwiftyJSON
这样的档次,它就是下了重载下标访问的法简化了 JSON
操作。使用这家伙,上面的看可以简化为底的项目安全的典范:

// 使用 SwiftJSON
if let value =
JSON(json)[“menu”][“popup”][“menuitem”][0][“value”].string {
print(value)
}

这样即便简单多了。

NSNull

文档注释

性考虑

Log 输出

func printLog<T>(message: T,
                    file: String = #file,
                  method: String = #function,
                    line: Int = #line)
{
  #if DEBUG
    print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
   #endif
}

乍本子的 LLVM
编译器在撞这个拖欠方法时,甚至会见直接拿此点子漫天去丢,完全不失去调整用她,从而实现零资金。

溢出

苟我们怀念如果另外编程语言那样的针对溢起处理温柔一些,不是受程序崩溃,而是略地于高位截断的话,可以用涌起处理的运算符,在
Swift 中,我们得使以下即五独带有 & 的操作符,这样 Swift
就见面忽视掉溢起之错:

漫起加法 (&+)
漫起减法 (&-)
泛滥起乘法 (&*)
泛滥起除了法 (&/)
漫起要模 (&%)

宏定义 define

性能访问控制

public class MyClass {
public private(set) var name: String?
}

Swift 中之测试

@testable

Core Data

闭包歧义

“为了提高可读性和安全性,最直白是以调用时尽量指明闭包参数的档次。

泛型扩展

俺们无可知由此扩大来再定义当前曾有些泛型符号,但是足以本着其展开以;在扩展中吗不可知啊夫类型丰富泛型符号;但若名字不冲突,我们是得于初声明的主意被定义跟利用初的泛型符号的。

兼容性

Apple 通过以一个最好小化的运行库集成打包到 app
中这样的方法来解决兼容性的题目。使用了 Swift 语言的类别在编译时见面于 app
包中涵盖这同一模仿运行时环境,并在起步时加载这些 dylib 包作为 Swift
代码的运作环境。这些库文件在打包好的 app 的 Frameworks 文件夹着:
然带的利有半点碰。首先是虽然 Swift 语言在不断变更,但是若的 app
不论在什么样的系版本及都好保障与付出编译时的所作所为等同,因为您因的
Swift 运行时是和 app 绑定的。这对于保证 Swift 升级后乍本子的 app
在原有的设施以及网上运行正常化是必不可少之。
其余一个利是向下兼容。虽然 Swift 是与 iOS 8 及 OSX 10.10
一同推出的,但是通过加载 Swift 的动态库,Apple 允许 Swift 开发之 app 在
iOS 7 和 OSX 10.9 上啊能运行,这对准 Swift
的赶快推广以及下呢是坏根本之。

列举 enum 类型

(不太懂)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图