参考:http://blog.csdn.net/fengsh998/article/details/28258805
1.常量和变量的定义。
常量使用let 进行约束, 变量使用var来约束,相信大家对var并不陌生,如早期的VB, pascal,js等都会有这样的定义。
swift对常量,和变量的约束,编译更加精确,有时候用户可以不需要声明某个常量是什么类型,像通常 声明一个变量 int b = 0;
而 在swift中使用var b=0 即可,swift可根据初始化的值进行判断是变量是什么类型,如果var 中没有指定足够的信息(当然是机算判断变量类型的信息时,)可以使用分号进行加以说明,
变量的声明与使用
let implicitInteger = 70 //会自动识别为integer
let implicitDouble = 70.0
let explicitDouble: Double = 70 //加上类型说明
变量的声明与使用
var myVariable = 42
myVariable = 50
var explicitVariable:Double = 60
//下面编译不会通过的,因为等式左右的数据类型不一样,而且不能隐式转换
//由此可以说swift的数据类型是安全的
var uint32Value:UInt32=uint8Value+uint16Value
//swift的类型转换 //swift不允许不同的数据类型,进行转换和赋值的,即便是Int的子类 let doubleValue:Double=12.345 var intVar:Int=3 var floatVar:Float=23.3456; //强转 //不同的数据类型是可以强转的,同一数据类型不同的子集也是不可以强转的 intVar=Int(doubleValue) print(intVar) floatVar=Float(doubleValue) print(floatVar)
常量变量可以用中文,这个略屌..
let 我老婆="我现在的女朋友" println(我老婆)
还有一点有意思是变量或常量的命名名称,几乎支持各种字符,包知unicode字符。
//注意1>加转义字符的\0空 \\反斜杠 \t水平制表符 \r回车 \n换行 \''双引号 \'单引号
//注意2>单字节unicode标量 \XNN ,nn 是两位十六进制数
两字节的Unicode标量\uNNNN ,nnnn是四位十六进制数字
四字节Unicode标量 \Unnnnnnnnn ,nnnnnnnn是八进制数字
let dollorSign="\u{24}" let blackHeart="\u{2645}" let sparklingHeart="\u{0001F496}"
还有一点有意思是变量或常量的命名名称,几呼支持各种字符,包知unicode字符。
let constvalue = 70 ;let 我爱你中国 = "我要写中国的操作系统" ;println(constvalue) ;println(我爱你中国);
let constvalue = 70 let 我爱你中国 = "我要写中国的操作系统" println(constvalue) println(我爱你中国)
//1>常量和变量 let 和var 类型推断 //2>pritln 打印插值运算 //3简单的数据类型 // 3.1 整数(Integer) Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64, //可以用.max 和min 来取得上下限 // // 3.2 整型 在一个32位平台,UInt的尺寸和UInt32是一样的 //在一个64位平台中UInt 和UInt64是一样的 // 3.3浮点类型 Double 表示64位的浮点数 精确度低于6位十进制数字 //Float 表示32位的浮点数 精确度低于15位十进制数字 // 3.4 字符/字符串类型 Char/String //类型别名 typealias typealias MYINT=Int let mychar:Character="L" //双引号必须是一个字符,两个会报错 print(mychar); let mystr:String="hello" // 3.5布尔类型 // 只有两个值 true false let mybool:Bool=true; let youBoll=false; //3.6字面值 // 3.6.1 整型 let decimalInteger=17//十进制 let binaryInteger=0b0001 //二进制 let OctalInteger=0174567 //八进制 let hexadecimalInteger=0x11 //十六进制 print(decimalInteger) print(binaryInteger) print(OctalInteger) print(hexadecimalInteger) //全是十进制 // 3.6.2浮点类型 let exponentDouble=1.21875e1//科学计数法 //十进制浮点数 let hexadecialDouble=0xC.3p0 //十六进制浮点数 print(exponentDouble) print(hexadecialDouble) // 3.6.3 字符 let char:Character="c" //3.6.4字符串 let something:String="hello world " //注意1>加转义字符的\0 空 \\ 反斜杠 \t 水平制表符 \r 回车 \n换行 \''双引号 \'单引号 //注意2>单字节unicode标量 \XNN ,nn 是两位十六进制数 //两字节的Unicode标量\uNNNN ,nnnn是四位十六进制数字 //四字节Unicode标量 \Unnnnnnnnn ,nnnnnnnn是八进制数字 let dollorSign="\u{24}" let blackHeart="\u{2645}" let sparklingHeart="\u{0001F496}" print(dollorSign) print(blackHeart) print(sparklingHeart) print("Hello, World!") //3.6.5 bool字面值 let bol=false;
3.字符串串接及类型转换
//1.种类 ,常量字符串let ,和变量字符串var //2初始化为空的字符串 // 1> "" let emptyStr = "" print(emptyStr) //打印然而什么都没有 // 2>String() let emptyString = String() print(emptyString) //打印然而都没有 // 3使用现成的字符串初始化 let string = "hello" let newString=string; //4计算字符串中字符个数(淘汰) //print("string的个数为\(count(string))")// (淘汰) //遍历(淘汰) //for character in string { //print(character) //} //5.字符串和字符的组合 或者字符串和字符串的组合 // + += //6.字符串的判断 string.isEmpty //判空 string.hasPrefix("123") //前缀 string.hasSuffix("1234")//后缀 //判断相等就用 == str1 == str2 //7.大小写转换 string.uppercaseString //所有字符转化大写 string.lowercaseString //所有字符转化小写 //8.Unicode 编码 //Unicode 是针对编码和文本的国际标准,几乎可以显示世界所有的语言 //swift 语言的swift 的字符串完全兼容Unicode ,支持不同的Unicode编码 //在Unicode 每一个字符都可表示一个或者多个Unicode scalars ,一个Unicode scalar 是一个21位数 //包含了UTF-8 ,UTF-16 let str1 = "\u{00000061}" var str2:String = "chicken\u{0001F425}" print(str1) print(str2) for char in str2.utf8 { print(char) } for char in str2.utf16 { print(char) } for scalar in str2.unicodeScalars { print(scalar.value) }
大家可能用OC都有一个想骂人的串接问题,如 在nsstring *a = "hello" 串接 " world",常常使用stringbyappendstring ,或使用stringWithFormat:"%@,%@" 来串接,有没有?而不能使用"+"操作符。真难过,实在难过,特别是对于C/C++,PASCAL,JAVA 甚至更多高级语言都是支持“+”号操作符。唯有OC特别,搞得我一个同事说,想学习一下IOS,但语言太另类了,其实啥语言都大差不差,习惯就好。现在好了,swift来了,他也支持“+”号操作符了。如:
“let label = "The width is "
let width = 94
let widthLabel = label + String(width)”
同时大家也可能发现了,width是整型,在这里被显式的强制类型转换为字符型,这里有个疑问,就是 如果没有进行强制类型转换,这let widthLabel = label + width这样是否可以编译过呢?编译器会不会隐式的进行转换呢,我也好期待,因为没有操作环境,只是在看swift官方学习文档中的,因此留在这里,后续有环境进行验证一下。
接下来说说这个类型转换,咋看又像在抄pascal 或java 的语法, c/c++ 的风格的都是(类型)变量,如(char *) var ,(double) var,而不会写成double(var),oc的写法,与c/C++的很像。没太搞明白为毛,即整合c/c++的,又特地搞个风格别致的,当然,什么都不要紧,习惯就好。对吧,大伙说。
不过swift似呼也嗅到了什么,也提提供了另一种参变量使用"\()" 操作符,其中括号中的还支持表达式操作。至于反斜扛操作嘛,就有点像大家在C/C++ 中的换行串接时,在行尾加上的\的含议差不多。看一下官方给出的例子:
“let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit.”
可能用文字表达不出\()的意思,其实就是参数变量 把上面四句翻译为oc 则为
NSInteger apples = 3;
NSInteger oranges = 5;
NSString *appleSummary = [NSString stringWithFormat:@"I have %d apples",apples];
经试验:
字符串串接我要写中国的操作系统
oc /c/c++都使用typedef 来约束新的类型别名
而swift 则使用typealias
字符串常量可以包括下面这些特殊字符:
空字符\0,反斜杠\,制表符\t,换行符\n,回车符\r,双引号\”和单引号\’
单字节Unicode字符,\xnn,其中nn是两个十六进制数
双字节Unicode字符,\unnnn,其中nnnn是四个十六进制数
四字节Unicode字符,\Unnnnnnnn,其中nnnnnnnn是八个十六进制数
字符串的比较使用 ==
大小写字符串使用uppercaseString 和 lowercaseString
unicode :
Swift 支持多种不同的方式取得Unicode字符串.
你可以使用for-in语句遍历字符串,来获得每一个字符的Unicode编码值。这个过程已经在字符(Working with Characters)描述过了。
或者,下面三个描述中使用合适的一个来获得一个字符串的值
UTF-8字符编码单元集合使用String类型的utf-8属性
UTF-16字符编码单元集合使用String类型的utf-16属性
21位Unicode标量集合使用String类型的unicodeScalars属性
如例子:
4.数组,字典
//1可变的数组和不可变的数组 //2.空数组的初始化 // 1> let a:[Int]=[] // 2 let b:[Int]=[Int]() //3.非空数组的初始化 // 1> let a1:[Int]=[1,2,3] let b1 = [1,2,3,56] // 2>专用语法初始化 var db = [Double](count: 5, repeatedValue: 1.0) print(db) //[1.0, 1.0, 1.0, 1.0, 1.0] // 3>数组初始化数组 var db1 = db //4.数组的操作 // 1>元素的个数 print(db1.count); // 2>判空 print(print(db.isEmpty)) // 3> == 判断是否相同 print(a1==b1) // 4>复制 //var db2 = db.copy(); var strArr:AnyObject = ["12","sdf","sdf"] var strArr1=strArr.copy() // 5追加 // += 或者 append() // 6插入 insert // 7读取值 a[0] 索引 // 8 修改值 // 1> 单个值下表 // 2> 一系列 a[2...5] 必须是一个封闭或者半封闭范围 // 9删除值 // remove // 10遍历数组 // 1>遍历值 for item in db { print(item) }
在swift的书中说,数组和字典都使用“[]”中括符,并可以通过索引或KEY /VALUE的方式存储。见官方例子:
“var shoppingList = ["catfish", "water", "tulips", "blue paint"] //声明一个四元素的数组变量
shoppingList[1] = "bottle of water" //重新将元素2的进行赋值
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations” //动太的添加一个jayne的key值为Public Relations
这个k/V的数组是否长的有点像JOSN啊。反正我看像,还可以动太的添加哦,
创建一个空的数组如: let emptyArray = String[]() //又是中括号又是圆括符的,看得真让人眼花。不过swift中说了,如果不需要指字类型,则数组可以直接使用"[ ]"
进行。如: shoppingList = [] ,字典则使用 “ [ :]” 来设为空字典。
另外字典增加了一个定议模式,有点像C++中的vector 或map之类的,可以指字 k/v的类型吧。见例:
“let emptyDictionary = Dictionary<String, Float>()”
整体感觉上还是比较像C++吧。
//1 空字典的初始化 var dic=Dictionary<Int,Int>() //2初始化非空字典 var dic1=[1:"s",2:"w"] //3 获取元素的个数 print(dic1.count) //4读取键 对应的值 print(dic1[1]) //5添加元素 dic1[3]="t" //添加键为3 值为 "t" 的键值对 //6修改键关联的值 // 1> dic1[3]="你好" print(dic1) // 2> dic1.updateValue("呵呵", forKey:2) print(dic1) //7 删除键 // 1> nil dic1[3]=nil //键为3,的这一键值对删除 // 2>removeAll() 删除所有 // 3>removeValueForKey() //遍历 // 1>遍历值 for dicValue in dic1.values { print(dicValue) } // 2>遍历键 for dickey in dic1.keys { print(dickey) } //遍历键值 for (key,value) in dic1 { print("\(key):\(value)") }
4.枚举类型
枚举在swift中可胃得到了很高的提升。不单单只简单的支持Int数据类型,还扩展了支持其它数据类型,一起来探究一下吧
基本语法:
枚举的关联值支持
Swift的枚举类型可以由一些数据类型相关的组成,如果需要的话,这些数据类型可以是各不相同的。枚举的这种特性跟其它语言中的奇异集合
5表达式。
//1.1 元 //目标数值的个数 //1.2赋值运算符和表达式 let (x,y)=(5,"Hello"); print(x); print(y); //1.3运算和表达式 // + - * / % 基本运算符 ,关于 负号,跟数学表达式是一样的 //关于/ 分母不能是0 var a1=9/4 var a2=9.00/4 print(a1) //表达式中都是整数,结果也是整数 print(a2) //当表达式有一个为浮点数,结果页浮点数 //关于% var b1=9%4 //正数 var b2=(-9)%(-4)//负数 var b3=(-9)%4 //负数 var b4=9%(-4) //正数 print(b1) print(b2) print(b3) print(b4) //注意浮点数取模,也是浮点数(特有) var a=8%2.5 print(a) //1.4自增,自减 ++ -- //1.5一元减运算符 let three = 3 let minusThtree = -three //注意空格 print(minusThtree) //1.6一元加运算 let asloMinusThree = +minusThtree; //只是为了对齐代码,不改变数值 print(asloMinusThree) //1.7位运算 // & // | // ^ 按位异或 相同为0 不同为1 // ~ 按位取反 // << 按二进制全部左移N位 ,右补0 // >> 按二进制右移N位 ,对于无符号位,高位补零 //1.8溢出运算符 &+ &- &* &/ //上溢出 var max=UInt8.max; //255 max = max &+ 1 print(max) //0 &+n ===n-1 //下溢出 var min=UInt8.min; //0 min = min &- 1 print(min) //255 &- n ==255-(n-1) //除 0 溢出(待研究) //1.9 逻辑运算符 && || ! let xx = !(10>7) print(xx) //值只能是true 或者false //1.10 范围运算符 //1. 封闭运算 for index in (1...5) { print(index) } //2.半封闭运算 for index in (1..<5) { print(index) //不包括5 } //1.11 求字节运算符 let size=sizeof(Int) print(size) //1.12 可选类型强制解析 var value:Int?=5 print(value) //可选值 var bb = value! - 9 //强制解析 print(bb) //1.13 类型转换 //swift 不存在隐式转换 //1整数的转换 ,整数有 8种 ,不一样要转换一下 //2 整数和浮点数的转换
if/swicth
“let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}”
teamScore
为什么都不加括号了?对于多个表达式,还是这样长蛇阵么?
另外书中有这一段“In an if statement, the conditional must be a Boolean expression—this means that code such as if score { ... } is an error, not an implicit comparison to zero.”
个人理解是,如果在一个条件语句中,条件值必须是BOOL表达式的,因为非BOOL表达式不会隐式的与0进行比较,这点可能与传统的if有点不同吧。
经验证:多个条件也不需要用括号的。不过,如果你想要表达式正确,还是要按照运算优先级。
再来看一下switch,这个总算有点点进步了,以前的switch大多只支持int或枚举类型,现在swift中把switch语句的表达式判断类型上进行了扩展。其次,每个case不再需要写break;这点不错。
“let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)?"
default:
let vegetableComment = "Everything tastes good in soup."
}”
哈哈,看到没有,没有break哦。。。冒似少了几个B的代码。
switch语句的case中可以匹配一个数值范围
思考:如果没有defalut:会是什么样的?有环境验证一下。
验证后有几个有意思的地方:
一,对成员具有完整性检测:如:
如果switch的条件声明在同一个函数内,这时会提示Switch condition evaluates to a constant
要去除这个,只需要将声明的变量放在函数外就可以
var directionToHead : CompassPoint = .West
6.程序控制结构
//1.选择结构 if / if else 语句 if(1)在swift是不对的 //2.选择结构 switch 语句 // 1> 不用break ,匹配到,自动跳出swith,剩余不会执行 // 2>可执行的语句不能为空 // //let grade = "B" //switch (grade) { // //case "A" : print("A") //case "B" " // //} // 3>多条件匹配 let grade = "B" switch (grade) { case "A,B" : print("A,B") case "B" : print("B") default: print("没找到") } // 4>范围匹配 let score = 45 switch (score) { case 0...60 : print("不及格") default: print("及格") } // 5>使用元组 //case 中可以直接测试元组是否符合相应的条件 let point = (1,1) switch point { case (0,0):print("原点") case (_,0):print("\(point.0),0 在x轴上") case (0,_):print("\(point.1),0 在y轴上") case(-2...2,-2...2):print("(\(point.0),\(point.1)) 在矩形内") default: print("(\(point.0),\(point.1)) 在矩形外") } // 6数值绑定 // 在switch 匹配中 将switch中的值给某个变量,也可以是常量 // 1> let mypoint = (2,2) switch mypoint { case (let x,0):print(" 在x轴上,并且x的值为\(x)") case (0,let y):print(" 在y轴上,并且x的值为\(y)") case(let x,let y):print(" 在其他地方,并且x的值为\(x)并且y的值为\(y)") } let mypoint1 = (2,2) switch mypoint1 { case (var x,0):print(" 在x轴上,并且x的值为\(x)") case (0,var y):print(" 在y轴上,并且x的值为\(y)") case(var x,var y):print(" 在其他地方,并且x的值为\(x)并且y的值为\(y)") } // 2>满足多个条件(淘汰) let mypoint2=(2,0) switch mypoint2 { case let(x,y):print(" 在其他地方,并且x的值为\(x)并且y的值为\(y)") case (let x,0):print(" 在x轴上,并且x的值为\(x)") case (0,let y):print(" 在y轴上,并且x的值为\(y)") } // 7使用where 关键字 //使用where 增加判断条件 let mypoint3=(2,2) switch mypoint3 { case let(x,y) where x==y: print(" 在斜线x==y上,并且x的值为\(x)并且y的值为\(y)") case let(x,y) where x == -y: print(" 在斜线x==-y上,并且x的值为\(x)并且y的值为\(y)") case let (x,y): print(" 这是任意的点") } //3 循环结构 for 语句 //for in // 1>for 后面的是常量 ,而非变量 // 2>省略常量 var value = 1 var sum = 0 for _ in (1...100) { sum += value value++ } print(sum) //4.循环结构while //5.跳转结构 continue ,break ,fallthought // fallthrought 只能在case 下面 let grade1 = "A" switch grade1 { case "A": print("90--100") fallthrough case "B": print("80--90") //fallthrough case "C": print("70--80") // fallthrough case "D": print("60--70") fallthrough default: print("<< 60") }
for - in,for, while, do-while
在for-in 中使用k/v数组,
“let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"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
}
}
}
largest”
这个让我感慨的就是每个变量都没有进行显式的声明类型。这也许就是swift所宣存的精确,高效的一个原因之一吧。
另外for 也像pascal一样支持“..”范围操作符。可能熟释DELPHI的朋友一定很深的印象。像这样的for
procedure foroperation
var
char c;
begin
for (c in ['a'..'z']) do
begin
//do something.
end;
end;
官网的例子:
“var firstForLoop = 0
for i in 0..3 {
firstForLoop += i
}
firstForLoop
var secondForLoop = 0
for var i = 0; i < 3; ++i {
secondForLoop += 1
}
secondForLoop”
两个for 过程是一样的,即i都是从0-3. 其实delphi 中还有low() to high()操作的,这个swift应该没有吧,如果有的话,我想apple的工程师都应经历了pascal的时代。
值得注意的是:swift中不仅有".." 也有"...",分别代表什么呢。两个点,相当于小于如0..3 等价于 0<=i<3 而使用...则相等于 "<=" 如 0..3 等价于 0<=i<=3
while / do while
“var n = 2
while n < 100 {
n = n * 2
}
n
var m = 2
do {
m = m * 2
} while m < 100
m”
7.函数的语法
//牢记几个标准的函数 //1>绝对值函数abs() 返回值为一个正数或者0 可以获取 -10,10,0,-1.233,1.233的绝对值 //2>最大值函数max()/最小值函数min() 可以数值,也可以字符串或者字符 ,如果是字符串,则是比较字符串的首字符, 如果是字符,则三个数都是字符进行比较,否则会出现错误 //3>序列的最大值函数 maxElenment()/最小值函数 minElement(),可以是数值,也可以范围(范围) //let seq=[1,34,45,77,34] //maxElement(seq) //maxElement(1...100) //4>判断序列是否包含指定元素函数contains() // contains(序列,元素) var seq=["swift","hello","world"] if seq.contains("swift") { //比较的时候,会区分大小写 print("包含") } //5.序列排序函数 sort() print("排列前:\(seq)") seq.sortInPlace(); print("排列后:\(seq)") //6序列倒序函数 reverse() for i in seq.reverse() { print(i) } //1无参函数 func printA() { print("A") } printA(); //在swift 中一定要声明之前,调用在后 //2有参函数 // func funcName(参数1:数据类型,参数二:数据类型)->返回值 func nameString(Name:String) { } //注意1>参数的个数,和调用传的个数相同 // 2>顺序 // //3函数参数的特殊情况 // 3.1>本地参数 func func1(start:Int,end:Int,str:String) { //start ,end ,str为本地参数 } // 3.2,外部参数 func joinFunc1(startInt start:Int,endInt end:Int,toString str:String) { } //startInt,endInt ,toString 为外部参数 // 注意1>调用必须用外部参数 // 2>顺序 // 3 快速书写 #(淘汰) //func joinFunc2(#start:Int,#end:Int,#toSting:String) { // // //} // 3.3 设定内部参数的默认值 func joinFunc2(start:Int=0, end:Int,str:String="默认值") { } //无参默认,传值,可以覆盖掉默认值 // 3.4将外部参数设置为默认值 func joinString(sting s1:String,toString s2:String="swift",withSting s3:String="---") { print("\(s1)\(s3)\(s2)") } joinString(sting: "hello") // 3.5可变参数 //使一个参数能接受0个或多个指定类型的参数 ... func average(numbers:Double...) { var total:Double=0 for number in numbers { total += number } print(total) } // 注意1>在一个函数中可变参数只能有一个 // 2> 多个参数中,可变参数只能排在末尾 average(1,2,4,5) average(34,45) // 3.6 常量参数和变量参数 // 函数中,默认参数都是常量 //要想在使用中修改参数的值 加var 了 func hhh (var name:String){ name="lichungui" print(name) } hhh("sdfg") // 3.7输入输出参数inout 可改变参数的值 func test(inout number:Int) { number=100 } var a:Int=0; test(&a) print(a) //神奇 100 //4.函数的返回值 // 1>一个返回值 func range(start:Int,end:Int)->Int { return end-start } // 2>多个返回值(元组) func count(sting:String)->(vowels:Int,consonants:Int,others:Int) { var vowels=0,consonants=0, others=0 return(vowels,consonants,others) } // 3,无返回值 //5.函数类型 //1>使用函数类型 func add(a:Int,b:Int)->Int { return a+b } var mathFuc :(Int,Int)->Int=add; var mathFuntion=add;//类型推断 print(mathFuc(1,5)) // 2>使用函数类型作为参数 (淘汰) //func mutiply(a:Int,b:Int)->Int { // // return a*b //} // //func printResult(fuc:(Int:Int)->Int,a:Int,b:Int) { // // print(fuc(a,b)) //} // //printResult(add, a: 3, b: 2) //printResult(mutiply(100, b: 200) ) // 3>使用函数类型作为返回值类型 //6闭包类型 OC block lambda // 1>闭包表达式 // {(参数列表)-> 返回值 in // 语句 // } // 2>无参 var str={ () in print("aaa") } str() // 3>有参 var str1={ (str:String) in print(str) } str1("asdfgh") // 4注意事项 // 1>推断类型 // 2>省略 return // 3简写参数名(淘汰) //var array=[1,2,3,45,5] // //var v1=compare(array,500, { // $0 > $1 //} //) // 4>trailing 闭包 let digitNames = [ 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine" ] let numbers = [16, 58, 510] let strings = numbers.map { (var number) -> String in var output = ""; while number > 0 { output = digitNames[number % 10]! + output number /= 10 } return output } print(strings) // 打印出来的结果: [OneSix, FiveEight, FiveOneZero] /** * PS: 1.在这个例子中, strings 常量被推断为字符串类型数组,即 [String], map 在数组中为每一个元素调用了闭包表达式, 您不需要指定闭包的输入参数 number 的类型,因为可以通过要映射的数组类型进行推断, 闭包表达式在每次被调用的时候创建了一个字符串并返回。其使用求余运算符 (number %10) 计算最后一位数字并利用 digitNames 字典获取所映射的字符串. 2.字典 digitNames 下标后跟着一个叹号 (!), 因为字典下标返回一个可选值 (optional value), 表明即使该 key 不存在也不会查找失败, 在上例中, 它保证了 number % 10 可以总是作为一个 digitNames 字典的有效下标 key, 因此叹号可以用于强展开 (force-unwrap) 存储在可选下标项中的 String 类型值. */ //捕获 /** * 在我们使用闭包的时候, 其实我们还可以捕获我们自己定义的常量或者变量, 即使里面的常量和变量的作用域不存在, 闭包仍然可以在闭包函数体内引用或者修改, Swift 最简单的闭包形式是嵌套函数,也就是定义在其他函数体内的函数, 嵌套函数可以捕 获其外部函数所有的参数以及定义的常量和变量, 让我们一起来看看: */ func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementBySeven = makeIncrementor(forIncrement: 7) let aaa = incrementBySeven() print(aaa) // 打印出来的结果: 7 /** * 1.makeIncrementor 返回类型为 () -> Int, 这意味着其返回的是一个函数,而不是一个简单类型值, 该函数在每次调用时不接受参数只返回一个 Int 类型的值, 关于函数返回其他函 数的内容,请查看 Function Types as Return Types. 2.makeIncrementor 函数定义了一个整型变量 runningTotal (初始为 0) 用来存储当前增加总数, 该值通过 incrementor 返回. 3.makeIncrementor 有一个 Int 类型的参数, 其外部命名为 forIncrement, 内部命名为 amount, 表示每次 incrementor 被调用时 runningTotal 将要增加的量. 4.incrementor 函数用来执行实际的增加操作, 该函数简单地使 runningTotal 增加 amount, 并将其返回. 5.Swift 会决定捕获引用还是拷贝值, 您不需要标注 amount 或者 runningTotal 来声明在嵌入的 incrementor 函数中的使用方式, Swift 同时也处理 runingTotal 变量的内存管理操作, 如果不再被 incrementor 函数使用, 则会被清除. */ let incrementBySeven1 = makeIncrementor(forIncrement: 7) let a3 = incrementBySeven1() let b3 = incrementBySeven1() let c3 = incrementBySeven1() print("\(a3), \(b3), \(c3)") // 打印出来的结果: 7, 14, 21 //上面已经很好的解释了, 这里我就不多做解释了, 还有一个注意点, 比如: let incrementBySeven2 = makeIncrementor(forIncrement: 7) let a4 = incrementBySeven2() let b4 = incrementBySeven2() let c4 = incrementBySeven2() print("\(a4), \(b4), \(c4)") // 打印出来的结果: 7, 14, 21 let incrementByTen = makeIncrementor(forIncrement: 10) let A5 = incrementByTen() let B5 = incrementByTen() let C5 = incrementByTen() print("\(A5), \(B5), \(C5)") // 打印出来的结果: 10, 20, 30 //虽然这两个常量调用的是同一个闭包, 但是它们之间所捕获的内容并没有关联, 这个需要注意.
“func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")”
通过这个例子,可以看到使用func关键词进行声明,其次 输入参数 使用“变量:类型”的型式,这还真像pascal,你还别说。最有特色的就是这个返回值,参过->符号指定返回的类型。这个也许是C++的地址函问符的一个使用方式吧,每个函数返回的其实都是一个地址块。另外函数如果有多个返回(即传出参数)怎么处理呢?如C/C++ 的使用“**”指针的指针 如 func(char ** outstring) 但在 swift中则:
“func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
getGasPrices()”
其次swift中的函数参数为数组时的写法,也很特别:
“func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(42, 597, 12)”
内连函数的支持
很多高级语方中都有内连函数,内连函数的使用也是很常见的一种,不仅使得代码执行更加高效,同时也减少了内存碎片。
一起看一下swift的内连函数的写法:
“func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()”
还有一个特另的:就是swift还提供了在函数中返回函数来看一下,写法也比较另类:
“func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer() //increment 可理解为addOne的函数指针
increment(7)”
把这段代码解读一下,首先红色部分是一个函数,入参为整型,返回一个整型的值。 再来看最外层的函数makeIncrementer 没有入参,有返回值,而返回值是使用"()"括起来。
int ->int 这个表示返回的为一个函数地址,该函数有一个int型的输入参数,同时还有一个int 型的返回值参数。这与c/c++的函数指很是有差别。
在swift中,函数也可以作为参数进行传递:(见红色部分)
“func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)”
最后还有三个没有理解透,等有ios 8 的环境再验证,好像是匿名函数的使用。
“numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})”
“numbers.map({ number in 3 * number })”
“sort([1, 5, 3, 12, 2]) { $0 > $1 }”