iOS学习笔记(3)-Swift概览

上次找到一个iOS实战教程,用的是swift,看了下确实比obj-c要方便不少,于是看了《swift programming language》,总结下基础语法,swift版本为2.2。

1 数据类型

  • 常量和变量: 用let声明常量,用var声明变量,常量只能赋值一次。
  • 类型推断: 定义变量的时候可以不用声明类型,swift可以自动推断。不过要注意的是,如果初始值信息不够或者没有初始值,需要声明变量类型,见下面例子。
  • 类型转换: 值不会隐式转换为其他类型,比如下面的字符串拼接,可以用+拼接字符串,但是整数需要先显示转换为String类型才可以拼接。另外,也可以通过反斜杠加括号的方式拼接。需要注意的是,不像python等其他语言,Swift的字符串必须用""而不是''括起来。
  • 元组: 通过()创建,元组内部的元素数据类型可以任意,不需要一样。
  • 数组和字典:数组和字典统一通过[]来创建。空的数组和字典需要使用初始化语法。如果类型信息可以推断出来,可以省掉类型信息。
  • 可选类型: 可选类型用来处理值可能缺失的情况,这是swift独有的,C或者objective-C中都没有这个类型。定义的时候在类型后面加个?表示可选类型。注意,nil不能用于非可选的变量,如果变量有可能缺失值,则需要声明为可选类型。可选类型如果声明的时候没有赋值,则自动会被设置为nil。
  • 类型别名: 可以通过typealias关键字来给已有类型定义一个别名。
//1 常量和变量
let apples = 3
apples = 4 //错误,常量只能赋值一次
var orange = 5
orange = 6 //正确

let orangesAreOrange = true 
let turnipsAreDelicious = false

//2 类型推断
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70 //显示声明类型,因为根据初始值无法确定变量类型

//3 类型转换
let desc = "Apple num: "
let descLabel = desc + String(apples)
let appleSummary = "I have \(apples) apples."


//4 元组
let http404Error = (404, "Not Found") //元组里的数据类型可以任意,不需要一致

//5 数组和字典
var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water"
 
var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

let emptyArray = [String]() //不加类型信息 let emptyArray = []
let emptyDictionary = [String: Float]() //不加类型信息 let emptyDictionary = [:]

//6 可选类型
var serverResponseCode: Int? = 404 //serverResponseCode 包含一个可选的 Int 值 404 
serverResponseCode = nil //serverResponseCode 现在不包含值

oranges = nil //错误
var surveyAnswer: String?// surveyAnswer 被自动设置为 nil

//7 类型别名
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min

2 控制流

与其他语言一样,有 if...else..., while, repeat...while, for...in

  • 括号问题: 循环或判断语句的括号可以省略,如下面的for...in,但是语句体的花括号{}必须有。
  • 强制解析和可选绑定: 在确定可选类型有值的情况下,使用!可以强制解析可选类型,也使用可选绑定来判断可选类型是否有值以及解析出可选类型的值。
  • 隐式解析可选类型: 有些可选类型在第一次被赋值后可以确定总会有值,这时候可以将可选类型定义为隐式解析可选类型,隐式解析可选类型方式为将类型后面的?改为!
  • switchif: switch语句支持任意类型的数据和各种操作,也不需要在每个case后面加break。还有if语句的判断必须是Bool类型,不能像其他语言那样可以直接拿整数值进行判断。
//1 括号问题
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)

//2 强制解析和可选绑定
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
if convertedNumber != nil {
     print("convertedNumber has an integer value of \(convertedNumber!).")
}
if let actualNumber = Int(possibleNumber) { //Int
    print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
    print("\'\(possibleNumber)\' could not be converted to an integer")
}
// 输出 "'123' has an integer value of 123"


//3 可选类型/隐式解析可选类型
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要惊叹号来获取值
let assumedString: String! = "An implicitly unwrapped optional string." 
let implicitString: String = assumedString // 不需要感叹号

//4 switch语句不用在每个case后面加break,if判断必须是Bool类型
let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
    print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything tastes good in soup.")
}

let i = 1 
if i {
   //编译错误
}
if i == 1 {
  //编译成功 
}

3 函数

  • 使用func来声明函数,使用->来指定函数返回值的类型,函数可以带有可变个数的参数(可变参数后面带...)。
  • 函数可以嵌套函数。函数也可以作为参数和另一个函数的返回值。
//1 函数声明
func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum 
}
sumOf()
sumOf(42, 597, 12)

//2 函数作为参数
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 17, 12]
hasAnyMatches(numbers, condition: lessThanTen)

4 对象和类 & 枚举和结构体

  • 使用class来创建一个类,类中属性和常量声明普通变量和常量声明,只是它们属于这个类。引用实例变量用self关键字,调用父类方法用super关键字。属性也可以有gettersetter
  • 构造函数为init,析构函数为deinit(注意后面没有括号),不需要func关键字。
  • 类之间继承用:,子类覆盖父类方法需要用override关键字。
  • 结构体和类相似,只是传参的时候结构体传的是值,类是传引用。
//1 类
class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    init(name: String) {
        self.name = name
    }
    deinit { 
        print("deinit")
    }
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    } 
}


class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name) //调用父类的构造器方法
        numberOfSides = 3 //修改父类定义的属性值
    }
    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
    override func simpleDescription() -> String {
        return "An equilateral triagle with sides of length \(sideLength)."
    }
}
let optionalSquare: EquilateralTriangle? = EquilateralTriangle(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength //处理可选变量的新语法,如果变量为nil,则返回nil,否则返回问号后面的值。注意,整个表达式返回的也是可选值。

//2 枚举和结构体
 enum Suit {
     case Spades, Hearts, Diamonds, Clubs
     func simpleDescription() -> String {
         switch self {
         case .Spades:
             return "spades"
         case .Hearts:
             return "hearts"
         case .Diamonds:
             return "diamonds"
         case .Clubs:
             return "clubs"
         }
     } 
 }
 let hearts = Suit.Hearts
 let heartsDescription = hearts.simpleDescription()

 struct Card {
     var rank: Rank
     var suit: Suit
     func simpleDescription() -> String {
         return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
     }
 }
 let threeOfSpades = Card(rank: .Three, suit: .Spades)
 let threeOfSpadesDescription = threeOfSpades.simpleDescription()

5 协议和扩展

  • 使用protocol声明协议,extension声明扩展。协议有点类似接口,而扩展用来为已有类添加新的功能。
  • 类,结构体和枚举都可以实现协议。注意结构体中的方法需要声明为mutating,用于标记该方法会修改结构体。而类中的方法不需要,因为类中方法总是可以修改类属性。
//1 协议声明
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

//2 类实现协议
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
 
//3 结构体实现协议
struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

//4 扩展Int,添加一个测试函数。
extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42 
    }
}
print(7.simpleDescription)

6 错误捕获

  • 使用throws关键字声明一个函数可能抛出异常,使用do...catch关键字捕获函数。
enum PrinterError: ErrorType {
    case OutOfPaper
    case NoToner
    case OnFire
}

func sendToPrinter(printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.NoToner
    }
    return "Job sent"
}

do {
    let printerResponse = try sendToPrinter("Bi Sheng")
    print(printerResponse)
} catch {
    print(error)
}

7 泛型

  • 泛型用尖括号<>来标识,跟Java里面一样。
func repeatItem<Item>(item: Item, numberOfTimes: Int) -> [Item] {
     var result = [Item]()
     for _ in 0..<numberOfTimes {
         result.append(item)
     }
     return result
 }
repeatItem("knock", numberOfTimes:4)

参考资料

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

推荐阅读更多精彩内容