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