盒子
盒子
文章目录
  1. 变量与常量
  2. 数组 (Array)
  3. 字典 (Dictionary)
  4. 元组(Tuple)
  5. 枚举类型(Enum)
  6. — Control Flow
    1. if
    2. for
    3. for-in
    4. while & do-while
    5. if-let
    1. 继承
    2. 初始化与反初始化
    3. 协议
    4. 扩展
  7. 函数
  8. closure
  9. 访问控制
  10. 运算符重载
  11. 泛型
    1. 字符串
  12. Others

iOS Swift

简单,安全,快

Ojbective-C 的方法名字太长

Swift 舍弃了null 而使用Optional 语言

变量与常量

  • 使用var声明变量,使用let声明常量
    let str = “String”
    var str = “String”

  • 类型推断: Swift是强类型的语言
    let str: String = “String”

其中String就是变量的类型。上面的:String 之所以可以省略是因为后面给变量str赋值了一个String类型的常量。
所以编译器能够推断出str也是String类型的。

数组 (Array)

在Swift中,Array和Dictionary是值类型的。所以使用简单的等号就可以完成拷贝了。不像有些语言还分深拷贝和浅拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var arrayOfIntegers : [Int] = [1,2,3]
// 隐式指定
var implicitArrayOfIntegers = [1,2,3]

// 也可以创建空数组,但必须提供其类型
let anotherArray = [Int]()

let arr = [2.0, 4.5, 3.7] // 数组常量的使用只需要用中括号里面加数组的元素;

let arrExplicit: [Double] // 显式的声明一个数组变量,则变量的类型为中括号,里面是每个元素的类型;

// for循环的条件不需要用括号括起来
// 0..<3 表示0到3的一个数组,但不包括3
// 0...3会包括3
for i in 0..<arr.count{
print(arr[i])
}
  • 数组的一些API:

arr.append(6.3)
arr.remove(at: 3)
arr.insert(10.9, at: 1)
arr.append(contentsOf: [3.5,6.8])
arr[0] = 89.23
arr.reversed()
arr.sort()

字典 (Dictionary)

  • 声明与使用:

    1
    2
    3
    4
    5
    var dictionary: [String:Int] = [
    "one" : 1,
    "two" : 2,
    "three" : 3
    ]
  • 赋值一个空的字典:
    var emptyDictionary: [Int:Int] = [:]

  • 字典取值:
    let value = dictionary[“one”]

  • 字典的添加,更新和删除

    1
    2
    3
    4
    var emptyDictionary: [Int:Int] = [:]
    emptyDictionary[1] = 12
    emptyDictionary.updateValue(14, forKey: 1)
    emptyDictionary.removeValue(forKey: 1)

元组(Tuple)

元组就是一种数据结构,里面包含一个或多个值,并且这些值可以是不同类型的。
元组中的值可以是命名的也可以是匿名的。如果是命名的,那么可以使用.符号来获取该值。

1
2
3
var tuple  = ("name",12)
var namedTuple = (name:"Name",age:12)
namedTuple.name = "updateName"
  • Tuple 的用处,方法返回多个返回值
1
2
3
func getNameAndAge() -> (String,Int){
return ("Ace",20)
}

枚举类型(Enum)

  • 声明与使用:

    1
    2
    3
    4
    5
    6
    7
    enum iOSDeviceType {
    case iPhone
    case iPad
    case iWatch
    }

    var myDevice = iOSDeviceType.iPhone
  • 当变量的类型已经明确时,赋值可以简化为:
    var myDevice: iOSDeviceType
    myDevice = .iPhone

  • Raw Value
    每个枚举都可以拥有自己的一个原生类型的raw value,所有的枚举关联的raw value必须
    是同一个类型的。当类型是Int时,默认按照枚举值的顺序递增其raw value。

    1
    2
    3
    4
    5
    6
    enum Direction: Int {
    case Up = 1
    case Down // will have the raw value 2
    case Left // will have the raw value 3
    case Right // will have the raw value 4
    }

— Control Flow

if

1
2
3
if 1+1 == 2 {
println("The math checks out")
}

for

1
2
3
4
5
var sum = 0
for var i = 0; i < 3; i++ {
sum += 1
}
sum // = 3

for-in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var firstCounter = 0
for index in 1 ..< 10 {
firstCounter++
}
// 循环9次

var secondCounter = 0
for index in 1 ... 10 { // 注意是三个句点,不是两个
secondCounter++
}
// 循环10次

let loopingArray = [1,2,3,4,5]
var loopSum = 0
for number in loopingArray {
loopSum += number
}
loopSum // = 15

while & do-while

1
2
3
4
5
6
7
var countDown = 5

while countDown > 0 {
countDown--
}

countDown
1
2
3
4
5
var countUP = 0
do {
countUp++
} while countUp < 5
countUp // = 5

if-let

if-let 语句检查一个可选变量是否包 含值。如果包含,则将这个值指定给一个常量变量,
然后运行某段代码。这样可以减少很 多行代码,同时又能够保证安全性。

1
2
3
4
5
6
7
var conditionalString : String? = "a string"
if let theString = conditionalString? {
println("The string is '\(theString)'")
} else {
println("The string is nil")
}
// 输出 "The string is 'a string'"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

class FirstClass {
let total: Double
let pro: String

// init方法是每个类的构造函数。不需要前缀func。
init(total: Double, pro: String) {
self.total = total
self.pro = pro
}

// 函数的返回值用-> 表示
func doSomeThing(param1: String, param2: String) -> String {
// 如何在控制台打印字符以及如何在字符中包含参数(使用反斜杠加括号)
print("do something \(str)")
return "over"
}

}

继承

要重写一个函数,要在子类中重新声明它,并添加 override 关键字

class Car: Vehicle {
// 继承类可以重写函数
override func description() -> String {
var description = super.description()
return description + “, which is a car”
} }

在一个被重写的函数中,可以通过 super 回调该函数在父类中的版本

override func description() -> String {
var description = super.description()
return description + “, which is a car”
}

初始化与反初始化

class InitAndDeinitExample {
// 指定的初始化器(也就是主初始化器)
init() {
print(“I’ve been created!”)
}
// 便捷初始化器,是调用上述指定初始化器所必需的
convenience init (text: String) {
self.init() // 这是必需的
print(“I was called with the convenience initializer!”)
}
// 反初始化器
deinit {
print(“I’m going away!”)
}
}

var example : InitAndDeinitExample?
// 使用指定的初始化器
example = InitAndDeinitExample() // 输出”I’ve been created!”
example = nil // 输出”I’m going away”
// 使用便捷初始化器
example = InitAndDeinitExample(text: “Hello”)
// 输出”I’ve been created!”
// 然后输出”I was called with the convenience initializer”
创建一个可以返回 nil 的初始化器(也称为可以失败的初始化器),就在 init 关键字的后面放上一个问号,并在初始化器确定它不能成功地构造该对象时,使用 return nil:

convenience init? (value: Int) {
self.init()
if value > 5 {
// 不能初始化这个对象;返回nil,表示初始化失败 return nil
} }
在使用一个可以失败的初始化器时,任何可以在其中存储该结果的变量都是可选的:

let failableExample = InitAndDeinitExample(value: 6)

协议

使用协议的好处是,可以利用 Swift 的类型体系来引用任何遵守某一给定协议的对象,个人现在理解为是Interface概念。

protocol Blinking{
var isBlinking:Bool{get}
var blinkSpeed: Double { get set }
func startBlinking(blinkSpeed: Double) -> Void

}

class Light:Blinking{
var isBlinking = false
var blinkSpeed = 1.2
func startBlinking(blinkSpeed: Double) {
print(“now my speed is (self.blinkSpeed)”)
}

}

扩展

extension Int {
var doubled : Int {
return self 2
}
func multiplyWith(anotherNumber: Int) -> Int {
return self
anotherNumber
} }

2.doubled // = 4
4.multiplyWith(32) // = 128
还可以利用扩展使一个类型遵守一个协议

extension Int : Blinking {
var isBlinking : Bool {
return false;
}
var blinkSpeed : Double {
get {
return 0.0; }
set {
// 不做任何事情
} }
func startBlinking(blinkSpeed : Double) {
print(“I am the integer (self). I do not blink.”)
} }
2.isBlinking // = false
2.startBlinking(2.0) // 输出”I am the integer 2. I do not blink.”

函数

  • 单返回值简单函数
    两个参数一个返回值,都为Int

func thirdFunction(firstValue: Int, secondValue: Int) -> Int {
return firstValue + secondValue
}
thirdFunction(1, 2)

  • 使用元组多返回值
    func fourthFunction(firstValue: Int, secondValue: Int)
    -> (doubled: Int, quadrupled: Int) {
    return (firstValue * 2, secondValue * 4)
    
    }
    fourthFunction(2, 4)

// 用数字访问:
fourthFunction(2, 4).1 // = 16

// 其他相同,只是使用了名字:
fourthFunction(2, 4).quadrupled // = 16

  • 外部名称调用
    在定义函数时,可以为参数指定名字。当无法马上明白每个参数的用途时,这一功能会非 常有用。可以像下面这样来定义参数名字:

func addNumbers(firstNumber num1 : Int, toSecondNumber num2: Int) -> Int {
return num1 + num2
}
addNumbers(firstNumber: 2, toSecondNumber: 3) // = 5

在为参数创建名字时,就是为参数创建一个内部名字和一个外部名字,一个参数的内部名字应当与外部名字相同。将同一个名字输 入两次也没有什么问题,但的确有一种简便的方式来定义一个外部名字与内部名字相同的 参数——就是在参数名之前放一个 # 符号

func multiplyNumbers(#firstNumber: Int, #multiplier: Int) -> Int {
return firstNumber * multiplier
}
multiplyNumbers(firstNumber: 2, multiplier: 3) // = 6

  • 将函数用作变量
    var numbersFunc: (Int, Int) -> Int;
    // numbersFunc现在可以存储任何接受两个Int并返回一个Int的函数

numbersFunc = addNumbers
numbersFunc(2, 3) // = 5

closure

sort需要传递一个闭包作为参数

var numbers = [2,4,34,6,33,1,67,20]
var numbersSorted = numbers.sort( { (first, second ) -> Bool in

return first < second

})
闭包只包含一行代码,可以省略 return 关键字

var numbersSorted = numbers.sort( { $1 > $0})
print(numbersSorted)
如果一个闭包是函数调用中的最后一个参数,可以将它放在括号外面。这纯粹是为 了提高可读性,不会改变闭包的工作方式

var numbersSorted = numbers.sort(){ $1 > $0}
print(numbersSorted)
闭包放在变量里面

var comparator = {(a: Int, b: Int) in a < b}
comparator(1, 2) // = true

访问控制

在将一个方法或属性声明为 public 时,App 中的所有人都能看到它:

// 可供所有人访问
public var publicProperty = 123

//如果将一个方法或属性声明为 private,那只能在声明它的源文件内部看到它:
// 只能在这个源文件中访问
private var privateProperty = 123

// 仅能供本模块访问
// 这里的’internal’是默认的,可以省略
internal var internalProperty = 123

运算符重载

类似C++的运算符重载

class Vector2D {
var x : Float = 0.0
var y : Float = 0.0
init (x : Float, y: Float) {
self.x = x
self.y = y
}

}
func +(left : Vector2D, right: Vector2D) -> Vector2D {
let result = Vector2D(x: left.x + right.x, y: left.y + right.y)
return result
}

let first = Vector2D(x: 2, y: 2)
let second = Vector2D(x: 4, y: 1)
let result = first + second

泛型

Swift与Java泛型相同

class Tree {
// ‘T’现在可以用作一种类型 var value : T
var value:T
var children : [Tree ] = []
init(value : T) {
self.value = value
}
func addChild(value : T) -> Tree {
var newChild = Tree(value: value)
children.append(newChild)
reutrn newChild
}
}

// 整数树
let integerTree = Tree(value: 5)
// 可以增加包含Int的子树
integerTree.addChild(10)
//用Swift设计程序 | 45
integerTree.addChild(5)
// 字符串树
let stringTree = Tree(value: “Hello”)
stringTree.addChild(“Yes”)
stringTree.addChild(“Internets”)

字符串

比较字符串

let string1 : String = “Hello”
let string2 : String = “Hel” + “lo”
if string1 == string2 {
println(“The strings are equal”)
}
查找字符串

if string1.hasPrefix(“H”) {
println(“String begins with an H”)
}
if string1.hasSuffix(“llo”) {
println(“String ends in ‘llo’”)
}
数据
let stringToConvert = “Hello, Swift”
let data = stringToConvert.dataUsingEncoding(NSUTF8StringEncoding)

Others

  1. Returning data from async call in Swift function
    -> pass callback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// in Bookshop class
func getGenres( completionHandler: (generes: NSArray) ->()) {
let task = session.dataTaskWithURL(url) {
data, response, error in
...
resultArray = results
completionHandler(genres: resultArray)
}
...
task.resume()
}

override func viewDidload() {
Bookshop.getGenres {
gernres in
println("view controller :\(genres)")
}
}
支持一下
扫一扫,支持forsigner
  • 微信扫一扫
  • 支付宝扫一扫