Posts /

Swift笔记

Twitter Facebook Google+
26 Feb 2019

待更新

Swift语言

[TOC]

速成文档。本文略去了大部分c语言类似部分,部分java类似部分,小部分python类似部分

写在一个文档里,便于使用Ctrl+F直接查找关键字就可使用

import

如果创建的是 OS X playground 需要引入 Cocoa

如果我们想创建 iOS playground 则需要引入 UIKit

标识符

如果一定要使用关键字作为标识符,可以在关键字前后添加重音符号(`),例如: ​

let `class` = "biu"

let 用于定义常量,定义完后不能修改。 var 用于定义变量,可以修改。

空格

编码规范要求 ​

let a = b + c

很容易报错,类似 ​

error: prefix/postfix '=' is reserved
error: consecutive statements on a line must be separated by ';'

print

public func print(items: Any..., separator: String = default, terminator: String = default)

如果我们想让其不换行输出,只需要将最后一个参数赋值为空字符串即可。

for x in 0...10{
print("\(x) ", terminator: "")
}
print()

输出结果为:0 1 2 3 4 5 6 7 8 9 10

接收用户的输入可以使用 readLine()

在字符串中可以使用括号与反斜线来插入变量: ​

import Cocoa

var name = "菜鸟教程"
var site = "http://www.runoob.com"

print("\(name)的官网地址为:\(site)")

数据类型

有点迷,注意首字母大写???

注意:swift3 中已经取消了++、–。

A += 1   // 类似 A++

区间运算符

闭区间运算符:1…5 区间值为 1, 2, 3, 4 和 5

半开区间运算符:1..< 5 区间值为 1, 2, 3, 和 4

for index in 1...5

类型别名

类型别名对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。

typealias newname = type

大概就是typedef

类型推断

let可作类型推断

类似void匹配各种数据但不是一个真的类型

var变量声明

var varB:Float

变量名也可以使用简单的 Unicode 字符

var 你好 = "你好世界"
print(你好)

可选类型Optional

以下两种声明是相等的:

var optionalInteger: Int?
var optionalInteger: Optional<Int>

在这两种情况下,变量 optionalInteger 都是可选整数类型

可选表示 “ 那儿有一个值,并且它等于 x “ 或者 “ 那儿没有值 “ 。

Optional 是一个含有两种情况的枚举,None 和 Some(T),用来表示可能有或可能没有值。

任何类型都可以明确声明为(或者隐式转换)可选类型。

当声明一个可选类型的时候,要确保 用括号给 ? 操作符一个合适的范围。例如,声明可选整数数组,应该写成 (Int[])? 

如果可选类型T?包含类型为T的任何值(也就是说它的值是 Optional.Some(T) ),这个可选类型等于 true,反之为 false。 ​ 如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值

optionalInteger = 42
optionalInteger! // 42

!用在nil上会报运行错误,nil就是null吧

var myString:String? = nil

if myString != nil {
    print(myString)
}else{
    print("字符串为 nil")
}

强制解析

当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值

import Cocoa

var myString:String?

myString = “Hello, Swift!”

if myString != nil { print(myString) }else{ print(“myString 值为 nil”) }

结果为 ​

Optional("Hello, Swift!")

2.

import Cocoa

var myString:String?

myString = "Hello, Swift!"

if myString != nil {
   // 强制解析
   print( myString! )
}else{
   print("myString 值为 nil")
}

结果为

Hello, Swift!

自动解析

使用感叹号(!)替换问号(?)

import Cocoa

var myString:String!

myString = "Hello, Swift!"

if myString != nil {
   print(myString)
}else{
   print("myString 值为 nil")
}

结果为

Hello, Swift!

可选绑定

判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量

可选绑定可以用在if和while语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。

常量

let constantName = <initial value>

类型标注: ​

var constantName:<data type> = <optional initial value>
let constB:Float = 3.14159

条件和循环

条件:

switch expression {
   case expression1  :
      statement(s)
      fallthrough /* 可选 */
   case expression2, expression3  :
      statement(s)
      fallthrough /* 可选 */
  
   default : /* 可选 */
      statement(s);
}

传统的for语句在swift3里弃用

但是现在用的4 = =

import Cocoa

var someInts:[Int] = [10, 20, 30]

for index in someInts {
   print( "index 的值为 \(index)")
}

while循环就得多用点了

import Cocoa
 
var index = 10

while index < 20 
{
   print( "index 的值为 \(index)")
   index = index + 1
}

没有do……while,把do改成repeat

字符串

字符串变量可修改 ‘+=’

字符串插值

import Cocoa

var varA   = 20
let constA = 100
var varC:Float = 20.0

var stringA = "\(varA) 乘于 \(constA) 等于 \(varC * 100)"
print( stringA )

字符串函数/运算符

函数/运算符 描述
isEmpty 判断字符串是否为空,返回布尔值
hasPrefix(prefix:String) 检查字符串是否拥有特定前缀
hasSuffix(suffix: String) 检查字符串是否拥有特定后缀。
Int(String) 转换字符串数字为整型
String.characters.count 字符串长度
utf8 可以通过遍历 String 的 utf8 属性来访问它的 UTF-8 编码
+ 连接两个字符串,返回一个新的字符串
< 判断两个字符串,对两个字符串的字符逐一比较
== 判断两个字符串是否相等

字符串分割数组 – 基于空格

let fullName = "First Last"
let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init)
// or simply:
// let fullNameArr = fullName.characters.split{" "}.map(String.init)

fullNameArr[0] // First
fullNameArr[1] // Last

字符

遍历字符串中的字符

import Cocoa

for ch in "Runoob".characters {
    print(ch)
}

字符串连接字符

import Cocoa

var varA:String = "Hello "
let varB:Character = "G"

varA.append( varB )

print("varC  =  \(varA)")

数组

创建

var someArray = [SomeType](repeating: InitialValue, count: NumbeOfElements)
var someInts = [Int](repeating: 0, count: 3)
var someInts:[Int] = [10, 20, 30]

使用 append() 方法或者赋值运算符 += 在数组末尾添加元素。

someInts.append(30)
someInts += [40]

数组遍历

字符串数组 ​

import Cocoa

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]

for item in someStrs {
   print(item)
}

输出

Apple
Amazon
Runoob
Google

如果我们同时需要每个数据项的值和索引值,可以使用 String 的 enumerate() 方法来进行数组遍历。

import Cocoa

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]

for (index, item) in someStrs.enumerated() {
    print("在 index = \(index) 位置上的值为 \(item)")
}

可以使用加法操作符(+)来合并两种已存在的相同类型数组

数组名.count 数组元素个数 只读属性 isEmpty 来判断数组是否为空

字典

Swift 字典每个值(value)都关联唯一的键(key),键作为字典中的这个值数据的标识符。

大概就是Map类型?

创建字典

	var someDict =  [KeyType: ValueType]()
	
	var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

访问字典

	var someVar = someDict[key]

返回的值是Optional类型。

添加 Key-Value 对

如果 key 不存在,则添加值,如果存在则修改 key 对应的值。

updateValue(_:forKey:)方法返回Optional值。 ​

	var oldVal = someDict.updateValue("One 新的值", forKey: 1)		

移除 Key-Value 对

使用 removeValueForKey() 方法来移除字典 key-value 对。如果 key 存在该方法返回移除的值,如果不存在返回 nil 。 ​

	var removedValue = someDict.removeValue(forKey: 2)

遍历字典

	for (key, value) in someDict {
		print("字典 key \(key) -  字典 value \(value)")
	}

字典转换为数组

	let dictKeys = [Int](someDict.keys)
	let dictValues = [String](someDict.values)
	
	for (key) in dictKeys {
	    print("\(key)")
	}
	for (value) in dictValues {
	    print("\(value)")
	}

count属性表示键值对数量;isEmpty

函数

定义

-> 后定义函数的返回值类型。

func funcname(形参) -> returntype
{
   Statement1
   Statement2
   ……
   Statement N
   return parameters
}

不带参没有void,无返回值无-> ​

调用

以下我们定义了一个函数名为 runoob 的函数,形参 site 的数据类型为 String,之后我们调用函数传递的实参也必须 String 类型,实参传入函数体后,将直接返回,返回的数据类型为 String。 ​

func runoob(site: String) -> String {
    return (site)
}
print(runoob(site: "www.runoob.com"))

其实意思就是

String runoob(String site) {
	return site;
}
printf("%s",runoob("www.runoob.com"));//site变量值为"www.runoob.com"

这里的site是局部参数名,只能在函数内部使用。

函数参数都有一个外部参数名和一个局部参数名。

外部参数名实现传参。

import Cocoa

func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}
pow(firstArg:5, secondArg:3)

a,b为局部参数名

另外两个长单词是外部参数名

如果你提供了外部参数名,那么函数在被调用时,必须使用外部参数名。

可变参数通过在变量类型名后面加入(…)的方式来定义

func vari<N>(members: N...){
    for i in members {
        print(i)
    }
}

vari(members: 4,3,5)

了解 可百度“泛型”

元组作为函数返回值 tuple

元组中的元素可以是任意类型,使用的是圆括号。

可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。

func minMax(array: [Int]) -> (min: Int, max: Int) {
    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)
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("最小值为 \(bounds.min) ,最大值为 \(bounds.max)")

如果你不确定返回的元组一定不为nil,那么你可以返回一个可选的元组类型。

例如(Int, Int)?或(String, Int, Bool)? ​

常量,变量及 I/O 参数

就是C++中的引用符号&改成inout

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

var x = 1
var y = 5
swapTwoInts(&x, &y)

_ 不知道干啥,是不是外部参数名

找了一些别的例子

func incrementor1(inout num: Int) {
    num += 1
}
var b = 10
incrementor1(&b)
b  // 11

这两种写法应该都行,不过外部参数吗在函数调用的时候可以不写

指针UnsafePointer是不可变的,无法修改指针的值

函数类型

参数类型+返回类型

定义一个叫做 addition 的变量,参数与返回值类型均是 Int ,并让这个新变量指向 sum 函数:

func sum(a: Int, b: Int) -> Int {
return a + b

​ }

var addition: (Int, Int) -> Int = sum

函数类型可作为参数类型、函数类型作为返回类型

函数嵌套

函数内定义一个新的函数,外部的函数可以调用函数内定义的函数。 这么刺激的嘛 但是好像就是在定义内部函数的位置就直接调用了它

闭包

就匿名函数

但它是一种引用类型,比如类和结构体也是引用类型,同样理解。

还有人说,可以把它作为一个引用类型的对象。可以把这个闭包的返回值(下面的返回值是一个函数)作为实例然后操作

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)

// 返回的值为10
incrementByTen()

// 返回的值为20
incrementByTen()

// 返回的值为30
incrementByTen()

// 返回的值为40
incrementByTen()

let alsoIncrementByTen = incrementByTen

// 返回的值也为50
print(alsoIncrementByTen())

​ ​ 这种写法有点刺激哦

let studname = { print("Swift 闭包实例。") }
studname()

输出结果为:

Swift 闭包实例。

接收两个参数并返回布尔值:

let divide = {(val1: Int, val2: Int) -> Int in 
   return val1 / val2 
}
let result = divide(200, 20)
print (result)

闭包表达式

sorted 方法

根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。 
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。

原数组不会被 sorted(by:) 方法修改。
 两个参数:

“大于” 表示 “按照字母顺序较晚出现”

Swift 自动为内联函数提供了参数名称缩写功能。

通过$数字来顺序调用闭包的参数。

var reversed = names.sorted( by: { $0 > $1 } )

更简单的方式:

var reversed = names.sorted(by: >)

尾随闭包

var reversed = names.sorted() { $0 > $1 }

捕获值

就函数里定义的函数可以捕获其外部函数所有的参数以及定义的常量和变量。

枚举

这些值是已经明确定义好的DaysofaWeek类型,不是01234。。了

一旦weekDay被声明为一个DaysofaWeek,你可以使用一个缩写语法(.)将其设置为另一个DaysofaWeek的值:

var weekDay = DaysofaWeek.THURSDAY 

var weekDay = .THURSDAY 

相关值和原始值

相关值有不同数据类型

enum {10,0.8,"Hello"}

enum Student{
    case Name(String)
    case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
    print("学生的名字是: \(studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。")
}

输出:

学生的成绩是: 98,97,95。


原始值数据类型相同,而且每个原始值在它的枚举声明中必须是唯一的。

在原始值为整数的枚举时,不需要显式的为每一个成员赋值,隐式赋值的值依次递增1。如果第一个值没有被赋初值,将会被自动置为0。

enum Month: Int {
    case January = 1, February, March, April, May, June, July, August, September, October, November, December
}

let yearMonth = Month.May.rawValue
print("数字月份为: \(yearMonth)。")

5

结构体

跟C不一样的地方:

这个文件这个词很迷哈,可以理解为java中的方法,然后自动生成方法的getter、setter就美滋滋了

定义:

struct MarkStruct{
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

实例化:

let marks = studentMarks()

所以结构体居然不是变量???? 生气哦

以下实例化通过结构体实例化时传值并克隆一个结构体:

struct MarksStruct {
   var mark: Int

   init(mark: Int) {
      self.mark = mark
   }
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct // aStruct 和 bStruct 是使用相同值的结构体!
bStruct.mark = 97
print(aStruct.mark) // 98
print(bStruct.mark) // 97

this这个词改成了self

结构体的作用

使用时:

结构体实例是通过值传递而不是通过引用传递。

这可真叫人伤心

不过它还有个类所以不懂结构体有存在的意义嘛?????不如枚举又不如类

与结构体相比新增了:

一句话就是类是引用类型了。

访问属性: 实例化类名.属性名

不能直接类名访问

恒等运算符

===:如果两个常量或者变量引用同一个类实例则返回 true

!==:引用不同类的实例

访问控制

internal

可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。

fileprivate

文件内私有,只能在当前源文件中使用。

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
	// 函数实现
}

大家都是private,函数前面也得写private

Setter的访问级别可以低于对应的Getter的访问级别


Twitter Facebook Google+