Swift

官方文档The Swift Programming Language官方文档 & 可选 《The Swift Programming Language》

一 工具及环境

1、工具

  • Xcode
  • AppCode

2、编写运行方式

(1)REPL

① 在终端输入:swift,可以看到版本情况,如下:

这里写图片描述
② 接下来即可进行代码编写
这里写图片描述

(2)Playground

① 通过 : File -> New -> Playground,打开Playground:
这里写图片描述

② 打开Xcode—>create a new project—>OS X Application—>Command Line Tool—>Language(Swift)

(3)使用swiftc命令
① 在终端使用:vi HelloWorld.swift
② 编写代码:

import Foundation
var str = "Hello World"
print(str)

③ 通过esc,输入指令退出编写::wq
④ 使用swiftc命令编译:swiftc HelloWorld.swift
⑤ 编译没有问题的情况下,可看到在同路径下生成同名的可执行文件(exec文件)
这里写图片描述

<三>使用“Markdown方言”编写代码注释

  • 设置快捷方式:Xcode -> Preferences -> Key Bindings -> 在下方 1 处设置一个自己的名称(如:My) -> 在 2 处输入: Show rendered -> 在 3 处设置想要用的快捷键(如:option + M)

在这里插入图片描述

① exam_01

  • 输入
//: # Heading1

/*:
 * item1
 * item2
 */
  • option + M,可见:
    在这里插入图片描述

② demo_02

  • 输入
/// A demo function ✨
func demo() {}
  • 将光标放在demo方法名上,option+command+2,可以在quick help看到对该方法的注释,如下:

在这里插入图片描述

  • option
    在这里插入图片描述

③ demo_03(含参数说明)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更多优雅高效使用Xcode参见官网Playground Secrets and Power Tips

二 基本语法

1、var / let

1、理解区分概念
(1)关键字、标识符

① mutating的使用

(2)常量、变量
(3)let、var

传统上,每种语言都用Hello World作为首程序,那么,我们也以此开始Swift学习之旅吧!

打开Xcode—>create a new project—>OS X Application—>Command Line Tool—>Language(Swift)

main.swift

println("Hello, World")

1.生成的文件名:以.swift作为扩展名
2.从上面的程序可知:
①Swift不需要导入头文件
②Swift不需要main函数
③Swift不需要每一语句都以;结束

此外,在编写Swift程序的时候,可以通过Xcode 的playground来进行查看程序运行的结果,工欲善其事必先利其器,如何使用playground,http://blog.csdn.net/yang_chengfeng/article/details/50587577,这是个人的一个小总结,下面所讲的程序都将在playground中进行

01-变量和常量
用 var定义变量,let定义常量

var myVariable = 42 
myVariable = 50
let myConstant = 42

但是,无论是变量还是常量,好像都不知道所定义的数据类型。其实不是这样的,编译器会根据所赋值默认变量的数据类型,可以如下:

let implicitInteger = 70
let implicitDouble = 70.0 // ①

对于①,如果是Float类型(注:在Swift中,数据类型名首字母大写),是否跟C语言一样写成70.0f?不是的:

let explicitFloat : Float = 70.0
// ②

如何证明呢?
可以在②处输入explicitFloat,Xcode会有提示,提示可以看到:Float explicitFloat

练习:
定义一个数据类型为Float的常量

let num: Float = 4

一种数据类型的数可以通过强制转换成另一种数据类型

02-字符串

let label = "The width is "
let width = 94
let labelWidth = label + String(94) // + :具有拼接两个字符串的作用

输出结果:

“The width is 94”

如果要在字符串中显示变量,可以:(变量名)

let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples"
let fruitSummary = "I have \(apples + oranges) pieces of fruit"

练习:

let name = "chengfeng_Yang"
let a: Float = 12.2
let b: Float = 12.2
let greeting = "Hello, \(name). \(a) + \(b) = \(a+b)"

03-数组和字典
空数组用[], 空字典用:[:]

let emptyArray = [String]() // ①
let emptyDictionary = DIctionary<String, Float>()

这里写图片描述
对于①,原来是:let emptyArray = String[]():不过运行过程出现:Array types are now written with the brackets around the element type, 并且此时编译器会提示:Fix-it String[->[String 或 Fix-it Insert [

var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water"

这里写图片描述

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic"
]
occupations["Jayne"] = "Public Relations"

这里写图片描述

04-控制流

let individualScore = [75, 43, 103, 87,12]
var teamScore = 0
for score in individualScore{
    if score > 50{ // if后面应该是Bool类型
        teamScore  += 3
    } else {
        teamScore += 1
    }
}
teamScore 

如无特殊说明,下面的程序的输出结果作为注释,注在 // 后

用?标记optional type , 用nil表示此类型数据丢失

var optionalSrting: String? = "Hello" // Hello
optionalSrting == nil // false

if语句:

var optionalName: String? = "John"
var greeting1 = "Hello"
if let name = optionalName{
    greeting1 = "Hello, \(name)"
}

switch语句:
1.一定要讨论到所有情况(即:default在大部分情况下是不能省略的)
2.where的作用:用来增加判断条件
3.case用法
4.不需要break也可以执行完对应的内容自动对出程序

let vegetable = "red pepper"
switch vegetable {
    case "celery":
        let vegetableComment = "Add1"
    case "cucuber", "watercress":
        let vegetableComment = "Add2"
    case let x where x.hasSuffix("pepper"):
        let vegetableComment = "\(x)"
    default:
        let vegetableComment = "nothing"
}

这里写图片描述

for-in的使用:

let interestingNumbers = [
    "Prime":[2, 3, 5, 7, 11, 13],
    "Fibonacci":[1, 1, 2, 3, 5, 8],
    "Square":[1, 4, 9, 16, 25],
]
var largest = 0
for(kind, numbers) in interestingNumbers{
    for number in numbers{
        if number > largest{
            largest = number
        }
    }
}

largest // 25
var firstLoop = 0
for i in 0...3{
    firstLoop += i
}
firstLoop // 6

其中,0…3是[0, 3]的取值范围

var secondForLoop = 0
for var i = 0; i < 3; ++i{
    secondForLoop += 1
}
secondForLoop // 3

while 与 do…while

var n = 2
while n < 100 {
    n = n * 2
}
n // 128
var m = 2
do{
    m = m * 2
} while m < 100
m // 128

7、控制语句:

(6)where语句:
① switch

② for

let numbers = [1, 2, 3, 4]
for item in numbers where item>2 {
    print("Count is: \(item)")
}

2、Collection

① 数组
  • 引用:
func collectionFunc() {
    var arr = [1, 2, 3]
    let tempArr = arr
    print(self.getBufferAddress(array: arr)) // UnsafeBufferPointer(start: 0x0000600000478e20, count: 3)
    print(self.getBufferAddress(array: tempArr)) // UnsafeBufferPointer(start: 0x0000600000478e20, count: 3)
    
    arr.append(4)
    print(self.getBufferAddress(array: arr)) // UnsafeBufferPointer(start: 0x0000600000297ae0, count: 4)
    print(self.getBufferAddress(array: tempArr)) // UnsafeBufferPointer(start: 0x0000600000478e20, count: 3)
}

func getBufferAddress<T>(array: [T]) -> String {
    return array.withUnsafeBufferPointer {
        return String(describing: $0)
    }
}
  • copy:
let b = NSMutableArray(array: [1, 2, 3])
let copyB:NSArray = b
let deepCopyB = b.copy() as! NSArray
  
b.insert(0, at: 0)
print(copyB) // (0, 1, 2, 3)
print(deepCopyB) // (1, 2, 3)
  • popLast() & removeLast()
var arr = [1, 2, 3]
arr.forEach { print($0) } // 逐个打印
  
let firstNum = arr.index { $0 == 1}
print(firstNum) // Optional(0)

print(arr.filter { $0 % 2 == 0 }) // [2]

print(type(of: arr.last)) // Optional<Int>
print(type(of: arr.removeLast())) // Int
print(type(of: arr.popLast())) // Optional<Int>
  • 排序
var arr = [3, 2, 6, 1, 9, 5]
print(arr.sorted()) // [1, 2, 3, 5, 6, 9]
print(arr.sorted(by: >)) // [9, 6, 5, 3, 2, 1]
print(arr.sorted(by: <)) // [1, 2, 3, 5, 6, 9]

 var fibonacci = [0, 1, 1, 2, 3]
let pivot = fibonacci.partition(by: { $0 < 1 })
print(fibonacci) // [3, 1, 1, 2, 0]
print(pivot) // 4
print(fibonacci[0..<pivot]) // [3, 1, 1, 2]
print(fibonacci[pivot..<fibonacci.endIndex]) // [0]
②字典

8、原生集合类型

(1)数组(Array)
① 有序、可重复
② swift数组类型Array,属于结构体类型;Foundation框架中NSArray数组,是一个类,非结构体,两者可通过“零开销桥接技术”互相转化

// 声明并初始化
var studentList1: Array<String> = ["张三", "李四"]
var studentList2: [String] = ["张三", "李四"]
let studentList3: [String] = ["张三"]
var studentList4 = [String]()

③ 不可变数组访问速率比可变数组高
④ 数组的增删改查

var studentList: [String] = ["张三", "李四"]
print(studentList)

// append追加一个元素, += 追加多个元素
studentList.append("王五")
print(studentList)

studentList += ["董六"]
print(studentList)

studentList.insert("刘备", at: studentList.count)
print(studentList)

let removeStu = studentList.remove(at: 0)
print(studentList)

studentList[0] = "张飞"
print(studentList)

⑤ 遍历

for item in studentList {
    print(item)
}

for (index, value) in studentList.enumerated() {
    print("Item \(index+1) : \(value)")
}

(2)集合(Dictionary)
① 键值对,无序性

var studentDictionary1 = Dictionary<Int, String>()
var studentDictionary2 = [Int: String]()
var studentDictionary3: Dictionary<Int, String> = [101: "张三", 102: "李四"]
var studentDictionary4 = [101: "张三", 102: "李四"]

② 删改

studentDictionary4[101] = "董六"
print("班级人数:\(studentDictionary4.count)")
let dismissStu = studentDictionary4.removeValue(forKey: 102)
let replaceStu = studentDictionary4.updateValue("王五", forKey: 101)

③ 遍历

for stuID in studentDictionary4.keys {
    print("学号:\(stuID)")
}
for stuName in studentDictionary4.values {
    print("姓名: \(stuName)")
}
for (stuId, stuName) in studentDictionary4 {
    print("学号-姓名:\(stuId) - \(stuName)")
}

(3)Set
① 无序,不重复

let A: Set<String> = ["a", "b", "c", "d"]
let B: Set<String> = ["d", "c", "e", "f"]

print("交集:\(A.intersection(B))")
print("并集:\(A.union(B))")
print("异或集合:\(A.symmetricDifference(B))")
print("差集:\(A.subtracting(B))")
print("是否子集:\(A.isSubset(of: B))")

9、函数

(1)函数参数
① 使用参数标签

func rectangleArea(W width:Double, H height: Double) -> Double {
    let area = width * height
    return area
}
print("面积:\(rectangleArea(W: 320, H: 480))")

② 省略参数标签

func rectangleArea(_ width:Double, H height:Double) -> Double {
    let area = width * height
    return area
}
print("面积:\(rectangleArea(100, H: 2))")

③ 参数默认

func makeCoffee(type: String = "卡布奇诺") -> String {
    return "制作一杯\(type)咖啡"
}

let coffee = makeCoffee()
print(coffee)

④ 可变参数

func sum(numbers:Double...) -> Double {
    var total:Double = 0
    for num in numbers {
        total += num
    }
    return total
}
print(sum(numbers: 30, 40))

⑤ 值类型参数的引用传递

swift提供inout关键字帮助实现将一个值类型参数以引用方式传递

func increment(value: inout Double, amount: Double = 1.0) {
    value += amount
}
var value: Double = 10.0
increment(value: &value) 
print(value) // 11.0

increment(value: &value, amount: 100.0)
print(value) // 111.0

(2)函数返回值
① 无返回值

func nothingForItOne() {
}

func nothingForItTwo() -> () {
}

func nothingForItThree() -> Void {  
}

② 多返回值

func position(dt:Double, speed:(x: Int, y: Int)) -> (x: Int, y: Int) {
    let posx: Int = speed.x * Int(dt)
    let posy: Int = speed.y * Int(dt)
    
    return(posx, posy)
}
let move = position(dt: 60.0, speed: (10, -5))
print("物体位移:\(move.x), \(move.y)")

(3)函数嵌套

func calculate(opr: String) -> (Int, Int) -> Int { 
    var result: (Int, Int) -> Int
    func add(a: Int, b: Int) -> Int {
        return a+b
    }
    func sub(a: Int, b: Int) -> Int {
        return a-b
    }
    switch (opr) {
    case "+":
        result = sub
    default:
        result = add
    }
    return result
}

10、闭包

对于上述嵌套函数的示例,可用下面代码替代:

func calculate(opr: String) -> (Int, Int) -> Int {
    var result: (Int, Int) -> Int
   
    switch (opr) {
    case "+":
        result = { // 闭包
            (a: Int, b: Int) -> Int in
            return a+b
        }
    default:
        result = { // 闭包
            (a: Int, b: Int) -> Int in
            return a-b
        }
    }
    return result
}

(1)示例:

// 嵌套函数
func makeArray() -> (String) -> [String] {
    var ary: [String] = [String]()
    func addElement(element: String) -> [String] { // ①
        ary.append(element)
        return ary
    }
    return addElement
}
let f1 = makeArray()
print(f1("张三"))

// 闭包
func makeArray() -> (String) -> [String] {
    var ary: [String] = [String]()
    
    return {(element: String) -> [String] in // ①
        ary.append(element)
        return ary
    }
}
let f1 = makeArray()
print(f1("张三"))

(2)尾随闭包

① 注意:闭包必须是参数列表最后一个参数
② 提供参数名缩写功能:可以直接通过$0$1等来表示闭包中的第一个、第二个参数


func calculate(opr: String, funN:(Int, Int) -> Int) {
    switch(opr) {
    case "+":
        print("10 + 5 = \(funN(10, 5))")
    default:
        print("10 - 5 = \(funN(10, 5))")
    }
}

calculate(opr: "+", funN: {(a: Int, b: Int) -> Int in return a + b})
calculate(opr: "+"){(a: Int, b: Int) -> Int in return a + b}
calculate(opr: "+"){$0 + $1}
calculate(opr: "-") {
    (a: Int, b: Int) -> Int in
    return a - b
}
calculate(opr: "-") {
    $0 - $1
}

(3)隐藏return关键字

func calculate(opr: String) -> (Int, Int) -> Int {
    var funN: (Int, Int) -> Int
    switch(opr) {
    case "+":
        funN = {a, b in a + b}
    default:
        funN = {a, b in a - b}
    }
    return funN
}

(4)使用闭包返回值

let c1: Int = {(a: Int, b: Int) -> Int in
                return a + b
              }(10, 5)
print("10 + 5 = \(c1)")

(5)逃逸闭包&非逃逸闭包

11、面向对象
(1)基本特性:封装、继承、多态
(2)数据类型:类、结构体、枚举

示例代码11-1:

enum WeekDay{
    case Monday, Tuosday, Wednesday, Thursday, Friday
}
var day = WeekDay.Monday
day = WeekDay.Friday
day = .Wednesday

func writeGreeting(day: WeekDay) {
    switch day {
    case .Monday:
        print("周一")
    default:
        print("非周一")
    }
}

① 枚举

示例代码11-2

// 原始值类型声明
enum WeekDays: Int {
    case Monday    = 0
    case Tuesday   = 1
    case Wednesday = 2
    case Thursday  = 3
    case Friday    = 4
}
// 取出原始值
enum WeekDay: Int {
    case Monday = 0, Tuesday, Wednesday, Thursday, Friday
}
print("周三的原始值:\(WeekDay.Wednesday.rawValue)")

示例代码11-3

enum Figure {
    case Rectangle(Int, Int)
    case Circle(Int)
}

func printFugure(figure: Figure) {
    switch figure {
    case .Rectangle(let width, let height):
        print("矩形宽高:\(width),\(height)")
    case .Circle(let radius):
        print("圆形半径:\(radius)")
    }
}
var figure = Figure.Circle(2)
printFugure(figure: figure)

示例代码11-4

// 关于类和结构体
class Employee {
    var no: Int = 0
    var name: String = ""
    var job: String?
    var salary: Double = 0
    var dept: Department?
}
struct Department {
    var no: Int = 0
    var name: String = ""
}

② 结构体

③ 类

这里写代码片

12、属性与下标

(1)属性与成员变量 & 计算属性与存储属性

① 存储属性 :常量属性和变量属性;适用于类和结构体,不适用于枚举类型

注:常量值类型,无论是结构体还是枚举类型都不能修改

② 延迟存储属性

示例代码 12-1:

class Employee {
    var no: Int = 0
    var name: String = ""
    var job: String?
    var salary: Double = 0
    lazy var dept: Department = Department() // 延迟加载:dept属性只有在第一次访问时才加载,如果永远不访问,就不会创建,可以减少内存占用
}

struct Department {
    let no: Int = 0
    var name: String = ""
}

let emp = Employee()

③ 计算属性:类、结构体、枚举都可以定义计算属性;计算属性提供了Getter和Setter

示例代码 12-2:

class Employee {
    var no: Int = 0
    var firstName: String = "Menior"
    var lastName: String = "Ly"
    var job: String?
    var salary: Double = 0
    lazy var dept: Department = Department()
    
    var fullName: String { // ① Setter和Getter
        get {
            return firstName + lastName
        }
        set (newFullName){
            var name = newFullName.components(separatedBy: ".")
            firstName = name[0]
            lastName = name[1]
        }
    }
}

struct Department {
    let no: Int = 0
    var name: String = ""
}

let emp = Employee()
print(emp.fullName)
        
emp.fullName = "Her.Ben"
print(emp.fullName)

④ 只读计算属性

示例代码 12-3

// 将示例代码 12-2 中 ① 改为只读计算属性
  var fullName: String { 
        return firstName + lastName // 只读计算属性
  }

⑤ 结构体和枚举的计算属性

示例代码 12-4

struct Department {
    let no: Int = 0
    var name: String = "SALES"
    var fullName: String {
        return "Love" + name + "Department"
    }
}

enum WeekDays: String {
    case Monday = "Mon."
    case TuesDay = "Tue."
    case Wednesday = "Wed."
    case Thursday = "Thu."
    case Friday = "Fri."
    
    var message: String {
        return "Today is " + self.rawValue
    }
}

 let dept = Department()
 print(dept.fullName)
        
 let day = WeekDays.Monday
 print(day.message)

⑥ 属性观察者

注:属性观察者不能监听延迟存储属性和常量存储属性的变化

// swift - newValue、oldValue
willSet() {
}
didSet() {
}

// OC - KVO - NSKeyValueObserving
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;

示例代码 12-5

class Employee {
    var no: Int = 0
    var name: String = "Monior" {
        willSet(newName) {
            print("员工新名:\(newName)")
        }
        didSet(oldName) {
            print("员工新名:\(oldName)")
        }
    }
    var job: String?
    var salary: Double = 0
    var dept: Department?
}

struct Department {
    var no: Int = 0 {
        willSet {
            print("新编号:\(newValue)")
        }
        didSet {
            print("旧编号:\(oldValue)")
        }
    }
    var name: String = ""
}

示例代码 12-6

class Employee {
    var no: Int = 0
    var name: String = "Monior" {
        willSet(newName) {
            print("员工新名:\(newName)") // Smith
        }
        didSet(oldName) {
            print("员工新名:\(oldName)") // Monior
        }
    }
    var job: String?
    var salary: Double = 0
    var dept: Department?
}

struct Department {
    var no: Int = 0 {
        willSet {
            print("新编号:\(newValue)") // 30
        }
        didSet {
            print("旧编号:\(oldValue)") // 0
        }
    }
    var name: String = "RESEARCH"
}

let emp = Employee()
emp.no = 100
emp.name = "Smith"
        
var dept = Department()
dept.no = 30

13、方法

18、泛型
(1)什么是泛型?

(2)作用:最大限度重用代码、保护类型的安全、提高性能

(3)如何使用?

① 基本使用

示例代码 18-1

func isEqual<T: Comparable>(a: T, b: T) -> Bool { // T:占位符
        return (a == b)
}

示例代码 18-2

struct StringQueue { // 缺点:只能放置String类型的元素
    var items = [String]()
    mutating func queue(item: String) {
        items.append(item)
    }
    mutating func deQueue() -> String? {
        if items.isEmpty {
            return nil
        } else {
            return items.remove(at: 0)
        }
    }
}

var strQueue = StringQueue()
strQueue.queue(item: "张三")
strQueue.queue(item: "李四")
strQueue.queue(item: "王五")
strQueue.queue(item: "董六")
print(strQueue.deQueue()!)
print(strQueue.deQueue()!)
print(strQueue.deQueue()!)

示例代码 18-3

struct Queue<T> {
    var items = [T]()
    
    mutating func queue(item: T) {
        items.append(item)
    }
    
    mutating func deQueue() -> T? {
        if items.isEmpty {
            return nil
        } else {
            return items.remove(at: 0)
        }
    }
}
var genericQueue = Queue<Int>()
genericQueue.queue(item: 0)
genericQueue.queue(item: 1)
genericQueue.queue(item: 2)
genericQueue.queue(item: 3)
print(genericQueue.deQueue()!) // 0
print(genericQueue.deQueue()!) // 1
print(genericQueue.deQueue()!) // 2
print(genericQueue) // Queue<Int>(items: [3])

② 泛型扩展

示例代码 18-4

struct Queue<T> {
    var items = [T]()
    
    mutating func queue(item: T) {
        items.append(item)
    }
    
    mutating func deQueue() -> T? {
        if items.isEmpty {
            return nil
        } else {
            return items.remove(at: 0)
        }
    }
}

extension Queue {
    func peek(position: Int) -> T? {
        if position < 0 || position > items.count {
            return nil
        } else {
            return items[position]
        }
    }
}

var genericQueue = Queue<Double>()
genericQueue.queue(item: 0.22)
genericQueue.queue(item: 1.43)
genericQueue.queue(item: 2.55)
genericQueue.queue(item: 3.98)
print(genericQueue.peek(position: 2)!) // 2.55
print(genericQueue.peek(position: 1)!) // 1.43
print(genericQueue) // Queue<Double>(items: [0.22, 1.4299999999999999, 2.5499999999999998, 3.98])

三、进阶篇

1、内存管理

2、错误处理

3、Foundation框架

(1) NSNumber

① 基本使用

示例代码 四-3-1

import Foundation

var intSwift = 80

var intNumber = NSNumber(value: intSwift)
var floatNumber = NSNumber(value: 80.0)

let myInt = intNumber.intValue
let myFloat = floatNumber.floatValue

② 比较大小

// 比较方式一
func isEqual(_ object: Any) -> Bool

// 比较方式二
func compare(_ other: Date) -> ComparisonResult

(10)正则表达式

① 即:regular expression;简写:regex、regexp、RE

② 相关类:NSRegularExpressionNSPredicateNSTextCheckingResult

a、NSPredicate:func evaluate(with: Any?),目的是验证字符串的有效性,缺点是不能过滤、检索、替换等,只能进行判断;无法处理错误

import Foundation

let pattern = "^\\W+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$"

let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
let str = "guangdongsheng@gmail.com"

if predicate.evaluate(with: str) {
    print("格式有效")
} else {
    print("格式无效")
}

b、NSRegularExpression:解决了NSPredicate问题

四、扩展

Reactive Programming in Swift

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值