Swift 基础入门教程

此文章属于Swift 基础教程,主要是全面的了解一下Swift的各种语法和函数。
主要参考Swift文档中的快速预览模块,期间搜索了最新的资料整理,加入了一些关键字的讨论和确认。希望对你的学习有帮助。
如果有你的观点和想法想和我讨论,欢迎留言。
github 地址

建议整体复制到你的playGround 运行

import UIKit

// 新语言的第一节  hello world
let helloWorld = "hello world!"
print(helloWorld)

//使用let 做常量 var 做变量 编译器可以判断值的类型 也可指定其类型 但是不会隐式的转换成其他类型
let myNumber = 43
var mynumber01 = 45
mynumber01 = 46
let myNumber3: Double = 90
let label = "The width is "
let width = 99
let widthString = label + String(width)
let widthString01 = "The width is \(width)"
let widthString02 = "The width is \(mynumber01 + width) km"

//数值型字面量也可以增加额外的格式使代码更加易读。整数和浮点数都可以添加额外的零或者添加下划线来增加代码的可读性。下面的这些格式都不会影响字面量的值。
let paddedDouble: Float = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

//""" 用于多行字符串 以下列出了两种换行方式 需要注意的是:使用"""换行方式  不能和内容在同一行  否则会报错
let lineString = """
你好
我现在
不方便
去你那
请多包涵
"""
let lineString1 = "你好\n我现在\n不方便\n去你那"

//创建数组和字典 根据规范 最好,后留出一个空格  :后留出一个空格
//在字典中如果类型不一致 或者无法判断出类型,需要对其进行注释,例如 : [String: Any]

/*
知识点:Any、AnyHashable、AnyObject、AnyClass的区别
Any是一个空协议集合的别名,它表示没有实现任何协议,因此它可以是任何类型,包括类实例与结构体实例,以及函数类型和可选类型。
AnyHashable遵守Hashable协议的Any类型,是Any的子集合,主要用于Dictionary和Set中。(Dictionary 要求它的Key类型需要遵守 Hashable协议)
AnyObject是一个成员为空的协议,任何对象都实现了这个协议。它是Any的子集合,Any中的类实例。
AnyClass是AnyObject.Type的别名而已。
可参考:https://blog.csdn.net/feosun/article/details/78002558
*/
var newArray = ["one", "two", "three", "four"]

//根据下标 修改元素
newArray[1] = "nihao"

//添加元素
newArray.append("nibuhao")

var newDic: [AnyHashable: Any] = [
    "name": "xiaoming",
    "age": 88,
    88: 89,
]
newDic[88] = 999

//创建空数组或者字典,如果可以推断用户信息,则可设置为空数组或者空字典
var emptyArray = [String]() //标明元素类型
let emptyArray1 = [] as [String]
emptyArray = []

var emptyDic = [String: Any]()
let emptyDic1 = [:] as [String: Any]
emptyDic = [:]

let acores = [78,89,99,23,34,54,65]
var teamScore = 0
for score in acores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)

//在值的类型后加? 表示类型可选
var optionString: String? = "optionstring"
print(optionString == nil)

var optionName: String? = "fengfeng"
var greeting: String = "hello!"
if let n = optionName {
    greeting = "hello \(n)"
} else {
    print("name 是空的")
}

//处理可选值的另一种方法是使用?? 提供默认值
let chaoName1: String? = nil
let chaoName: String = "lichao"
let chao = "hello \(chaoName1 ?? chaoName)"

//switch 支持任意类型的数据的操作,不限于整数和相等的情况. 下面例子中的where关键字指定额外的要求,并且只能在使用switch的语句,所有这些vagateble是泛型的,免去Swift中的类型转换。
//关于泛型可以参考(https://www.jianshu.com/p/6624f5365745)比较重要

let vagateble = "daxiang"
switch vagateble {
case "dayali":
    print("shuiguoshi _ dayali")
case "pingguo":
    print("shuiguoshi _ pingguo")
case "juzi":
    print("shuiguoshi _ juzi")
case let x where x.hasPrefix("daxiang") :
    print("shuiguoshi _ daxiangjiao+++++++ \(x)")
default:
    print("shadoubushi")
}

//字典的迭代 iterate (不同类型的数字是不能比较大小的,比如Double 和 Int ,需要有一个转换为相同类型才可以比较,这也是swift 安全性的体现之一)
let iterateDic = [
    "one": [2,3,4,67,78.8766,432],
    "two": [2,3,4,67,78.8766,432],
    "three": [2,3,4,67,78.8766,432],
    "four": [2,3,4,67,78.8766,432],
    "five": [2,3,4,67,78.8766,432],
]

var lagest: Double = 0
for (_, values) in iterateDic {
    for value in values {
        if value > lagest {
            lagest = value
        }
    }
}
print(lagest)

//while  repeat...while
var whileNumber = 2
while whileNumber < 200 {
    whileNumber += 33
}
print(whileNumber)


var repeatNumber = 3
repeat {
 repeatNumber += 20
} while repeatNumber < 300
print(repeatNumber)


//..< 不包括上限的值  ... 包括上限的值
var total = 0
for i in 1..<3 {
    total += i
}
print(total)

//函数和闭包
func greet(person: String, day: String) -> String {
    return "hello \(person) ,today is \(day)"
}
greet(person: "liuchao", day: "2018.9.27")

//在参数名前写入自定义的参数标签(本例的at) 或者加 _ 可省略参数标签
func greet2(_ person: String, at day: String) -> String {
    return "hello \(person) ,today is \(day)"
}
greet2("liuchao", at: "2018.9.27")


// 同objectiveC相比,swift多了一种结构类型,就是元组(之后会讲)
// 函数可使用元组 传
入复合参数
func jisuanscores(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0

    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }
        sum += score
    }

    return (min, max, sum)
}
let result = jisuanscores(scores: [3,45,66,77,23,35,546,243,37])
print(result.min, result.max, result.sum)

//函数还可以嵌套
func returnFifteen() -> Int {
    var a = 10

    func add() {
        a += 5
    }

    add() //内部函数的调用需要在函数声明之后

    return a
}
returnFifteen()

//牛逼的是 函数还可以返回另一个函数作为返回值
func fanHuiHanShu() -> ((Int) -> Int) {

    func addNumber(number: Int) -> Int {
        return number + 23
    }
    return addNumber
}
let addNumber = fanHuiHanShu()
addNumber(33)

//既然函数可以作为返回值  那么函数同样可以作为参数之一
func jianCeShiFouYouShiYiXia(list: [Int], condition: (Int) -> Bool) -> Bool {

    for number in list {

        if condition(number) {
            return true
        }
    }
    return false
}
let list = [2,3,4,5,6,7,23,43]
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
jianCeShiFouYouShiYiXia(list: list, condition: lessThanTen)

//闭包closures 闭包是无名的,因为他们能够从上下文中捕获变量、常量,从而应用在自身的作用区域。
let number0 = list.map({ (number: Int) -> Int in
    let result = 3 * number
    return result
})

print(number0)
print(list)

//还可以这样写, 当已知闭包的类型(例如委托的回调)时,可以省略其参数的类型,返回类型或两者。 单个语句闭包隐式返回其唯一语句的值。
let number1 = list.map( { number in
    3 * number
})
print(number0)
print(list)

//您可以按编号而不是按名称来引用参数 - 这种方法在非常短的闭包中特别有用。
//作为函数的最后一个参数传递的闭包可以在括号后面立即出现。
//当闭包是函数的唯一参数时,可以完全省略括号。
let sortedNumbers = list.sorted { $0 > $1 }
print(sortedNumbers)

//闭包的声明
var biBao: () -> String = {
    return "nihao"
}
//调用
biBao()

//无返回值的闭包
var biBao2: () -> () = {
    print("wobuhao")
}
biBao2()

//带参数的闭包
var canShuBiBao: (String, Int) -> String = {
    (name: String, age: Int) -> String in

    let nameString = "我叫 \(name), 今年\(age)岁了!"
    return nameString
}
print(canShuBiBao("liuchao",89))

//带参数的闭包简化 根据参数自动推断参数类型
canShuBiBao = {
    (name,age) in

    let nameString = "我叫 \(name), 今年\(age)岁了!"
    return nameString
}
print(canShuBiBao("liuchao001",89))

//第二次闭包简化 如果函数体只包含一句return 可省略return
canShuBiBao = {
    (name,age) in
    "我叫 \(name), 今年\(age)岁了!"
}
print(canShuBiBao("liuchao00333",89))

//第三次简化 被捕获的参数列表中 可通过 $ 获取  可自行判断出参数类型  所以可以省略 (name,age) in
canShuBiBao = {
    "我叫 \($0), 今年\($1)岁了!"
}
print(canShuBiBao("liuchao0033333333",89))

//对象和类 (: NSObject 可省略 )
class Person: NSObject {
    var name: String = "liuchao"
    let age: Int = 28

    var newName: String? {

//        set {
//        print(newValue)
//        }

        willSet {

            print(newValue ?? "")
        }

        didSet {

            print(oldValue ?? "")
        }

//        get {
//        return "new liuchao name"
//        }
    }


    init(name: String) {
        self.name = name

        super.init()
    }

    func nameAgeString() -> String {

        return "我叫 \(name), 今年\(age)岁了!"
    }

    deinit {
        print("对象销毁")
    }
}

let person = Person.init(name: "liuchao00999999")
person.name
person.age
person.newName = "newvalue liuhao------------"
person.newName
let nageAgeString = person.nameAgeString()

//枚举和结构体

//使用该rawValue属性可以访问枚举的原始值
enum LiuChao: Int {
    case abc = 1
    case two, three, four, five, six, seven
    case liuchao1, liuchao2, liuchao3

    func jianDanGuoLv() -> String {
        switch self {
        case .abc:
            return "001"
        case .two:
            return "002"
        case .three:
            return "003"
        case .liuchao1:
            return "004"
        case .liuchao2:
            return "005"
        case .six:
            return "006"
        case .four:
            return "007"
        default:
            return "------"
        }
    }
}
let chao222 = LiuChao.abc.rawValue
let chao2242 = LiuChao.liuchao1.rawValue
LiuChao.abc.jianDanGuoLv()

if let row = LiuChao.init(rawValue: 3) {
    row.jianDanGuoLv()
}

//枚举的另一种情况
enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")

switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure...  \(message)")
}

//用 typealias 关键字定义类型别名。一旦为类型创建了一个别名,你就可以在任何使用原始名字的地方使用这个别名。
typealias AudioSample = UInt16

//结构体
struct LiuChao333 {
    var name: String
    var age: Int

    func nameAgeStringResult() -> String {

        return "\(name),\(age)"
    }
}

let naage = LiuChao333.init(name: "liuchao", age: 23)
naage.nameAgeStringResult()


//Protocols and Extensions   针对结构体和枚举 实例方法中修改属性值,可以在方法定义前添加关键字mutating
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

class SimpleClass: ExampleProtocol {

    var simpleDescription: String = "this is a simple description"

    func adjust() {
        simpleDescription += "yes yes yes"
    }
}
let simpaleclass = SimpleClass()
simpaleclass.adjust()
simpaleclass.simpleDescription

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    var anotherProperty: Int = 69105
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription


extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
print(7.simpleDescription)

let protocolValue: ExampleProtocol = b
print(protocolValue.simpleDescription)
//print(protocolValue.anotherProperty)

// 错误处理
enum PrinterError: Error {
    case outOfPaper
    case onToner
    case onFire
}

//如果在函数中抛出错误  函数会立刻返回 调用函数会提示错误
func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "funnys" {
        throw PrinterError.outOfPaper
    }
    return "嘿嘿  不是我"
}
try send(job: 3, toPrinter: "fundnys")


//在do 内放可能引发错误的代码  catch 内可以打印错误的名字
do {
    try send(job: 3, toPrinter: "funny")
} catch let printerError as  PrinterError {
    print(printerError)
}

//处理错误的另一种方式是try?将结果转为可选的,
let printerResult = try? send(job: 2, toPrinter: "funnys")
print(printerResult ?? "dede")

//先fridgeIsOpen = true,然后是函数体正常的流程,最后在 return 之前执行 fridgeIsOpen = false,defer一个很适合的使用场景就是用来做清理工作
var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]


func fridgeContains(_ food: String) -> Bool {
    fridgeIsOpen = true
    defer {
        fridgeIsOpen = false
    }

    let result = fridgeContent.contains(food)
    return result
}
fridgeContains("milk")
print(fridgeIsOpen)

//泛型,在尖括号里写一个名字来创建一个泛型函数或者类型。适用于类,枚举和结构体

func repeatItem<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result = [Item]()

    for _ in 0..<numberOfTimes {
        result.append(item)
    }
    return result
}
repeatItem(repeating: "ItemItems", numberOfTimes: 4)

//重新实现 Swift 标准库中的可选类型
enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleValue: OptionalValue<Int> = .none
possibleValue = .some(100)


//where 一般用作条件判断,确认实现了什么才执行函数体,比如下面,确认T.Element实现了 Equatable协议,并且T.Element == U.Element
//T.Element 表示序列元素的类型 比较的是元素的类型相等 比如[1, 2, 3]的元素类型是 Int
func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Element: Equatable, T.Element == U.Element
{
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])

//元组
let http404Error = (404,"Not Found")
http404Error.0
http404Error.1

//必须元素的数量一致
let (statusCode,statusString) = http404Error
print(statusCode)
print(statusString)
let (statusCode1,_) = http404Error

//也可以单独命名,但是必须通过访问名字来获取元素
let httpError1 = (statuscode2: 200, statusString2: "OK")
httpError1.statuscode2
httpError1.statusString2

//断言,可在debug模式下运行,在release模式下不运行
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
//针对代码已经检查了条件
assertionFailure(_:file:line:)

//先决条件 precondition,在debug和release下都运行
precondition(index > 0, "Index must be greater than zero.")
//针对代码已经检查了条件
preconditionFailure(_:file:line:)

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

推荐阅读更多精彩内容

  • 更多整理资料尽在👉一平米小站 变量和常量 运算符 可选项 条件语句 循环 字符串 元组 数组 字典 10-对象和类 控件
    leiyulingling阅读 1,728评论 0 2
  • 我也不知道自己为什么开这篇文,只是坐在这里别提纲的时候忽然发现好久没有好好爱过自己了,不知道什么,最近真的好累,喜...
    离未央阅读 330评论 0 1
  • 放假第二天 1:.公园晨练,去早市 2:上午洗棉衣,毛衣等 3:下午去按摩 走了10389步,完成每日一万步目标。
    心境如花阅读 214评论 0 0
  • 平凡之人因为不能保持内心的清静,在生理上则形成心火上炎,肾水下流之“火水未济”之象,此象是人体阴阳失和之象,...
    双星道人阅读 638评论 0 0
  • 清明小记 清明时节雨纷纷,路上行人欲断魂。雨水如期而至,行人如期而归。每年的清明,一家老小都会来到这个熟悉而又陌...
    循环录阅读 101评论 0 1