swift 学习(一)

swift学习

一、基础部分

1. 常量(let) 变量(var
swift能够自己推断变量的类型,可以不用写变量的类型
let test = "你好,世界!!"
let test:String = "你好,世界!!"
var π:Double = 3.14
2. 类型转换
如果常量和变量的类型不一致,必须把类型转成一致的以后在做运算,但是如果是字面量的话,swift会自动判断类型,所以不用转换
字面量:就是表达式右边的值,就叫字面量,
let three = 3
let pi = 3.14
let threeAndPi = (Double)three + pi (正确)
let threeAndPi = three + pi          (错误)
let threeAndPi = 3 + 3.14
3. 可选类型(Optional)

为什么需要Optional,因为非可选类型不能赋值为nil

var surveryAnswer:String = nil (错误)
var surveryAnswer:String? = nil (正确)
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感叹号来获取值
let assumedString: String! = "An implicitly unwrapped optional string." 
let implicitString: String = assumedString // 不需要感叹号

基本运算符

1. 三目运算符 、空和运算符
三目运算符
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20) // rowHeight 现在是 90

空合运算符:是为了判断Optional类型为nil的时候,提供默认值,与三目运算符有区别
let defaultColorName = "red"
var useDefineColorName:String?
let defineColorName = useDefineColorName ?? defaultColorName
2. 区间运算符

闭区间
a…b
半开区间
a..

集合类型

1. 数组Arrays
创建空数组
var someInts = [Int]()
var someInts = []
var threeDoubles = Array(repeatElement(0.0, count: 3))

一次改变数组中的多个值
shoppingList[4...6] = ["Bananas", "Apples"]
2. 集合Set
创建集合
var favoriteGenres:Set<String> = ["Rock","Classical","Hip hop"]

移除元素
let rock = favoriteGenres.remove("Rock")
print(rock!)

遍历集合
for item in favoriteGenres {
print(item)
}
集合操作
• 使用 intersection(_:) 方法根据两个 合中都包含的值创建的一个新的 合。
• 使用 symmetricDifference(_:) 方法根据在一个 合中但不在两个 合中的值创建一个新的 合。 • 使用 union(_:) 方法根据两个 合的值创建一个新的 合。
• 使用 subtracting(_:) 方法根据不在该 合中的值创建一个新的 合
。
 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).sort()
 // [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]
3. 字典 Dictionary
//创建字典
var ariports:[String:String] = ["LHR":"London"]
//修改字典
ariports.updateValue("ShangHai", forKey: "LHR")
ariports["LHR"] = "Asia"
//遍历字典
for (ariportsCode,ariportsValue) in ariports {
print(ariportsCode+":"+ariportsValue)
}

for ariportsCode in ariports.keys {
print(ariportsCode)
}

for ariportsValue in ariports.values {
    print(ariportsValue)
}
4.控制流
//闭区间
for item in 1...5 {
    print(item)
}
//开区间
for item in 1..<5 {
    print(item)
}
//用 _ 忽略item的值
var base = 0
for _ in 1...5 {
    base += 1
}
print(base) //:  base = 5
//while 循环
repeat {
 statements
} while condition

//switch 
let someCharacter:Character = "z"
switch someCharacter {
case "c": //错误 ,case后面必须有语句
case "z":
    print("The letter first of the alphabat")
case "a":
    print("The letter last of the alphabat")
default:
    print("some other character")

}
switch someCharacter {
case "c","z": //正确 ,
    print("The letter first of the alphabat")
case "a":
    print("The letter last of the alphabat")
default:
    print("some other character")
}
// 可以用 _ 匹配所有可能的值
// 如果存在多个匹配,那么只会执行第一个被匹配到的 case 分支。考虑点(0, 0)会首先匹配 case (0, 0) ,因此剩下的能够匹配的分支都会被忽视掉

let anthorPoint = (0,0)
switch anthorPoint {
case (0,0):
    print("origin")
case (_,0):
    print("_ 0 \(anthorPoint)")
case (0,_):
    print("0 _ \(anthorPoint)")
case (-2...2,-2...2):
    print("-2...2 \(anthorPoint)")
default:
    break
}
值绑定(Value Bindings)
case 分支允许将匹配的值绑定到一个临时的常量或变量,并且在case分支体内使用 —— 这种行为被称为值绑 定(value binding),因为匹配的值在case分支体内,与临时的常量或变量绑定。
下面的例子展示了如何在一个 (Int, Int) 类型的元组中使用值绑定来分类下图中的点(x, y):

 let anotherPoint = (2, 0)
 switch anotherPoint {
 case (let x, 0):
     print("on the x-axis with an x value of \(x)")
 case (0, let y):
     print("on the y-axis with a y value of \(y)")
 case let (x, y):
     print("somewhere else at (\(x), \(y))")
 }
// 输出 "on the x-axis with an x value of 2"
Where

case 分支的模式可以使用 where 语句来判断额外的条件。
下面的例子把下图中的点(x, y)进行了分类:

 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"

fallthrough 关键字不会检查它下一个将会落入执行的 case 中的匹配条件。 fallthrough 简单地使代 码继续连接到下一个 case 中的代码,这和 C 语言标准中的 switch 语句特性是一样的

// 验证API的可用性
if #available(platform name version, ..., *) { 
    APIs 可用,语句将执行
} else {
    APIs 不可用,语句将不执行
}

函数

函数返回可以是可选类型 Optional ,当返回值为nil 的时候用可选类型

 func minMax(array: [Int]) -> (min: Int, max: Int)? {
 if array.isEmpty { return nil }
 var currentMin = array[0]
 var currentMax = array[0]
 for value in array[1..<array.count] {
     if value < currentMin {
         currentMin = value
     } else if value > currentMax {
         currentMax = value
     }
    }
     return (currentMin, currentMax)
 }

你可以在函数名称前指定它的参数标签,中间以空格分隔。可用(_)忽略参数标签

func someFunction(argumentLabel paramterName:Int)->Void {
print(paramterName)
}
someFunction(argumentLabel: 2)

函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误(compile-time error)。这意味着你不能错 误地更改参数值。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那 么就应该把这个参数定义为输入输出参数(In-Out Parameters)。

func swapTwoInts(_ a: inout Int,_ b: inout Int)->Int{
let tempoary:Int = a
a = b
b = tempoary
return tempoary
}
var aa = 10
var bb = 20
print(swapTwoInts(&aa, &bb)) // : 10

闭包

()->Void 简单的闭包定义。
逃逸闭包 @escaping ,闭包作为参数传入函数的时候,如果是逃逸闭包的话此闭包是被self,引用的。也就是引用计数会加1,即使函数执行之后,self引用也不会释放。

class A {
func someMethod(cloure: @escaping()->String){

    print("some:\(cloure)")
}

}
class B {
var somePerproty = “hello”
let classA = A()
func testCloure(){
classA.someMethod {
self.somePerproty = “test”
return self.somePerproty
}
print(“some:(somePerproty)”)
}
}

枚举

当不需要匹配每个枚举成员的时候,你可以提供一个 default 分支来涵盖所有未明确处理的枚举成员:

let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}

枚举的关联值。

  • 可以让枚举值对应的原始值不是唯一的, 而是一个变量.
  • 每一个枚举可以是在某种模式下的一些特定值
enum lineSegmentDescriptor{
    case StartAndEndPattern(start:Double, end:Double)
    case StartAndLengthPattern(start: Double, length:Double)
}

var lsd = lineSegmentDescriptor.StartAndLengthPattern(start: 0.0, length: 100.0)
lsd = lineSegmentDescriptor.StartAndEndPattern(start: 0.0, end: 50.0)

print(lsd)
// 输出结果: StartAndEndPattern(0.0, 50.0)

注意
原始值和关联值是不同的。原始值是在定义枚举时被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终不变。关联值是创建一个基于枚举成员的常量或变量时才设置的值,枚举成员的关联值可以变化。

枚举原始值隐式赋值。
在使用原始值为整数或者字符串类型的枚举时,不需要显式地为每一个枚举成员设置原始值,Swift 将会自动为 你赋值。

如果mercury没有默认值,那么就是0,随后递增,
 enum Planet: Int {
     case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

字符串默认值就是字符串本身
enum CompassPoint: String {
     case north, south, east, west
}

使用关键字indirect 表示枚举成员是可递归的。

类和结构体

结构体和枚举和基本的数据类型一样是’值类型’,也就是数据传递的时候,都是copy一个副本。类是引用。

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

这时候修改cinema的属性,对hd不会有影响。

如果创建了一个结构体struct的实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使有属性被声明为变量也不行,但是类 class 可以修改属性,即使类被定义成常量:

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

延迟存储属性
延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标示一个延迟存 储属性。

注意
必须将延迟存储属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得 到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。

类型属性用关键字static,如果需要在子类中重写需要用关键字class,类型方法同理,

class ViewMode {
static  var interlaced = false
var frameRate = 0.0
var name:String?
func someViewMode() {
    //这里会出现编译错误,因为`interlaced` 是类型属性,而
    // `someViewMode` 方法不能修改类型属性
    interlaced = false
     //这样写不会报错
    ViewMode.interlaced = false
}
//如果需要修改`interlaced` ,需要把方法定义成类型方法
static func someViewMode1() {
    interlaced = false
}
}

注意:结构体和枚举与类有一些区别。结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。

struct LevelTracker {
static var highestUnlockLevel = 1
var currentLevel = 1
static func unlocked(level:Int){
    if level>highestUnlockLevel {
        highestUnlockLevel = level
    }
}
//如果需要访问`currentLevel` 属性,需要把方法定义成`mutating`
mutating func someLevel() {
    currentLevel = 0
}
static func isUnlocked(level:Int)->Bool {
    return level<=highestUnlockLevel
}
func somePoperty() {
    //这样写也会编译错误
    LevelTracker.currentLevel = 1
    //这个访问类型属性不会报错
    LevelTracker.highestUnlockLevel = 0
    }
}

还有要注意一下,如果结构体和枚举的实例是常量,那么就不能修改他们的属性,不论属性是常量还是变量,因为结构体和枚举都是值类型,和类不同。

let fixedPoint = Point(x: 3.0, y: 3.0)   fixedPoint.moveByX(2.0, y: 3.0)
// 这里将会报告一个错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值