Swift学习笔记

这是一篇学习swift的笔记

Objective-C是很好的语言,Runtime机制、消息机制等也是爱不释手。
Swift一直在更新,闲暇时间学一遍。学习的Blog:《从零开始学swift》
以下代码全部在playground进行的尝试

变量

let 是常量
var 是变量
不能修改的使用常量可以提高程序的可读性。

var str = "Hello, playground"
print(str)

let constA:Int = 12
let constB = 12
let constC = 12; let constD:Float = 12

元组:关系数据库中的基本概念,元组表中的一条记录,每列就是一个字段。因此在二维表里,元组也称为记录。元组是Swift中特有的。

var abc = (10, 12, 30, "abc")
var score = (id:"1001", name:"张三", english_score:30, chinese_score:90)
score.english_score = 100
score

运算符

  • 引用号(.):实例调用属性、方法等操作符。
    
  • 问号(?):用来声明可选类型。
    
  • 感叹号(!):对可选类型值进行强制拆封。
    
  • 箭头(->):说明函数或方法返回值类型。
    
  • 冒号运算符(:):用于字典集合分割“键值”对。
    
  • ..< 运算符是一个非包函范围运算符,不包括上限值。
    
  • 运算符 ... :类似上面,包括上限值。
    
  • ?? 操作符: a ?? b 如果a不为nil,返回a里面的值,否则返回b的值
    

操作符要求类型一致(int8 和 int16是不同的)

let short:Int16 = 277
let sshort:Int8 = 100
//Int8(short) + sshort
short + Int16(sshort)

..<运算符

  let arr = ["abc", "bcd"]
        for i in 0..<arr.count {
            if someC[i] != anotherC[i] {
                return false
            }

for in

遍历容器。可以用变量遍历,也可以用元组遍历。
如下

var stList = [String]()
stList.insert("abc", atIndex: 0)
stList.insert("bcd", atIndex: 1)
stList.insert("cde", atIndex: 0)

var stList2:[String] = ["a", "B", "c"];

for st in stList2 {
    print(st)
}

for (index, value) in stList.enumerate() {
    print("index\(index):\(value)")
}

属性

属性类型

  • 存储属性:存储数据,分为常量属性(let)和变量属性(var),如下面的name和number。
  • 计算属性:不存储数据,通过计算其他属性返回数据,如下面的workYears。

当声明属性时,声明必须为它们设置初始值,或者在初始化时设置初始值。
如果不希望为属性设置初始值,必须声明它们作为可选。

var strLin = "loyinglin" //设置初始值
var str:String? //声明为可选

读写器

  • get
  • set
  • willSet
  • didSet
    见下代码。
class Person {
    var name:String = "loying"
    var number:Int = 2010551110
    private var mYear = 2016 {
        willSet(year) {
            print("willSet\(year)")
        }
        didSet(year) {
            print("didSet\(year)")
        }
    }
    var workYears:Int {
        get {
            print("get year")
        return 2016 - mYear
        }
        set(year) {
            if (year >= 0){
                mYear = 2016 - year
            }
        }
    }
}

访问权限控制

访问权限类型

  • public:可以访问自己模块中的任何public实体,也可以访问其他模块中的public实体。
  • internal:只能访问自己模块的任何internal实体,不能访问其他模块中的internal实体。默认权限是internal。
  • private:只能在当前源文件中使用的实体,称为私有实体。
public class Person {
    private var name:String = "loying"
    internal var number:Int = 2010551111
}

原则

  • 统一性原则:A如果包含B,那么A的权限开放等级大于等于B。
    (元组类型的访问级别遵循元组中字段最低级的访问级别)
  • 设计原则:对外开放使用public,对外封闭使用internal或private。

结构体与类

结构体:值类型,每个实例没有独一无二的标识。

类:引用类型,每个实例有独一无二的标识。

可选链

可选链是一种可以调用属性、方法的过程,用于调用的对象可能为nil。
如果目标有值,调用就会成功;如果目标为nil,调用将返回nil。
多次请求或调用可以被链接成一个链,如果任意一个节点为nil将导致整条链失效。
** 通过可选链调用方法时返回值总是可选类型的 **。
调用 Optional 对象方法前,必须拆包:
使用问号(?)声明的可选类型,在拆包时需要使用感叹号(!),这种拆包方式称为“显式拆包”;
使用感叹号(!)声明的可选类型,在拆包时可以不使用感叹号(!),这种表示方式称为“隐式拆包”。

var nilInt:String? = "abc"
let textNil = nilInt
if let test = nilInt {
    print("OK \(test)  \(textNil) \(textNil!)") //观察输出值
}
if (textNil != nil) {
    print("textNil \(textNil)")
}

函数

多种实现方式,具体如下

func plus(width:Int, height:Int)->Int { //普通函数
    return width + height
}
print("1 + 2 = \(plus(1, height: 2))")
plus((Int)(short), height: Int(sshort))

func plus2(W width:Int, H Height:Int)->Int { //参数别名
    return width + Height
}
plus2(W:12, H:23)

func plus3(width:Int, _ Height:Int)->Int { //不带参数名
    return width + Height
}
plus3(22, 33)

func plus4(width:Int, _ Height:Int = 10)->Int { //默认参数值
    return width + Height
}
plus4(20, 20)
plus4(20)

func plusMore(width:(Length:Int, Size:Int), _ mul:Int) -> (Length:Int, Size:Int) { //元组参数
    let ret = (Length:width.Length * mul,
        Size:width.Size * mul)
    return ret
}
plusMore((Length: 20, Size: 5), 3)

构造函数

  • 便利构造函数:带convenience的init,必须调用指定构造函数
  • 指定构造函数:不带convenience的init。
    构造函数的主要作用是初始化实例,包括初始化存储属性和其它的初始化。
 class Person {
    var name:String = "loying"
    var number:Int = 2010551110
      
    init(id:Int) {
        number = id
    }
    convenience init() {
        self.init(id:0)
    }
}

继承

在Swift中,类是单继承。多重继承通过多个协议实现。

属性、方法、下标

类可以继承另一个类的方法、属性、下标等特征。
子类继承父类后,可以重写父类的方法、属性、下标等特征。

读写器

你可以将一个继承来的只读属性重写为一个读写属性,只需要你在重写版本的属性里提供 getter 和 setter 即可。但是,不可以将一个继承来的读写属性重写为一个只读属性。
你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值是不可以被设置的,所以,为它们提供willSet
或didSet 实现是不恰当。

重写静态属性

我们可以在子类中重写从父类继承来的属性,属性有实例属性和静态属性之分。
class修饰的属性可以被重写,static关键字就不能被重写。

重写静态方法

静态方法使用class或static关键字,class修饰的静态方法可以被重写,static关键字就不能被重写。

重写属性

下标是一种特殊属性。子类属性重写是重写属性的getter和setter访问器,对下标的重写也是重写下标的getter和setter访问器。

final

final声明的类不能被继承,final声明的属性、方法和下标不能被重写。

错误处理

Cocoa错误处理模式

构造函数的最后一个参数是NSErrorPointer(即NSError指针),那么在实际调用时候我们需要传递err变量地址(即&err),&是取地址符。当方法调用完成后,如果有错误则err变量会被赋值。

swift错误处理模式

使用do - try - catch 模式
使用了try?语句没有必要使用do-catch语句将其包裹起来。
所以使用try!打破错误传播链条时,应该确保程序不会发生错误。

do {
    let path:String? = NSBundle.mainBundle().pathForResource("text", ofType: "txt")
    
    let str = try NSString(contentsOfFile:path!, encoding:NSUTF8StringEncoding)
    print(str)
}
catch let err as NSError {
    err.description
}

捕获列表

捕获列表中的每个元素都是由weak或者unowned关键字和实例的引用(如self)成对组成。每一对都在方括号中,通过逗号分开

NSNotificationCenter.defaultCenter().addObserverForName("DoneModelChange", object: nil, queue: nil) { [unowned self](note) -> Void in
            self.tableView.reloadData()
        }

闭包

尾随闭包

闭包表达式是函数最后一个参数,调用函数可以使用尾随闭包写法。
如下:

func plusAfterMul(plus:Int, factor1:Int, factor2:Int, funMul:(Int, Int)->Int)->Int {
    return plus + funMul(factor1, factor2)
}
plusAfterMul(1, factor1: 2, factor2: 3) {
    (a:Int, b:Int)->Int in
    var ret = 1
    var count = b
    while count > 0 {
        --count
        ret *= a
    }
    return ret
}

单一表达式隐式返回

如下,排序函数的第二个参数的函数类型明确指出,一个布尔值必须由闭包返回。因为闭包体内含有一个表达式(s1 > s2)返回一个布尔值, 不会出现歧义,其返回关键字可以省略。

let count = [5, 10, -6, 75, 20]
var descending = sorted(count, { n1, n2 in n1 > n2 })
var ascending = sorted(count, { n1, n2 in n1 < n2 })
println(descending)
println(ascending)

Any、AnyObject

AnyObject是一个协议,Any是零个协议。
AnyObject用于任何类实例,而Any用于任何变量。
AnyObject 可以代表任何 class 类型的实例。
看如下例子
声明一个 Int 和一个 String,按理说它们都应该只能被 Any 代表,而不能被 AnyObject 代表的。
实际上,元素其实已经变成了 NSNumber 和 NSString 。因为我们 import 了 UIKit 。因为我们显式地声明了需要 AnyObject,编译器认为我们需要的的是 Cocoa 类型而非原生类型,而帮我们进行了自动的转换。

import UIKit
let swiftInt: Int = 1
let swiftString: String = "miao"
var array: [AnyObject] = []
array.append(swiftInt)
array.append(swiftString)

在上面的代码中如果我们把 import UIKit 去掉,会得到无法适配 AnyObject 的编译错误。
可以把声明 array 的 [AnyObject] 换成 [Any]。

关联类型

Swift 允许相关类型,并可由关键字“typealias”协议定义内部声明。

  • 类似typedef,可以给对象一个别名;
  • 代表泛型;
protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

运算符重载

Paste_Image.png

惰性初始化

  • 简单表达式

lazy var first = NSArray(objects: "1","2")

  • 闭包

lazy var second:String = { return "second" }()

不要忘记最后的小括号,只有加了小括号,闭包才会在调用的时立刻执行。

要类型声明lazy var second:String 这样Xcode会进行类型检查。

泛型函数、协议的应用

protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct Stack<T>: Container {
    var items = [T]()
    
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func append(item: T) {
        self.push(item)
    }
    
    var count: Int {
        return items.count
    }
    
    subscript(i: Int) -> T {
        return items[i]
    }
}

func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType:Equatable>(someC: C1, anotherC: C2) -> Bool {
        if someC.count != anotherC.count {
            return false
        }
        
        for i in 0..<someC.count {
            if someC[i] != anotherC[i] {
                return false
            }
        }
        
        return true
}

var stackOfStrings = Stack<String>()
stackOfStrings.push("abc")
stackOfStrings.push("qwe")

var arrayOfString = Stack<String>()
arrayOfString.push("abc")
arrayOfString.push("aaa")

if allItemsMatch(stackOfStrings, anotherC: arrayOfString) {
    print("ok")
}
else {
    print("not equal")
}

总结

学习的过程中,先对着《从零开始学swift》,把swift的代码实现一遍。
大概有300多行代码,写完之后语法基本熟悉了。
然后找一个oc的项目,把里面的oc代码全部用swift实现一遍。swift入门就结束了。
整个代码文件如下

//: Playground - noun: a place where people can play

import UIKit

//看右侧
var str = "Hello, playground"

//简单的打印
print(str)

let image = UIImage(named: "abc.jpeg")

let view = UIView(frame: CGRectMake(0, 0, 100, 100))

let constA:Int = 12
let constB = 12
let constC = 12; let constD:Float = 12

var abc = (10, 12, 30, "abc")
var score = (id:"1001", name:"张三", english_score:30, chinese_score:90)
score.english_score = 100
score

var strLin = "loyinglin"

strLin.insert("L", atIndex: strLin.endIndex)

//strLin.insertContentsOf("abc", at: strLin.endIndex)

//strLin.replaceRange(range, with: "abc")
(strLin as NSString).substringWithRange(NSMakeRange(0, 4))
strLin.substringWithRange(Range(start: strLin.startIndex.advancedBy(1), end: strLin.endIndex.advancedBy(-2)))

let short:Int16 = 277
let sshort:Int8 = 100
//Int8(short) + sshort
short + Int16(sshort)

var stList = [String]()
stList.insert("abc", atIndex: 0)
stList.insert("bcd", atIndex: 1)
stList.insert("cde", atIndex: 0)

var stList2:[String] = ["a", "B", "c"];

for st in stList2 {
    print(st)
}

for (index, value) in stList.enumerate() {
    print("index\(index):\(value)")
}

func plus(width:Int, height:Int)->Int {
    return width + height
}
print("1 + 2 = \(plus(1, height: 2))")
plus((Int)(short), height: Int(sshort))

func plus2(W width:Int, H Height:Int)->Int {
    return width + Height
}
plus2(W:12, H:23)

func plus3(width:Int, _ Height:Int)->Int {
    return width + Height
}
plus3(22, 33)

func plus4(width:Int, _ Height:Int = 10)->Int {
    return width + Height
}
plus4(20, 20)
plus4(20)

func plusMore(width:(Length:Int, Size:Int), _ mul:Int) -> (Length:Int, Size:Int) {
    let ret = (Length:width.Length * mul,
        Size:width.Size * mul)
    return ret
}
plusMore((Length: 20, Size: 5), 3)

func plusAfterMul(plus:Int, factor1:Int, factor2:Int, funMul:(Int, Int)->Int)->Int {
    return plus + funMul(factor1, factor2)
}
plusAfterMul(1, factor1: 2, factor2: 3) {
    (a:Int, b:Int)->Int in
    var ret = 1
    var count = b
    while count > 0 {
        --count
        ret *= a
    }
    return ret
}

enum Days:Int{
    case Mon
    case Tus, Wed, Thu, Fri
}

var bool = Days.Mon == Days.Thu

internal class Department {
    var dName:String = "department-1"
    let dNumber:Int = 123
}

private class Person {
    var name:String = "loying"
    var number:Int = 2010551110
    private var mYear = 2016 {
        willSet(year) {
            print("willSet\(year)")
        }
        didSet(year) {
            print("didSet\(year)")
        }
    }
    var Dept:Department?
    var YDept:Department!
    var workYears:Int {
        get {
            print("get year")
        return 2016 - mYear
        }
        set(year) {
            if (year >= 0){
                mYear = 2016 - year
            }
        }
    }
    
    init(id:Int) {
        number = id
        print("total person\(++Person.totalPerson) and \(self)")
    }
    
    

    convenience init() {
        self.init(id:0)
    }
    
    static var totalPerson = 0
}

private class Student: Person {
    var school:String {
        willSet(value) {
            print("school is \(value)")
        }
    }
    convenience init(sch:String) {
        self.init(sch:sch, id:123)
    }
    init(sch:String, id:Int) {
        school = sch
        super.init(id: id)
    }
    
    override var workYears:Int {
        get {
            return super.workYears
        }
        set(year) {
            super.workYears = year
        }
    }
    
    init() {
        school = "ly"
        super.init(id:123)
    }
    
    deinit {
        print("dealloc \(school)")
    }
    
}

private var st = Student(sch: "abc")
st.school
st.workYears

private var man = Person()
man = Person(id: 123)
man.number
man.mYear
man.workYears
man.workYears = 3
man.mYear
Person()

private var arrMen = [st, man]
for item in arrMen {
    let test = item as? Student
    if (test != nil) {
        (item as! Student).workYears
        print("item is student in \(test?.workYears)")
    }
    if let test2 = item as? Student {
        print("test2 \(test2)")
    }
}

man.Dept?.dNumber
man.Dept = Department()
man.Dept!.dNumber

man.YDept?.dNumber

var opStr:String?
print(opStr)
//print(opStr!)

var nilInt:String? = "abc"
let textNil = nilInt
if let test = nilInt {
    print("OK \(test)  \(textNil) \(textNil!)")
}
if (textNil != nil) {
    print("textNil \(textNil)")
}

struct DoubleArray: Equatable {
    let rows:Int, columns:Int
    var grid:[Int]
    init(row:Int, column:Int) {
        self.columns = column
        self.rows = row
        
        grid = Array(count: row * column, repeatedValue: 0)
    }
    
    subscript(row:Int, column:Int)->Int {
        return grid[row * columns + column]
    }
    mutating func setValue(row:Int, column:Int, value:Int) {
        grid[row * columns + column] = value
    }
    
    var count:Int {
        return grid.count
    }
}
func ==(lhs: DoubleArray, rhs: DoubleArray) -> Bool {
    return lhs.count == rhs.count
}

var dArr:DoubleArray = DoubleArray(row: 3, column: 3)
dArr[2, 2]
dArr.setValue(1, column: 1, value: 1)
dArr[1, 1]

extension Int {
    var lyDesc:String {
        var desc = ""
        switch (self) {
        case 4: desc = "Bad"
        case 8: desc = "Good"
        default:desc = "nothing"
        }
        return desc
    }
    
    func lyPrint() {
        print("ly Print self:\(self)")
    }
}

1.lyDesc
4.lyDesc
8.lyDesc

1234567.lyPrint()

var ab = {(a:Int, b:Int) -> Int in
    var ret = a + b
    return ++ret
}
ab(3, 4)

var moba:(Int, Int)->Int = {$0 * $1}
moba(4, 6)

do {
    let path:String? = NSBundle.mainBundle().pathForResource("text", ofType: "txt")
    
    let str = try NSString(contentsOfFile:path!, encoding:NSUTF8StringEncoding)
    print(str)
}
catch let err as NSError {
    err.description
}
str

var msg:String!
if msg != nil {
    
}
else {
    print("OJ\(msg)")
}

protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct Stack<T>: Container {
    var items = [T]()
    
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func append(item: T) {
        self.push(item)
    }
    
    var count: Int {
        return items.count
    }
    
    subscript(i: Int) -> T {
        return items[i]
    }
}

func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType:Equatable>(someC: C1, anotherC: C2) -> Bool {
        if someC.count != anotherC.count {
            return false
        }
        
        for i in 0..<someC.count {
            if someC[i] != anotherC[i] {
                return false
            }
        }
        
        return true
}

var stackOfStrings = Stack<String>()
stackOfStrings.push("abc")
stackOfStrings.push("qwe")

var arrayOfString = Stack<String>()
arrayOfString.push("abc")
arrayOfString.push("aaa")

if allItemsMatch(stackOfStrings, anotherC: arrayOfString) {
    print("ok")
}
else {
    print("not equal")
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容