【Swift官方助读】重点摘取

2017-01-14 10:46:42来源:http://www.jianshu.com/p/9d8588bb6aa9作者:攀Dar人点击

Swift概览

1 基本的字符串操作 输入输出在swift中无需引入库文件


2 在全局写代码作为程序的入口,因而无需main()函数也无需在每句statement后加分号


3 "this is my number" + String(appleNum) 字符串中插入字符串 方法用+号及强转字符串


4 "this is my number (appleNum + orangeNum)" 在字符串中引用别的类型时可以这样的形式


5 数组字典


var shoppingList = ["1", "2", "3"]
var shoppingList1 = [String]()
var shoppingList2 = []; //官方并未举这个例子创建数组 但该方法用于一次性置空已存在的数组
shoppingList[1] = "4"
shoppingList = []
var diction = ["location":"Beijing", "weather":"Cloudy", "transport":"Good"]
var diction1 = [NSString: NSString]()
var diction2 = [:] //同样不是官方推荐初始化方法 但该方法用于一次性置空已存在的字典
diction["population"] = "50000"
diction = [:]

6 if 语句必须是Bool判断表达式 而不会默认拿一个值与0进行比较了 所以要想截获单纯值可能失败的情况则需要引入optional值了 var optionalString: String? = "Hello" , print(optionalString == nil) 来比较要么用if let name = optionalName {}来判断 并得到解绑的值给name


7 (optionalNickName ?? noneOptionalDefaultName) 这个??符号表示如果前面的可选值为nil那么久直接返回后面的非可选值


8 switch支持任意对象 和 更多的比较操作而不仅仅是integer的相等操作 且不再需要break来标注结束该case默认成功就不会往下执行


let fullName: String = "John Appleseed"
switch fullName {
case "John":
print("yes here")
case "John Appleseed", "JUST":
print("Hi it's me")
case let x where x.hasSuffix("pepper"):
print("pepper now")
default:
print("None")
}

9 for in 函数可以直接遍历字典数据类型了 注意字典是无序的所以结果也是随机的顺序


let interestingNumbers = [
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
print(largest)

10 循环While 既可放在前面也可以放在后面 放在后面记得加上repeat 如果要循环也可以用上面的for in 注意:..< 不包含最右值 ...都包含左右值


//【0】
var n = 2
while n < 100 {
n = n * 2
}
print(n)
//【1】
var m = 2
repeat {
m = m * 2
} while m < 100
print(m)
//【2】
var total = 0
for i in 0..<4 {
total += i
}
print(total)

11 func 方法 参数列表 与返回值的划分 用 -> 区分 前面是参数后面是返回值 参数和返回值的名在前类型在后


//调用时参数名为默认方法的参数名一致
func getMyName(withKey: String, day: String) -> String{
return withKey + "is Friday /(day)"
}
getMyName(withKey: "Yes", day: "No")
//如果想隐藏或自定义可以加前下划线或者加多一个参数
func greet(_ person: String, on day: String) -> String {
return "Hello /(person), today is /(day)."
}
greet("John", on: "Wednesday")
//返回tuple多参数的返回值 返回值可以通过名称拿到也可通过索引获取
func calculateStatistics(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 statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)
print(statistics.2)
//除了可以有数组列表做参数 还可以用某一个类型的未知个数列表做参数
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(numbers: 42, 597, 12)
//与上面的区别就是直接传数组 需要创建数组
func sumOfNumberWith(numbers: [Int]) ->Int{
var sum = 0
for number in numbers {
sum += number
}
return sum
}
let array = [1, 2, 5]
sumOfNumberWith(numbers: array)

12 Function可以嵌套 在嵌套的方法中可以使用嵌套方法以外的方法内的变量 且方法是一等类型所以方法可以返回方法 也可以当做方法的传参


Function是一个特殊的块能被稍晚再调用,并能访问位于块被创建区域内的其它变量和方法
func lessThanTen(number: Int)-> Bool{
return number < 10
}
func hasAnyMatches(list: [Int], condition: (Int) -> (Bool)) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func haseAnyMatches(list: Int..., condition: (Int) -> (Bool)) -> Bool{
for item in list {
return condition(item)
}
return false
}
let list = [20, 25, 31, 11, 20]
haseAnyMatches(list: 15, 19, 29, condition: lessThanTen)
hasAnyMatches(list: list, condition: lessThanTen)
//闭closure与方法作为参数调用的区别就是把整个方法体都写进来了
//如果这个块作为方法参数已经很明确了即可直接忽略参数类型和返回值 更精简
//也可以省略参数使用下标来获取 既然参数都没有了 那就直接省略了in这个区分参数和返回值的符号
let result1 = haseAnyMatches(list: 15, 19, 29, condition: lessThanTen)
let result2 = haseAnyMatches(list: 15, 19, 29, condition: {(number: Int) -> Bool in return number < 10})
let result3 = haseAnyMatches(list: 15, 19, 29, condition: {number in return number < 10})
let result4 = haseAnyMatches(list: 15, 19, 29, condition: {return $0 < 10})
result1
result2
result3
result4

13 代码规范


// 1 一个类型实现一个协议时建议单独声明一个扩展,保证逻辑性分离 如
class MyViewcontroller: UIViewController {
// class stuff here
}
// MARK: - UITableViewDataSource
extension MyViewcontroller: UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewcontroller: UIScrollViewDelegate {
// scroll view delegate methods
}
//不推荐实现的所有协议写在一起
class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
// all methods
}
// 2 代码分区
// MARK: -
// 3 更多的使用LET,而不是VAR
// 4 不建议直接命名顶级变量,建议定义在结构体或者枚举内部,用static let 声明。 可以给这些变量一个合适的命名空间
enum Math {
static let e = 2.718281828459045235360287
static let pi = 3.141592653589793238462643
}
radius * Math.pi * 2 // circumference
// 5 对于一个可选类型var foo = Type? 不要使用强制解包
foo!.doSomethind()
使用可选绑定,或者可选链操作
if let foo = foo {
// Use unwrapped `foo` value in here
} else {
// If appropriate, handle the case where the optional is nil
}
foo?.callSomethingIfFooIsNotNil()
// 6 首选STRUCT而非CLASS 在非必需(比如没有生命周期)的时候使用struct,因为多态可以使用protocl实现 继承可以使用组合实现 值类型容易辨别,更可以用let去推测不可变的行为
// 7 只有在闭包或者命名冲突等必须时才使用SELF 忘掉Objective-C到底时使用self.pro 还是_ivar的访问方式,对于swift内部调用properties或者method省略掉self
// 8 对于只读的属性或者下标语法,使用隐式的GETTER方法
建议
var myGreatProperty: Int {
return 4
}
subscript(index: Int) -> T {
return objects[index]
}
不建议完整的写法,比较繁琐
var myGreatProperty: Int {
get {
return 4
}
}
subscript(index: Int) -> T {
get {
return objects[index]
}
}

14 类和对象


初始化用init
对象销毁前清理deinit
class Shape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "Shape with /(numberOfSides) sides"
}
}
let shape = Shape(name: "Triangle")
shape.numberOfSides = 3
let descriptionStr = shape.simpleDescription()
descriptionStr
class Square: Shape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
//不能同时和get或者set同时存在
// willSet {
//
// sideLength = newValue * 3.0
// }
//
// didSet {
//
// }
}

override func simpleDescription() -> String {
return "square sides with sides of /(sideLength)"
}
}
let squareInstance = Square(sideLength: 20, name: "FourSquares")
squareInstance.area()
squareInstance.simpleDescription()
squareInstance.perimeter
squareInstance.perimeter = 9
squareInstance.perimeter

15 Enumerations


默认是从0开始 自动按顺序增加1 但你可以通过给其赋不一样的值如浮点型或字符串赖改变这一默认行为 rawValue是对应的case的你所指定的值如果不指定 默认是Int类型就会自动以你指定的最后那一个后面开始加1 
另外虽然case只有三个 但每个case中如果有多个选项且是Int类型则还是依然会自动增加的只是这几种情况都做同一种case的处理而已 后面取值时同一个case下的三种情况对应三种取值
case时不要再认为case的值是rawValue的一个体现就像其他语言中是int的一个别名而已代表实际的int值 因为如果非必要rawValue有意义甚至可以不用设置rawValue 因而这个case所对应的值其实就是实际的枚举值 且这个rawValue必须要enum的type是确定的 不然是无法设置获取这个值得
enum Rank: Int {
case ace = 1
case two = 3, three = 5, four
case five, six, seven
//写成 .clubs因为知道这个常量就是枚举型的
func simpleDescription() -> String {
switch self {
case .ace:
return "ace123"
case .two, .three, .four:
return "two_three_four"
default:
return String(rawValue)
}
}
}
//第一种初始化 不能写成 .clubs因为还不知道这个常量是什么类型的
let rankOne = Rank.five
let rankOne: Rank = .five //或者这样也是可以的 因为知道类型
rankOne.simpleDescription()
rankOne.rawValue
//第二种初始化方法
let rankTwo = Rank(rawValue: 4)
rankTwo?.rawValue
//rawValue只有在有type类型时才会有且与初始化时的值一致
enum Suit: String {
case spades, hearts, diamonds, clubs
}
let suitOne = Suit.diamonds
suitOne.rawValue
let suitTwo = Suit(rawValue: "hearts")
suitTwo?.rawValue
//enum的rawValue都是一样的 关联值可以每次创建时不一样
enum ServerResponse {
case result(String, String)
case failure(String)
}
let success = ServerResponse.result("6:00 am", "8:09 pm")
//拥有关联值得enum在switch时也会有所不同
//另外也可单独截取关联值出来 比如在switch中用let
switch success {
case let .result(sunrise, sunset):
print("Sunrise is at /(sunrise) and sunset is at /(sunset).")
case let .failure(message):
print("Failure... /(message)")
}

16 Structures


结构体和类非常类似 只是前者是值传递 后者是引用的传递
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The /(rank.simpleDescription()) of /(suit.simpleDescription())"
}
}

17 Protocol


protocol ExampleProtocol{
var simpleDescription: String {get}
mutating func adjust()
}
class SimpleClass: ExampleProtocol {
//实现协议需要的属性和方法 不然报错
var simpleDescription: String = "SimpleDescription"
var simpleOtherProperty: String = "OtherProperty"
func adjust() {
simpleDescription = simpleDescription + "_____"
}
}
//因为是值类型 需要显示写上mutating才能修改结构体自身的属性值 class不需要因为class本身可以修改自身
struct SimpleStruct: ExampleProtocol{
var simpleDescription: String = "SimleStruct"
mutating func adjust() {
simpleDescription = simpleDescription + "******"
}
}
var a = SimpleClass()
a.adjust()
a.simpleDescription
var b = SimpleStruct()
b.adjust()
b.simpleDescription

18 Extension


extension Int: ExampleProtocol {
var simpleDescription: String {
return "Description__"
}
mutating func adjust() {
self += 4
}
}
7.simpleDescription
var digit: Int = 8
digit.adjust()
digit
let valueOfProtocol: ExampleProtocol = a
valueOfProtocol.simpleDescription
valueOfProtocol.simpleOtherProperty //找不到这个属性 类型是协议所以能拿到的东西仅限于协议内的而哪怕赋值了一个遵循了协议的对象 但也是拿不到那个对象的协议外的东西了

19 ErrorHandle


//系统的协议ErrorProtocol
enum PrintError: ErrorProtocol {
case outOfPager
case noToner
case onFire
}
//方法参数后写上throws标记这个方法有抛出异常功能 然后在需要抛出异常的地方写上throw
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "NeverHasToner" {
throw PrintError.noToner
}
return "JobSuccess"
}
//关于捕捉错误
//try可以不需要返回值 也可以接受返回值 catch在失败的时候才会走且do里面try失败后的都不会再走了 catch里的error是系统返回的错误码变量
do {
try send(job: 8080, toPrinter: "NeverHasToner")
} catch {
print(error)
}
do {
let result = try send(job: 8080, toPrinter: "NeverHasToneroooooo")
print(result)
let result1 = try send(job: 8080, toPrinter: "NeverHasToner")
print(result1)
} catch {
print(error)
}
//也可以像switch通过case来检验捕捉到的错误的具体case
do {
let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
print(printerResponse)
} catch PrintError.onFire {
print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrintError {
print("Printer error: /(printerError).")
} catch {
print(error)
}
//或者也可以通过try?获取抛出异常的结果是否为nil
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")

20 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("banana")
print(fridgeIsOpen)

21 Generics


enum OptionalValue<Wrapped> {
case none
case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none
possibleInteger = .some(100)
func anyCommonElements<T: Sequence, U: Sequence where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element>(_ lhs: T, _ rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
//<T: Equatable> is the same as writing <T where T: Equatable>

22 第一章


1. 如果值不用改变永远优先使用常量胜过变量
2. 可以联排定义多个同类型的变量或常量 var red, green, blue: Double
3. 声明时如果有赋初始值则类型不需要写 因为类型推导是swift的一大特性
4. 支持这个命名哦 let

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台