三日上手swift(最后一天)会陆续更新到项目

本swift教程并不是教大家如何如何玩转一门语言,是让大家快速看懂别人swfit的项目,最后加上强大的复制粘贴和万能的google,用一种相对极端的方法快速入门做项目



重复说明,我的写代码,大家千万不要拿去敲(谁敲谁傻b),太浪费时间和消磨积极性,只需要根据代码板块复制粘贴到playground上看(不知道的看上一篇文章), 一块一块看比较有效率 ,特别要看打印结果,然后可以自己根据思路写上注释,如果遇到报错,可能是你复制粘贴代码导致重复定义,也可能是xcode的问题,细节不用太在意,主要了解语法结构!

重点到最后一章我会上传一个小项目让你大家来敲一遍,敲到不懂的回来看即可!


循环引用
import UIKit

class Person {
    var book : Book?

    deinit {
        print("Person -- 销毁")
    }
}

class Book {
    weak var owner : Person?//解决循环引用,指向的对象销毁时,会自动指向nil,所用用Var(因为可选类型)

    deinit {
        print("Book -- 销毁")
    }
}

var p : Person? = Person()
var b : Book? = Book()

p!.book = b
b!.owner = p

p = nil
b = nil
可选链

可选链的使用:赋值、取值、调用方法,里面系统会自己判断可选类型,且进行

解绑
赋值:
person.dog?.toy?.price = 50
取值:
let price = person.dog?.toy?.price
调用方法
person.dog?.toy?.flying()
import UIKit

// 1.声明类
class Person {
    var name : String = ""
    var dog : Dog?
}

class Dog {
    var weight : Double = 0.0
    var toy : Toy?
}

class Toy {
    var price : Double = 0.0

    func flying() {
        print("飞盘在flying")
    }
}

// 2.创建类对应的对象
let person = Person()
person.name = "Kobe"

let dog = Dog()
dog.weight = 30.0

let toy = Toy()
toy.price = 100.0

// 3.让三个对象之间产生关系
person.dog = dog
dog.toy = toy

// 4.可选链的使用
// 4.1.将person的dog的toy的价格修改成50
// 给可选链进行赋值
// person.dog!.toy!.price = 50 太危险
/* 太麻烦
if let dog = person.dog {
    if let toy = dog.toy {
        toy.price = 50
    }
}
 */
person.dog?.toy?.price = 50

// 4.2.取出person的dog的toy的价格
// 从可选链取值 : 从可选链中取值取到的类型一定是一个可选类型
//let price = person.dog!.toy!.price
/*
if let dog = person.dog {
    if let toy = dog.toy {
        let price = toy.price
    }
}
 */
let price = person.dog?.toy?.price

// 4.3.让person的dog的toy的飞起来
// 可选链调用方法 : 系统会自动判断可选类型是否有值
// person.dog!.toy!.flying()
person.dog?.toy?.flying()

协议:

用协议来实现多继承,但oc、swift本事不支持多继承

// 1.如何定义协议
protocol SportProtocol {
    func playBasketball()
    func playFootball()
}

// 2.声明类, 并且遵守协议
class Person : SportProtocol {
    var name : String = ""

    func playBasketball() {
        print("打篮球")
    }

    func playFootball() {
        print("踢足球")
    }
}

//逗号分隔遵守多个协议
class Dog : NSObject, SportProtocol {
    func playBasketball() {
        print("打篮球")
    }

    func playFootball() {
        print("踢足球")
    }
}
基协议
import UIKit

// NSObjectProtocol : Swift中基协议

protocol CrazySportProtocol : NSObjectProtocol {
    func jumping()
}

protocol SportProtocol : CrazySportProtocol {
    func playBasketball()
}

class Person: NSObject, SportProtocol {
    func playBasketball() {
        print("打篮球")
    }

    func jumping() {
        print("蹦极")
    }
}

@objc : 可以保留OC某些特性
import UIKit

// @objc : 可以保留OC某些特性(可选性)
@objc protocol SportProtocol {
    func playBasketball()
    func playFootball()

    optional func jumping()
}

class Person: SportProtocol {
    @objc func playBasketball() {

    }

    @objc func playFootball() {

    }

    @objc func jumping() {

    }
}
协议在设计代理模式中的应用
import UIKit

// 1.定义协议 : 规范
// class --> 该协议只能被类遵守

protocol BuyTicketDelegate : class {
    func buyTicket() -> String
}

// 2.定义类, 并且有一个去北京的行为
class Person {
    var name : String = ""
    weak var delegate : BuyTicketDelegate?

    func goToBeijing() {

        // print("买火车票")
        // 让代理帮你买票
        let ticket = delegate?.buyTicket()
        print(ticket)

        print("坐火车去北京")
    }
}

// 3.创建对象
let p = Person()
p.name = "Kobe"

// 4.定义其他类, 遵守协议, 并且有买票的行为
class YellowCatte : BuyTicketDelegate {
    func buyTicket() -> String {
        return "从广州到北京的高铁"
    }
}

class Student: BuyTicketDelegate {
    func buyTicket() -> String {
        return "帮助同学买了一张票"
    }
}

// 5.创建具体的对象,成为person的代理
let huangNiu = YellowCatte()
p.delegate = huangNiu

// 6.去北京
p.goToBeijing()

闭包(其实就是oc中的block)

基本写法:(参数列表)-> (返回值类型)

建一个HttpTools类,内部如下

import UIKit

class HttpTools {
    // (参数列表) -> (返回值类型)
    func loadData(finishedCallback : (result : String) -> ()) {
        dispatch_async(dispatch_get_global_queue(0, 0)) {
            print("发送异步网络请求:\\\\(NSThread.currentThread())")

            dispatch_sync(dispatch_get_main_queue(), {
                print("回调主线程:\\\\(NSThread.currentThread())")

                finishedCallback(result: "json数据")
            })
        }
    }

}

ViewController中使用
import UIKit

class ViewController: UIViewController {

    var tools : HttpTools?

    // override : 对父类方法的重写
    override func viewDidLoad() {
        super.viewDidLoad()

        tools = HttpTools()
    }

    override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        tools?.loadData({ (result) in
            print("在ViewController中获取到数据:\\\\(result)")
        })
    }
}
尾随闭包,可对比上面的代码
override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        // 尾随闭包 : 如果函数的最后一个参数是一个闭包.那么可以将函数调用写成尾随闭包
        tools?.loadData() { (result) in
            print("在ViewController中获取到数据:\\\\(result)")
        }

        // 如果函数有且只有一个参数,并且是一个闭包, 那么()也可以省略
        tools?.loadData { (result) in
            print("在ViewController中获取到数据:\\\\(result)")
        }
    }
闭包的循环引用

循环引用解决方案二:(推荐)
tools?.loadData({[weak self] (result) in
self?.view.backgroundColor = UIColor.redColor()
})

import UIKit

class ViewController: UIViewController {

    var tools : HttpTools?

    // override : 对父类方法的重写
    override func viewDidLoad() {
        super.viewDidLoad()

        tools = HttpTools()
    }

    override func touchesBegan(touches: Set, withEvent event: UIEvent?) {

        // 如果是在闭包中用到当前对象属性或者方法时,self也不可以省略
        // weak : 指向的对象销毁时,会自动指向nil

        // 循环引用解决方案一:
        /*
        weak var weakself : ViewController? = self
        tools?.loadData({ (result) in
            // print("在ViewController中获取到数据:\\\\(result)")
            weakself?.view.backgroundColor = UIColor.redColor()
        })
        */

        // 循环引用解决方案二:(推荐)
        /*
        tools?.loadData({[weak self] (result) in
            self?.view.backgroundColor = UIColor.redColor()
        })
        */

        // 循环引用解决方案三:(不推荐)
        tools?.loadData({[unowned self] (result) in
            self.view.backgroundColor = UIColor.redColor()
        })
    }

    deinit {
        print("ViewController -- deinit")
    }
}

懒加载

import UIKit

/*
 用到时再加载
 多次使用只会加载一次
 */

class ViewController: UIViewController {

    lazy var names : [String] = {
        return ["Kobe", "James", "Curry"]

    }()

    //这种写法可带参数
    lazy var btn : UIButton = {
        let btn = UIButton()
        btn.setTitle("按钮", forState: .Normal)
        btn.backgroundColor = UIColor.redColor()

        return btn

    }()

    //这种写法不可带参数,但比较简便,方便使用
    lazy var btn1 : UIButton = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()

        // print(names.count)

    }

    override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        names.count
    }
}

访问权限:

internal : 内部的
1> 当不指定具体的访问权限时, 默认的访问权限就是internal
2> internal的访问权限: 在当前项目(包)的任何地方都可以访问

private : 私有的
private的访问权限 : 在当前的源文件中可以访问

public : 公共的
1> public的访问权限 : 可以跨包进行访问
2> 包 : 项目/框架

处理异常

主要看方式二: try?方式 --> 系统处理异常, 如果有异常,则返回nil,如果没有异常,则返回结果
let regex = try? NSRegularExpression(pattern: "", options: .CaseInsensitive)
regex?.matchesInString("", options: [], range: NSMakeRange(0, 0))

// 创建一个`正则表达式`对象
        // let view = UIView(frame: CGRectZero)

        // 在swift中如果在调用一个方法, 该方法最后一个throws, 那么说明该方法会抛出异常
        // 如果该方法有抛出异常,必须对异常进行处理. 如果不处理,则编译不通过
        /*
         三种处理异常的方式
           方式一: try方式 --> 手动处理异常, 并且可以获取到最终的异常结果
             do {
                let regex = try NSRegularExpression(pattern: "", options: .CaseInsensitive)
             } catch {
                print(error)
             }
           方式二: try?方式 --> 系统处理异常, 如果有异常,则返回nil,如果没有异常,则返回结果
             let regex = try? NSRegularExpression(pattern: "", options: .CaseInsensitive)
             regex?.matchesInString("", options: [], range: NSMakeRange(0, 0))
         方式三: try!方式(不推荐) --> 告诉系统该方法不可能有异常. 注意:一旦发生异常,程序就会崩溃
            let regex = try! NSRegularExpression(pattern: "", options: .CaseInsensitive)
        */
自定义抛出异常
import UIKit
//异常要用枚举,且继承ErrorType
enum TypeError : ErrorType {
    case Jian1
    case Jian2
    case Jian3
    case TooBig
}

class HttpTools: NSObject {
    func loadData(type : Int) throws -> String {
        switch type {
        case 0:
            return "zero"
        case 1:
            return "one"
        case 2:
            return "two"
        case 3:
            // 抛出异常
            throw TypeError.Jian1
        case 4:
            // 抛出异常
            throw TypeError.Jian2
        case 5:
            // 抛出异常
            throw TypeError.Jian3
        default:
            // 抛出异常
            throw TypeError.TooBig
        }
    }
}

你可能感兴趣的:(三日上手swift(最后一天)会陆续更新到项目)