swift基本语法

2017-06-20  本文已影响18人  南冯

YES

常量和变量使用注意

var x = 0.0, y = 0.0, z = 0.0
var red, green, blue: Double

类型标注

整数范围

浮点数

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

类型推倒

类型别名

输出常量和变量

基本运算

逻辑分支

for循环

for i in 0..<10{
print(i)
}
for _ in 0..10{

}

while 循环

var c = 10
while c > 11  {
// 自增自减?????
    print("大于0")
}

dowhile

repeat {
    statements
} while condition

字符串

let age = 28
let info = "my name is \(name),my age is \(age)"
// 拼接字符串时的格式化
let min = 2
let sec = 3
let timestring  = String.init(format: "%02d:%02d", arguments:[min,sec])
let substr = (timestring as NSString).substring(to: 3)

数组

var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles 是一种 [Double] 数组,等价于 [0.0, 0.0, 0.0]
for (index, value) in shoppingList. enumerated() {
    print("Item \(String(index + 1)): \(value)")
}

集合

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits. intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits. symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]


let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]

houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true

字典

var dict = [String : AnyObject]()
let airportCodes = [String](airports.keys)
// airportCodes 是 ["YYZ", "LHR"]

let airportNames = [String](airports.values)
// airportNames 是 ["Toronto Pearson", "London Heathrow"]
for (key , value) in dictm{

}

元组

*元组的基本写法

let info = ("lili",18,1.88)
info.0
info.1
let info = (name :"lili",age : 18,height : 1.88)
info.name
info.age

forin

let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // 每5分钟呈现一个刻度线 (0, 5, 10, 15 ... 45, 50, 55)
}
可以在闭区间使用 stride(from:through:by:) 起到同样作用:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // 每3小时呈现一个刻度线 (3, 6, 9, 12)
}

可选类型

定义可选类型

* var name : Optional<String> = nil
* var name : String? = nil
var surveyAnswer: String?
// surveyAnswer 被自动设置为 nil
if name != nil {
print(name!)
}```

* 可选绑定
  * 判断name是否有值,如果没有值,直接不执行{}
  * 如果name有值,系统会自动将name进行强制解包,并且将解包后的结果赋值给name

if let name = name {
print(name)
}

* 你可以在可选绑定中使用常量和变量。如果你想在if语句的第一个分支中操作 actualNumber 的值,你可以改成 if var actualNumber,这样可选类型包含的值就会被赋给一个变量而非常量。
### 隐式解析可选类型

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感叹号来获取值

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // 不需要感叹号


### 错误处理
* 当一个函数遇到错误条件,它能报错。调用函数的地方能抛出错误消息并合理处理。

func makeASandwich() throws {
// ...
}

do {
try makeASandwich()
eatASandwich()
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}

NO

### 字符串
* 判断是否为""

if emptyString.isEmpty {
print("Nothing to see here")
}


* 字符串插值:您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:

let multiplier = 3
let message = "(multiplier) times 2.5 is (Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"

* 如果想要获得一个字符串中Character值的数量,可以使用字符串的characters属性的count属性:
* 

greeting[greeting.endIndex] // error
greeting.index(after: endIndex) // error

## Array

let oddNumbers = [1,3,5,7]

* 创建空数组
 * var emptyDoubles : [Double] = []
 * The full type name is also allowed
  var emptyFloats: Array<Float> = Array()

* 如果你需要一个使用默认值提前初始化的数组

let digitCounts = Array(repeatElement(0, count: 10))

### 比较运算符
* 注意: Swift 也提供恒等(===
)和不恒等(!==
)这两个比较符来判断两个对象是否引用同一个对象实例。
### 空合运算符
* a ?? b  表述的意思:a != nil ? a! : b

###元组比较
* Swift 标准库只能比较七个以内元素的元组比较函数。如果你的元组元素超过七个时,你需要自己实现比较运算符。
* 因为 Int 和 String 类型的值可以比较,所以类型为 (Int, String) 的元组也可以被比较。

### 区间运算符
* 闭区间运算符: 闭区间运算符(a...b)定义一个包含从 a 到 b(包括 a 和 b)的所有值的区间。a 的值不能超过 b
* 半开区间运算符:半开区间运算符(a..<b)定义一个从 a 到 b 但不包括 b 的区间。 之所以称为半开区间,是因为该区间包含第一个值而不包括最后的值。
### 逻辑组合运算符
* Swift 逻辑操作符 && 和 || 是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。
* 数组遍历

let streets = ["mahadun","newyork"]
for street in streets {
print("I don't live on \(street).")
}

* 判断数组是否为空 isEmpty

if oddNumbers.isEmpty {
print("数组为空")
}else{
print("i know(oddNumbers.count) odd Numbers")

}

*  取到数组的第一个 最后一个元素 ,如果数组为空,返回nil

if let firstElement = oddNumbers.first , let lastelement = oddNumbers.last {
print(firstElement, lastelement, separator: ", ")
}

* 利用角标访问数组元素,不在 0..<count 会报数组越界错误

* 增加或者删除数组元素

var students = ["ben","ivy","jodell"]
// 添加单个元素 append(_:) 一次添加多个元素 append(contentsOf:)
students.append("maxi")
students.append(contentsOf: ["shaki","william"])
// 插入一个或多个元素
students.insert("liam", at: 3)
// 删除元素
students.remove(at: 0)
// 删除最后一个
students.removeLast()

* 修改元素
students[0] = "dddd"

**当数组元素的个数超过初始容量,数组会将分配更大的内存区域并将其元素复制到新存储中。新存储空间是旧存储容量的倍数**

*  修改数组的副本copy
   * 如果数据类型为int 结构体类型,修改原数组内容不会影响副本的内容

var numbers = [1, 2, 3, 4, 5]
var numbersCopy = numbers
numbers[0] = 100
print(numbers)
// Prints "[100, 2, 3, 4, 5]"
print(numbersCopy)
// Prints "[1, 2, 3, 4, 5]"


 * 如果数组元素是对象

class InergerReference{
var value = 10
}
var firstIntegers = [InergerReference(),InergerReference()]
var secondInergers = firstIntegers
firstIntegers[0].value = 100
print(firstIntegers[0].value,secondInergers[0].value)
// 100 100
firstIntegers[0] = InergerReference()
print(firstIntegers[0].value,secondInergers[0].value)
// 10 100

*  Array 与 NSArray的转换 用as


## Dictionary
*  如何创建一个空字典
 var emptyDict: [String : String] = [:]
* 通过key来取值 取出来的值我可选项
 print(dictionary[200] ?? "")

if let message = dictionary[500]{
print(message)
}else{
print("meiyou改制")
}```

var interstingNumbers = ["primes" : [2,3,5,5,11,13],
                         "trianguler" : [1,3,4,56,6]]
for key in interstingNumbers.keys {
    interstingNumbers[key]?.sort(by: >)
}
print(interstingNumbers["primes"] ?? "")
var imagePaths = ["star": "/glyphs/star.png",
                  "portrait": "/images/content/portrait.jpg",
                  "spacer": "/images/shared/spacer.gif"]

for (key,value) in imagePaths {
    print("\(key) : \(value)")
}
var dict : [String : String] = Dictionary.init(minimumCapacity: 10)
dict["name"] = "lili"
dict.isEmpty
dict.count
imagePaths["star"]
imagePaths.index(forKey: "spacer")
imagePaths.first
imagePaths.keys
imagePaths.values
imagePaths.updateValue("falsh.png", forKey: "xxx")
imagePaths
imagePaths.removeValue(forKey: "flash")
imagePaths.removeAll()
imagePaths.enumerated()
imagePaths.makeIterator()
imagePaths.underestimatedCount
imagePaths.first

可选项 Optional

let shortForm: Int? = Int("33")
// 可选项包含两个分支 Optional.some
let number: Int? = Optional.some(44)
let nonumber: Int? = Optional.none
print(nonumber == nil)
let imagePaths = ["star": "/glyphs/star.png",
                  "portrait": "/images/content/portrait.jpg",
                  "spacer": "/images/shared/spacer.gif"]``` 
 * 解包方式一: if let 

if let starPath = imagePaths["star"] {
print("The star image is at '(starPath)'")
} else {
print("Couldn't find the star image")
}```

let defaultiamgepath = "/iamges/default.png"
let heartpath = imagePaths["heart"] ?? defaultiamgepath
let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultiamgepath
let num = Int("42")!
let isPng = imagePaths["star"]! .hasSuffix(".png")

switch 语句

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 无效,这个分支下面没有语句
case "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// 这段代码会报编译错误
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// 输出 "The letter A
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
var naturalCount: String
switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// 输出 "There are dozens of moons orbiting Saturn."
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// 输出 "(1, -1) is on the line x == -y"
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
    print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
     "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("\(someCharacter) is a consonant")
default:
    print("\(someCharacter) is not a vowel or a consonant")
}
// 输出 "e is a vowel"

控制转移语句

*Switch 语句中的 break
当在一个switch代码块中使用break时,会立即中断该switch代码块的执行,并且跳转到表示switch代码块结束的大括号(})后的第一行代码

let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description)
// 输出 "The number 5 is a prime number, and also an integer."

提前退出

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)")
    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }
    print("I hope the weather is nice in \(location).")
}

检测API的可用性 最后一个参数,*,是必须的,用于指定在所有其它平台中,如果版本号高于你的设备指定的最低版本,if语句的代码块将会运行

if #available(iOS 10, macOS 10.12, *) {
    // 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
    // 使用先前版本的 iOS 和 macOS 的 API
}

函数

func sumof(numbers:Int...) ->Int{
    var sum = 0
    for num in numbers {
        sum += num
    }
    return sum
}
sumof(numbers: 1,2,3,5)```
* swift中的默认参数

func makeCoffee(coffeename: String = "蓝山"){
print("我要喝(coffeename)咖啡")
}
makeCoffee()
makeCoffee(coffeename: "猫屎")

* 有参有返回值

func greet(name: String,day: String,number: Int) -> String{

return "Hello \(name),Today is\(day),\(number)"

}
print(greet(name: "zhangsan", day: "33", number: 23))


* 函数返回值为元组

可选元组类型如 (Int, Int)? 与元组包含可选类型如 (Int?, Int?) 是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
func calculate(scores: [Int]) -> (max: Int,min: Int,sum: Int){
var max = scores[0]
var min = scores[0]
var sum = 0

for num in scores {
    if num > max {
        max = num
    }else if num < min{
        min = num
    }
    sum += num
}
return (max,min,sum)

}
let statistics = calculate(scores: [3,4,5])
print(statistics.max)
print(statistics.0)

* 输入输出函数

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now (someInt), and anotherInt is now (anotherInt)")
// 打印 "someInt is now 107, and anotherInt is now 3"


* 函数作为返回类型

func makeIncrementer() -> ((Int,Int) -> Int){

func addNumber(num1: Int,num2: Int) -> Int{
    return num1 + num2
}
return addNumber

}

let add = makeIncrementer()
add(3,4)

* **函数作为参数(重点)**
 * 平方

func square(a: Float) -> Float{

return a * a

}
square(a: 2.0)```

func cube(a: Float) -> Float{
    
    return a * a * a
}
cube(a: 2.0)```
 * 平均值

func averageSumm(num1: Float,num2: Float,function:(Float -> Float)) -> Float{

return (function(num1) + function(num2))/2

}```

func test(){

    func demo(){}
    demo()
}
test()
var numbers = [1,3,2,5,63,7,0]
let sortNmbers = numbers.sorted(){
    
     $0 < $1
}
print(sortNmbers)

class Strudent : NSObject{
    // 定义存储属性
    var name: String?
    var age: Int = 0
    var mathScore: Double = 0
    var chineseScore: Double = 0
    
    // 定义计算型属性:通过别的方式计算得到结果的属性
    var averageScore: Double{
    // 在swift中如果使用当前对象的属性和方法不需要添加self
    return (mathScore + chineseScore) * 0.5
    }
    // 定义类属性: 类属性是和整个类相关的属性,而且是通过类名来进行访问
    static var courseCount: Int = 0
    
}
// 给类属性赋值
Strudent.courseCount = 2
let stu = Strudent()
//stu.age = 20
stu.name = "zhangsan"
stu.mathScore = 50
stu.chineseScore = 60
stu.averageScore
// 解包
if let name = stu.name {
    print(name)
}
// 可以利用KVC赋值
stu.setValue("lisi", forKey: "name")
class Person: NSObject{

//    var name: String?
    var name: String?{
        // 监听属性的变化
        willSet {// 属性即将改变时进行监听
        print("willsetlllll")
        }
        didSet {//属性已经改变时进行监听
        print("didsettttt")
        }
    
    }
    
    
    // 在构造函数中,如果没有明确super.init(),那么系统会帮助调用super.init()
    override init() {
        super.init()
        print("=====")
    }
    
    // 自定义构造函数
    init(name: String) {
        self.name = name
    }
    
    // 字典转模型
    init(dict: [String: AnyObject]) {
        super.init()
        setValuesForKeys(dict)
    }
    override func setValue(_ value: Any?, forUndefinedKey key: String) {
        
    }
}

//let p1 = Person.init()
//let p2 = Person.init(name: "lisi")
let p3 = Person.init(dict: ["name": "wangwu" as AnyObject,
                            "age": 24 as AnyObject
                            ])
print(p3.name ?? "")

便利构造函数

 1.遍历构造函数通常都是写在extension里面
 2.遍历构造函数init前面需要加载convenience
 3.在遍历构造函数中需要明确的调用self.init()
extension UIButton {

    convenience init(imageName: String,backGroundName: String) {
        self.init()
        setImage(UIImage.init(named:imageName), for:UIControlState())
        setImage(UIImage.init(named: imageName + "_highlighted"), for: .highlighted)
        setBackgroundImage(UIImage.init(named: backGroundName), for: .normal)
        setBackgroundImage(UIImage.init(named: backGroundName + "highlighted"), for: .highlighted)
        sizeToFit()
    }
}

重写一个类的description属性

    // MARK:- 重写description
    override var description: String{
    return dictionaryWithValues(forKeys: ["access_token", "expires_in", "uid"]).description
    }

点击事件需要添加@objc fileprivate 非对外方法添加fileprivate

GCD 的使用

        let group = DispatchGroup.init()
        // 入组
        group.enter()
        // 出租
        group.leave()
        // 通知
        group.notify(queue: DispatchQueue.main) { 
            // 执行code
        }
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { 
            // 执行code
        }

        let queue = DispatchQueue.init(label: "")
        queue.async { 
            <#code#>
        }

队列相关

// 创建队列
let queue = DispatchQueue(label: "com.appcoda.myqueue")
// 指定优先级
 let queue1 = DispatchQueue.init(label: "com.appcoda.myqueue1", qos:.background)

 // 创建一个并发队列
 let queue1 = DispatchQueue.init(label: "com.appcoda.myqueue1",attributes:.concurrent)

 //并发执行
queue1.async {
            for i in 100 ..< 110{
                print("😎",i)
            }
        }
// 获取全局队列
DispatchQueue.global()
// 主队列
DispatchQueue.main

workitem


  // workitem
    func useWorkItem() {
        var value = 10
        
        // 方法1
        let workItem = DispatchWorkItem {
            value += 5
        }
        workItem.perform()
        
        // 方法2
        let queue = DispatchQueue.global(qos: .utility)
        
        queue.async(execute: workItem)
        
        //通知
        workItem.notify(queue: DispatchQueue.main)        {
            print("value = ", value)
        }
    }

闭包

{ (parameters) -> returnType in
    statements
}

枚举

与 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的CompassPoint例子中,north,south,east和west不会被隐式地赋值为0,1,2和3。相反,这些枚举成员本身就是完备的值,这些值的类型是已经明确定义好的CompassPoint类型。
enum CompassPoint {
    case north
    case south
    case east
    case west
}
enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
directionToHead = .south
switch directionToHead {
    case .north:
        print("Lots of planets have a north")
    case .south:
        print("Watch out for penguins")
    case .east:
        print("Where the sun rises")
    case .west:
        print("Where the skies are blue")
}
// 打印 "Watch out for penguins”

判断一个枚举类型的值时,switch语句必须穷举所有情况。如果忽略了.west这种情况,上面那段代码将无法通过编译,因为它没有考虑到CompassPoint的全部成员。强制穷举确保了枚举成员不会被意外遗漏。

let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}
// 打印 "Mostly harmless”
let earthsOrder = Planet.earth.rawValue
// earthsOrder 值为 3

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection 值为 "west"
indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

类和结构体

class SomeClass {
    // 在这里定义类
}
struct SomeStructure {
    // 在这里定义结构体
}
let vga = Resolution(width:640, height: 480)

属性

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// 该区间表示整数0,1,2,3
rangeOfFourItems.firstValue = 6
// 尽管 firstValue 是个变量属性,这里还是会报错

这种行为是由于结构体(struct)属于值类型。当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。

属于引用类型的类(class)则不一样。把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性

必须将延迟存储属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。注意
如果一个被标记为 lazy 的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次。

struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

注意
必须使用 var 关键字定义计算属性,包括只读计算属性,因为它们的值不是固定的。let 关键字只用来声明常量属性,表示初始化后再也无法修改的值

struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// 打印 "the volume of fourByFiveByTwo is 40.0"
class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

全局变量和局部变量

注意全局的常量或变量都是延迟计算的,跟[延迟存储属性]相似,不同的地方在于,全局的常量或变量不需要标记lazy
修饰符。局部范围的常量或变量从不延迟计算。

方法

结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。

但是,如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择可变(mutating)行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的self属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。

要使用可变方法,将关键字mutating 放到方法的func关键字之前就可以了

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// 打印 "The point is now at (3.0, 4.0)"

注意,不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性,

let fixedPoint = Point(x: 3.0, y: 3.0)fixedPoint.moveByX(2.0, y: 3.0)// 这里将会报告一个错误
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}

类型方法

注意
在 Objective-C 中,你只能为 Objective-C 的类类型(classes)定义类型方法(type-level methods)。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含

下标

Swift 的Dictionary类型的下标接受并返回可选类型的值。上例中的numberOfLegs字典通过下标返回的是一个Int?或者说“可选的int”。Dictionary类型之所以如此实现下标,是因为不是每个键都有个对应的值,同时这也提供了一种通过键删除对应值的方式,只需将键对应的值赋值为nil即可。

继承

class SomeClass: SomeSuperclass {
    // 这里是子类的定义
}

重写

在方法someMethod()的重写实现中,可以通过super.someMethod()来调用超类版本的someMethod()方法。
在属性someProperty的 getter 或 setter 的重写实现中,可以通过super.someProperty来访问超类版本的someProperty属性。
在下标的重写实现中,可以通过super[someIndex]来访问超类版本中的相同下标。
注意
你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值是不可以被设置的,所以,为它们提供willSet或didSet实现是不恰当。
此外还要注意,你不可以同时提供重写的 setter 和重写的属性观察器。如果你想观察属性值的变化,并且你已经为那个属性提供了定制的 setter,那么你在 setter 中就可以观察到任何值变化了。

防止重写

构造过程

你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。

注意
当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察者。

*构造过程中常量属性的修改 你可以在构造过程中的任意时间点给常量属性指定一个值,只要在构造过程结束时是一个确定的值。一旦常量属性被赋值,它将永远不可更改。

注意
对于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。

struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)

类的继承和构造过程

注意
子类可以在初始化时修改继承来的变量属性,但是不能修改继承来的常量属性。

�### 析构 deinit

deinit {
    // 执行析构过程
}

扩展

extension SomeType {
    // 为 SomeType 添加的新功能写到这里
}

extension SomeType: SomeProtocol, AnotherProctocol {
    // 协议实现写到这里
}

注意
扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器。

闭包

{ (parameters) -> returnType in
    statements
}
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函数体部分
}

// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure(closure: {
    // 闭包主体部分
})

// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
    // 闭包主体部分
}
上一篇下一篇

猜你喜欢

热点阅读